(jsp) scriptlets 什么时候 运行 他们的 (Java) 代码?
When do (jsp) scriptlets run their (Java) code?
我正在处理如下代码的空指针异常:
<%
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,并在第二段代码中正确重定向节)
简而言之,您对标记库和小脚本的处理顺序不正确; 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");
这里的问题源于标记库首先被解析,而隔离和评估它们的代码不关心 scriptlet 块或 DOM。在您的情况下,<tags:ComboBox>
标记只是认为 scriptlet 是一个常规字符串。
您应该做的是将 scriptlet 中的值暴露给标签库使用的可访问范围;例如,对于 JSTL,您需要通过 pageContext.setAttribute("varName", value)
.
将其添加到页面上下文中
查看 this answer 了解更多详情。
A 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 设置,并且不包括标签库执行的复杂性。
我正在处理如下代码的空指针异常:
<%
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,并在第二段代码中正确重定向节)
简而言之,您对标记库和小脚本的处理顺序不正确; 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");
这里的问题源于标记库首先被解析,而隔离和评估它们的代码不关心 scriptlet 块或 DOM。在您的情况下,<tags:ComboBox>
标记只是认为 scriptlet 是一个常规字符串。
您应该做的是将 scriptlet 中的值暴露给标签库使用的可访问范围;例如,对于 JSTL,您需要通过 pageContext.setAttribute("varName", value)
.
查看 this answer 了解更多详情。
A 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 设置,并且不包括标签库执行的复杂性。