当属性无效时,我可以在自定义 JSP 标记中使用 JSTL 引发异常吗?

Posted

技术标签:

【中文标题】当属性无效时,我可以在自定义 JSP 标记中使用 JSTL 引发异常吗?【英文标题】:Can I throw exception with JSTL in a custom JSP tag when an attribute is invalid? 【发布时间】:2012-02-09 09:06:56 【问题描述】:

我正在制作一些 JSP 标记。我将类型参数传递给标签。

代码如下:

<%@ attribute name="type" require="true" %>
<c:choose>
    <c:when test="$type eq 'even'">
        <c:set var="remainder" value="0" />
    </c:when>
    <c:when test="$type eq 'odd'">
        <c:set var="remainder" value="1" />
    </c:when>
    <c:otherwise>
        <%-- Want to throw exception!! --%>
    </c:otherwise>
</c:choose>

如果我传递了错误的值,我想抛出一个异常。当我搜索这个主题时,我发现了this。我不能在 JSTL 中抛出一个正常的异常吗?

【问题讨论】:

我不认为你真的需要在用户界面中抛出异常。只需将错误描述放在 else 块中即可。 谁会捕捉到这个异常? 只要扔就马上注意到问题 【参考方案1】:

我决定恢复和编辑看起来部分正确的a deleted answer。

您可以通过将其添加到 scriptlet 中来引发异常,如下所示:

<c:choose>
    <c:when test="$type eq 'even'">
        <c:set var="remainder" value="0" />
    </c:when>
    <c:when test="$type eq 'odd'">
        <c:set var="remainder" value="1" />
    </c:when>
    <c:otherwise>
        <% if (true) throw new Exception("Wrong type"); %>
    </c:otherwise>
</c:choose>

但是,您的 jsps 应该是“视图”层的一部分,因此您应该真正尝试将逻辑(包括抛出异常)保留在 servlet 中。

注意if (true) 语句。这是一个技巧,因为如果您只是将异常脚本放入您的代码中,编译器会抱怨“无法访问的代码”。

【讨论】:

【参考方案2】:

只要扔就马上注意到问题

谁会“注意到”?该异常只能被容器捕获,它会导致一些“500 Internal Server Error”页面(或您定义的一些自定义错误页面)。

如果这是你真正想要的,你可以定义一个自定义标签来执行“抛出新的 WhatException()”,然后使用你的自定义标签库,如:&lt;mytaglib:reportError/&gt;,因为标准核心标签库没有考虑任何人都希望抛出异常。

【讨论】:

【参考方案3】:

我只会使用自定义的 EL 函数或标签,系统地抛出异常,或显示带有错误消息的大红色 div,或两者兼而有之

$myFn:illegalState("the type must be odd or even but it is " $type)

【讨论】:

【参考方案4】:

我假设您的目标是告知开发人员他们对您的自定义标签的不当使用。正如其他答案中提到的那样,您可能希望以不同的方式处理用户输入错误,因为在 JSP 中引发错误可能(取决于配置)最终会将用户发送到应用程序错误页面。

如果您能够使用 Java 编写标签处理程序,则该规范在 TLD 中包含几个可选元素,可以做到这一点。

    规范定义了validator 元素,该元素采用实现javax.servlet.jsp.tagext.TagLibraryValidator 的类。实际上,这使用起来有些复杂,因为它提供了很多灵活性。 规范还定义了tei-class,它采用扩展TagExtraInfo 的类。正如 JavaDoc 所指出的:

    自定义标签的额外标签信息;这个类在 标记库描述符文件 (TLD)。必须使用这个类:

    如果标签定义了任何脚本变量 如果标签想要提供标签属性的翻译时验证

根据 JSP 版本,您需要重写 isValid()validate() 方法来处理验证开发人员提供的变量。

Apache 标签库使用这些来验证他们的一些标签: (https://github.com/javaee/jstl-api/blob/master/impl/src/main/java/org/apache/taglibs/standard/tei/ImportTEI.java)

    public boolean isValid(TagData us) 
        if (Util.isSpecified(us, VAR) && Util.isSpecified(us, VAR_READER))
            return false;

        return true;
    

或者,如果您使用的是 JSP 2.0,那么实现 validate 会稍微复杂一些,因为它允许返回 ValidationMessage 的数组。 Glassfish 有一个例子:(https://github.com/javaee/glassfish/blob/master/appserver/tests/appserv-tests/devtests/web/jspGetTagLibraryInfos/servlet/taglib/MyTagExtraInfo.java)

    public ValidationMessage[] validate(TagData data) 
        ValidationMessage[] vms = null;
        TagLibraryInfo[] infos =
            getTagInfo().getTagLibrary().getTagLibraryInfos();
        if (infos.length != 1) 
            vms = new ValidationMessage[1];
            vms[0] = new ValidationMessage(null, "Wrong number of tsglibs");
        
        return vms;
    

【讨论】:

以上是关于当属性无效时,我可以在自定义 JSP 标记中使用 JSTL 引发异常吗?的主要内容,如果未能解决你的问题,请参考以下文章

在自定义 Angular 组件中访问 FormControl

Android Google Map API 自定义标记在自定义标记上带来谷歌地图数据

传入null时,JSP标记属性从父范围继承变量?

在自定义 Delphi 组件中实现 Columns.Columns 属性

在自定义控件中,有CheckBox控件,当触发OnCheckedChanged事件时

谷歌地图如何在自定义地点显示我的位置标记?