Java 您能使JSP在未声明的变量上崩溃吗?

Java 您能使JSP在未声明的变量上崩溃吗?,java,jsp,Java,Jsp,我们注意到JSP中未声明的变量可能会导致非常糟糕的性能 查看以下示例代码: <c:if test="..."> <c:set var="isSaleCategory" value="true"/> </c:if> <c:forEach items="${ARTICLES}" var="article" varStatus="status"> <c:if test="${not empty articlePrice &

我们注意到JSP中未声明的变量可能会导致非常糟糕的性能

查看以下示例代码:

<c:if test="...">
    <c:set var="isSaleCategory" value="true"/>
</c:if>

<c:forEach items="${ARTICLES}" var="article" varStatus="status">
    <c:if test="${not empty articlePrice && (!isSaleCategory)}">

代码处理和返回结果花费了5-6秒

如果我们首先初始化变量,执行时间将下降到几毫秒:

<c:set var="isSaleCategory" value="false"/>

<c:if test="...">
    <c:set var="isSaleCategory" value="true"/>
</c:if>

<c:forEach items="${ARTICLES}" var="article" varStatus="status">
    <c:if test="${not empty articlePrice && (!isSaleCategory)}">

现在,我们不介意添加这些代码来初始化变量,但棘手的部分是找到它们。。。在没有循环的页面上,我们不会看到第二次+响应时间,但在重载情况下,这当然会增加不必要的负载


当JSP遇到上述未初始化的变量时,有没有办法使其处理失败?

当访问未声明的变量时,它的速度很慢的问题是,解析程序会深入挖掘以尝试找到变量

尝试大量未声明的变量时会抛出许多ClassNotFoundException,这需要花费大量时间

解决这个问题的一种方法是编写一个自定义ELResolver,如果在页面范围中找不到值为null的变量,它只需将该变量作为已解析变量,这样就可以防止框架进一步挖掘

private static class NullOnMissingVariableELResolver extends ELResolver
{
    /** {@inhericDoc} */
    @Override
    public Object getValue(ELContext context, Object base, Object property) 
    {
        if (base == null && property != null) 
        {
            String key = property.toString();
            PageContext page = (PageContext) context.getContext(JspContext.class);
            Object result = page.findAttribute(key);

            if (result == null)
            {
                context.setPropertyResolved(true);
            }
        }

        return null;
    }

当然,这需要注意,如果您有使用这些特殊类查找的模板,它们将无法工作

我发现了关于这个问题的更多信息,它似乎出现在Tomcat 8中:

另一种解决方案是在变量前面加上作用域,而不是:

${isSaleCategory}
使用


虽然这意味着对jsp文件进行了大量更改,但是Marcus与客户ELResolver的回答很好地发现了这些情况。

没有NPE吗?看起来更像是第二次测试中的错误处理,其中由于第一次测试失败而无法设置
isSaleContegory
。如果您想在第二个测试中添加NullPointer检查作为OR条件,该怎么办?
(isSaleCategory为null | | |!isSaleCategory)
您的文章集有多大?似乎奇怪的是,变量强制应该如此昂贵。@Antoniossss JSP非常宽容(这是本例中的核心问题),对于这些场景,不要抛出任何异常。很好的建议!在开发模式下,我们可以将ELResolver设置为引发异常并修复未设置的变量。找到了根本原因:
${requestScope.isSaleCategory}