一道练习题引发的思考
在一个JSP页面中,有如下代码,请问最终的输出结果为:
1 <%! int i = 1;%> 2 <%! int getNumber(){ 3 return i; 4 }%> 5 <% int i = 10; 6 out.println("first i = "+i);%> 7 <% out.println("second i = "+i);%> 8 <% out.println("third i = "+getNumber());%>
其输出结果为:first i = 10 second i = 10 third i = 1
这道题容易出错的原因是在于分不清在<%! %>声明语句中声明的变量和在<% %>小脚本中声明的变量的区别,它们两个区别具体如下:JSP声明语句中声明的变量在生成Servlet后位于类的成员变量部分,属于全局变量;而JSP脚本段声明的变量在生成Servlet后位于service方法中,属于局部变量,当方法运行完后就被销毁了。Servlet是一个单实例对象,成员变量只有一个,每个用户都可访问到它,所以会污染全局变量,在多用户访问时,也不利于维护数据的正确性和安全性。
其实 我们可以从jsp生成的.java文件看出区别,从源代码可以看出这个jsp页面程序到底是怎么执行的:
1 package org.apache.jsp; 2 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import javax.servlet.jsp.*; 6 7 public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase 8 implements org.apache.jasper.runtime.JspSourceDependent { 9 //JSP声明语句声明的变量和方法,在全局部分 10 int i = 1; 11 int getNumber(){ 12 return i; 13 } 14 private static final javax.servlet.jsp.JspFactory _jspxFactory = 15 javax.servlet.jsp.JspFactory.getDefaultFactory(); 16 17 private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; 18 19 private volatile javax.el.ExpressionFactory _el_expressionfactory; 20 private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; 21 22 public java.util.Map<java.lang.String,java.lang.Long> getDependants() { 23 return _jspx_dependants; 24 } 25 26 public javax.el.ExpressionFactory _jsp_getExpressionFactory() { 27 if (_el_expressionfactory == null) { 28 synchronized (this) { 29 if (_el_expressionfactory == null) { 30 _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); 31 } 32 } 33 } 34 return _el_expressionfactory; 35 } 36 37 public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() { 38 if (_jsp_instancemanager == null) { 39 synchronized (this) { 40 if (_jsp_instancemanager == null) { 41 _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); 42 } 43 } 44 } 45 return _jsp_instancemanager; 46 } 47 48 public void _jspInit() { 49 } 50 51 public void _jspDestroy() { 52 } 53 //JSP页面生成的Service方法,小脚本语句位于这个方法中 54 public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) 55 throws java.io.IOException, javax.servlet.ServletException { 56 57 final javax.servlet.jsp.PageContext pageContext; 58 javax.servlet.http.HttpSession session = null; 59 final javax.servlet.ServletContext application; 60 final javax.servlet.ServletConfig config; 61 javax.servlet.jsp.JspWriter out = null; 62 final java.lang.Object page = this; 63 javax.servlet.jsp.JspWriter _jspx_out = null; 64 javax.servlet.jsp.PageContext _jspx_page_context = null; 65 66 67 try { 68 response.setContentType("text/html;charset=UTF-8"); 69 pageContext = _jspxFactory.getPageContext(this, request, response, 70 null, true, 8192, true); 71 _jspx_page_context = pageContext; 72 application = pageContext.getServletContext(); 73 config = pageContext.getServletConfig(); 74 session = pageContext.getSession(); 75 out = pageContext.getOut(); 76 _jspx_out = out; 77 78 out.write("\r\n"); 79 out.write("\r\n"); 80 out.write("<html>\r\n"); 81 out.write("<head>\r\n"); 82 out.write(" <title>test</title>\r\n"); 83 out.write("</head>\r\n"); 84 out.write("<body>\r\n"); 85 out.write(" "); 86 out.write("\r\n"); 87 out.write(" "); 88 out.write("\r\n"); 89 out.write(" "); 90 //JSP小脚本中声明的变量 91 int i = 10; 92 //JSP小脚本中的语句 93 out.println("first i = "+i); 94 out.write("\r\n"); 95 out.write(" "); 96 //JSP小脚本中的语句 97 out.println("second i = "+i); 98 out.write("\r\n"); 99 out.write(" "); 100 //JSP小脚本中的语句 101 out.println("third i = "+getNumber()); 102 out.write("\r\n"); 103 out.write("</body>\r\n"); 104 out.write("</html>\r\n"); 105 } catch (java.lang.Throwable t) { 106 if (!(t instanceof javax.servlet.jsp.SkipPageException)){ 107 out = _jspx_out; 108 if (out != null && out.getBufferSize() != 0) 109 try { 110 if (response.isCommitted()) { 111 out.flush(); 112 } else { 113 out.clearBuffer(); 114 } 115 } catch (java.io.IOException e) {} 116 if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); 117 else throw new ServletException(t); 118 } 119 } finally { 120 _jspxFactory.releasePageContext(_jspx_page_context); 121 } 122 } 123 }