【问题标题】:When do (jsp) scriptlets run their (Java) code?(jsp) scriptlet 何时运行它们的 (Java) 代码?
【发布时间】:2015-12-05 22:02:38
【问题描述】:

我正在处理如下代码的空指针异常:

<%
SessionData session = getSessionData(request);
Webpage webPage = null;
if (session!= null) {
    webPage = session.getWebPage();
}
%>

<script type="text/javascript"> 

//NullPointer happens here, webPage is null when the session is lost
<tags:ComboBox
    comboBox="<%=webPage.getComboBox()%>" />

</script>

当我可以将 if (session!=null 的结尾移到 javascript 之后时,我感到很惊讶,当会话为空时,它似乎忽略了该代码。

<%
SessionData session = getSessionData(request);
Webpage webPage = null;
if (session!= null) {
    webPage = session.getWebPage();
//} move this to below
%>

<script type="text/javascript"> 

//NullPointer happens here, webPage is null when the session is lost
<tags:ComboBox
    comboBox="<%=webPage.getComboBox()%>" />

</script>
<% } %> //moved to here

括号内的ComboBox 标签的scriptlet 是否不再运行?我认为它仍然会尝试将组合框从网页上移开,但最终仍会得到一个空指针。我是否认为 scriptlet 在代码实际运行之前都获得了它们的值是不正确的?

(我只是想提一下,如果没有会话,有一个包含的脚本会重定向页面。我得到一个带有第一部分代码的 NullPointer,并正确重定向到第二部分)

【问题讨论】:

    标签: java jsp scriptlet


    【解决方案1】:

    一个 JSP 被 servlet 容器即时编译成一个 servlet。

    这种编译实际上是一种简单的反转:

    TEXT1
    <% java code %>
    TEXT2
    <%= java expression %>
    TEXT3
    

    编译为:

    out.print("TEXT1");
    java code
    out.print("TEXT2");
    out.print(java expression);
    out.print("TEXT3");
    

    所以当你说:

    TEXT1
    <% if (true) { %>
    TEXT2
    <% } %>
    TEXT3
    

    你得到:

    out.print("TEXT1");
    if (true) {
    out.print("TEXT2");
    }
    out.print("TEXT3");
    

    为了清楚起见,上面的例子被缩小了,例如换行被忽略,样板 servlet 设置不包括在内,标签库执行的复杂性也没有涉及。

    【讨论】:

      【解决方案2】:

      简而言之,您对标签库和scriptlet的处理顺序不正确; JSP 编译器首先识别 JSP 指令,然后解析并呈现标记库输出,然后将不在 scriptlet 中的所有内容转换为写入页面的一堆静态字符串,然后将生成的 Java 文件围绕现有的 scriptlet 代码缝合在一起,寻找一些东西像这样:

      // start of class and _jspService method declaration omitted for brevity
      
          out.write("<html>\n");
          out.write("\t<head>\n");
          out.write("\t<title>Example Static HTML</title>\n");
      
      // comment inside a scriptlet block
      int x = request.getParameter("x");
      pageContext.setParameter("x", x);
      
          out.write("\t</head>\n");
      

      这里的问题源于标签库首先被解析的事实,隔离和评估它们的代码既不关心脚本块也不关心 DOM。在您的情况下,&lt;tags:ComboBox&gt; 标记只是认为 scriptlet 是常规字符串。

      您应该做的是将您的 scriptlet 中的值暴露给标签库使用的可访问范围;以 JSTL 为例,您需要通过 pageContext.setAttribute("varName", value) 将其添加到页面上下文中。

      查看this answer了解更多详情。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-05
        • 2019-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-03
        • 1970-01-01
        相关资源
        最近更新 更多