先来看一道题,猜猜它的输出:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<% int x=5; %>
<%! int x=7; %>
<%! int getX(){return x;}%>
<%=x%><br/>
<%=getX()%>
</body>
</html>
结果是:
jsp在编译后会被解析成java文件,比如这个test.jsp
就会被解析成test_jsp.java
,我把关键代码贴出来就一目了然了:
public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
int x=7;
int getX(){return x;}
/*忽略与这个例子无关的代码*/
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
/*忽略与这个例子无关的代码*/
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>Title</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
int x=5;
out.write('\r');
out.write('\n');
out.write('\r');
out.write('\n');
out.write('\r');
out.write('\n');
out.print(x);
out.write("<br/>\r\n");
out.print(getX());
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
/*忽略与这个例子无关的代码*/
}
}
可以看到,值为7
的x
和getX()
方法都属于test_jsp
类的 成员变量/方法,而值为5
的x
则是_jspService
方法的一个临时变量
<%=x%>
和<%=getX()%>
都是在_jspService
中进行输出,因此这里的x
为临时变量x(5)
,而类方法getX()
输出的就当然是类变量x(7)
了
总结
<%%>
和<%!%>
都是JSP的声明脚本,但是由于JSP编译后的页面内容都会写入对应的Java文件的_jspService()
(类似于Servlet
的service()
)方法中,所以<%%>
中声明的变量是_jspService()
的临时变量,而<%!%>
中声明的变量是Java类的成员变量。因此方法必须写入<%!%>
中,因为方法中不能再次定义方法。而输出/调用语句都是在_jspService()
方法中,因此输出的变量是取就近原则,调用的方法则是正常调用。
即
<%%>
的变量优先输出<%!%>
的方法只会涉及<%!%>
中的变量,与<%%>
没有任何关系