1、JSP的由来
在JSP出现之前,为了实现动态网页的效果,服务器端利用 Servlet 的输出流向客户端发送HTML标签以及HTML页面中的内容,但是在多数动态网页中,绝大部分内容是静态的,只有少量内容需要动态实现。但是为了这少量的动态内容,程序猿依然要用Servlet 输出其中所有的静态内容,这就使得整个Servlet 程序代码非常臃肿,导致Servlet 的开发效率非常低下。
为了弥补Servlet 的缺陷,SUN公司在Servlet 的基础上推出了JSP(Java Server Pages)技术作为解决方案。JSP是简化Servlet 编写的一种技术,它由态部分和动态部分两部分组成,静态部分用于写入标准的HTML标签及内容;动态部分就是嵌入的Java代码与JSP动态标签了。通过这种方式,使静态的部分直接使用HTML代码编写,对于动态的内容则使用 JAVA 脚本编写。
对于Servlet 来说,无论动态、静态都用Java代码编写;而JSP则将静态的分出来,全部用HTML写(底层还是使用Java包装);动态的用Java 写。究其本质还是一样的,所以说,JSP的本质就是一种特殊的Servlet 。
2、JSP的语法
JSP = HTML + Java 脚本 + JSP 标签(指令),JSP中三种Java 脚本:
● <%...%>:Java代码片段,用于定义0~N条Java 语句,方法中能够写什么,这里面就能放什么;
● <%= %>:Java 表达式,用于输出一条表达式或变量的结果。 response.getWriter().print() 方法中能够写什么,这里面就能够写什么;
● <%! … %> :声明,用来创建类的成员变量和成员方法,Java 类中能够写什么,这里面就能够写什么,要注意的是,里面的内容不在 _jspService() 方法之内,直接被JSP转化后的类体包含。
3、JSP 原理
前面已经阐述过,JSP的本质实质是一种特殊形式的 Servlet :
● 当用户访问一个JSP页面时,会向 Servlet 容器(这里是Tomcat)发出请求;
● 如果这个JSP页面是第一次被访问或者这个页面被改动过时,服务器会把JSP 编译成 .java文件,当然,这个.java 就是一个servlet类,然后再把 .java 文件编译成.class 文件。因为编译会耗费一定时间,所以页面在第一次被访问或改动后被访问时会花费较长的访问时间;
● 创建该类对象,最后由Servlet 容器调用它的service() 方法;
● 第二次请求同一JSP时,直接调用service() 方法。
4、验证JSP原理
首先,我们来写一个hello.jsp文件:
[java] view plaincopyprint?
1.
2. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
3. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
4.
5. <%
6. String s = request.getHeader("User-Agent");
7. %>
8.
9.
10.
11.
12. My JSP 'a.jsp' starting page
13.
14.
15.
16.
17.
18.
19.
22.
23.
24.
25.
26.
27.
28. 姓名 |
29. 年龄 |
30. 性别 |
31.
32. <%
33. for(int i = 0; i < 10; i++) {
34. %>
35.
36. 张三 |
37. 18 |
38. 男 |
39.
40. <% }%>
41.
42.
43.
44.
45. <%!
46. public void fun1() {
47. System.out.println("hello");
48. }
49.
50. %>
51. <%int a = 10; %>
52.
53. <%a++; %>
54.
55. <%=a %>
56.
57.
58.
59.
60.
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String s = request.getHeader("User-Agent");
%>
My JSP 'a.jsp' starting page
姓名 |
年龄 |
性别 |
<%
for(int i = 0; i < 10; i++) {
%>
张三 |
18 |
男 |
<% }%>
<%!
public void fun1() {
System.out.println("hello");
}
%>
<%int a = 10; %>
<%a++; %>
<%=a %>
然后让我们在tomcat 下找到被编译成的.java 文件,为了节省空间,我把一些解释标记在代码注释中:
[java] view plaincopyprint?
1.
2. /*
3. * Generated by the Jasper component of Apache Tomcat
4. * Version: Apache Tomcat/7.0.42
5. * Generated at: 2015-12-27 10:03:19 UTC
6. * Note: The last modified time of this file was set to
7. * the last modified time of the source file after
8. * generation to assist with modification tracking.
9. */
10. package org.apache.jsp;
11.
12. import javax.servlet.*;
13. import javax.servlet.http.*;
14. import javax.servlet.jsp.*;
15. import java.util.*;
16.
17. public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
18. implements org.apache.jasper.runtime.JspSourceDependent {
19.
20.
21. public void fun1() { //要特别注意,这是在<%! %>中定义的方法,没有被放在service方法中
22. System.out.println("hello");
23. }
24.
25.
26. private static final javax.servlet.jsp.JspFactory _jspxFactory =
27. javax.servlet.jsp.JspFactory.getDefaultFactory();
28.
29. private static java.util.Map _jspx_dependants;
30.
31. private javax.el.ExpressionFactory _el_expressionfactory;
32. private org.apache.tomcat.InstanceManager _jsp_instancemanager;
33.
34. public java.util.Map getDependants() {
35. return _jspx_dependants;
36. }
37.
38. public void _jspInit() {
39. _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
40. _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
41. }
42.
43. public void _jspDestroy() {
44. }
45.
46. public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
47. throws java.io.IOException, javax.servlet.ServletException { //这是_jspService()方法
48.
49. final javax.servlet.jsp.PageContext pageContext; //内置对象的初始化
50. javax.servlet.http.HttpSession session = null;
51. final javax.servlet.ServletContext application;
52. final javax.servlet.ServletConfig config;
53. javax.servlet.jsp.JspWriter out = null;
54. final java.lang.Object page = this;
55. javax.servlet.jsp.JspWriter _jspx_out = null;
56. javax.servlet.jsp.PageContext _jspx_page_context = null;
57.
58.
59. try {
60. response.setContentType("text/html;charset=UTF-8");
61. pageContext = _jspxFactory.getPageContext(this, request, response,
62. null, true, 8192, true);
63. _jspx_page_context = pageContext;
64. application = pageContext.getServletContext();
65. config = pageContext.getServletConfig();
66. session = pageContext.getSession();
67. out = pageContext.getOut();
68. _jspx_out = out;
69.
70. out.write("\r\n");
71. out.write("\r\n");
72. out.write("\r\n");
73.
74. String s = request.getHeader("User-Agent"); //它的原身是String s = request.getHeader("User-Agent");,被直接拿过来了
75.
76.
77. out.write("\r\n");
78. out.write("\r\n");
79. out.write("\r\n");
80. out.write("\r\n"); //这些都是HTML代码,底层被包装成和Servlet 一样的实现方式
81. out.write(" \r\n");
82. out.write(" My JSP 'a.jsp' starting page\r\n");
83. out.write(" \r\n");
84. out.write("\t\r\n");
85. out.write("\t\r\n");
86. out.write("\t \r\n");
87. out.write("\t\r\n");
88. out.write("\t\r\n");
89. out.write("\t\r\n");
92. out.write("\r\n");
93. out.write(" \r\n");
94. out.write(" \r\n");
95. out.write(" \r\n");
96. out.write(" \r\n");
97. out.write("\t\r\n");
98. out.write("\t 姓名 | \r\n");
99. out.write("\t 年龄 | \r\n");
100. out.write("\t 性别 | \r\n");
101. out.write("\t
\r\n");
102.
103. for(int i = 0; i < 10; i++) { //这也是直接拿过来的
104.
105. out.write("\t\r\n");
106. out.write("\t\r\n");
107. out.write("\t 张三 | \r\n");
108. out.write("\t 18 | \r\n");
109. out.write("\t 男 | \r\n");
110. out.write("\t
\r\n");
111. }
112. out.write("\r\n");
113. out.write("
\r\n");
114. out.write("\r\n");
115. out.write("\r\n");
116. out.write("\r\n");
117. out.write('\r');
118. out.write('\n');
119. int a = 10; //这些是定义的变量,可以看到是放在了service方法中的
120. out.write("\r\n");
121. out.write("\r\n");
122. a++;
123. out.write("\r\n");
124. out.write("\r\n");
125. out.print(a );
126. out.write("\r\n");
127. out.write("\r\n");
128. out.write(" \r\n");
129. out.write("\r\n");
130. } catch (java.lang.Throwable t) {
131. if (!(t instanceof javax.servlet.jsp.SkipPageException)){
132. out = _jspx_out;
133. if (out != null && out.getBufferSize() != 0)
134. try { out.clearBuffer(); } catch (java.io.IOException e) {}
135. if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
136. else throw new ServletException(t);
137. }
138. } finally {
139. _jspxFactory.releasePageContext(_jspx_page_context);
140. }
141. }
142. }
143.
144.
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.42
* Generated at: 2015-12-27 10:03:19 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;
public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
public void fun1() { //要特别注意,这是在<%! %>中定义的方法,没有被放在service方法中
System.out.println("hello");
}
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map _jspx_dependants;
private javax.el.ExpressionFactory _el_expressionfactory;
private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map getDependants() {
return _jspx_dependants;
}
public void _jspInit() {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException { //这是_jspService()方法
final javax.servlet.jsp.PageContext pageContext; //内置对象的初始化
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
String s = request.getHeader("User-Agent"); //它的原身是String s = request.getHeader("User-Agent");,被直接拿过来了
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n"); //这些都是HTML代码,底层被包装成和Servlet 一样的实现方式
out.write(" \r\n");
out.write(" My JSP 'a.jsp' starting page\r\n");
out.write(" \r\n");
out.write("\t\r\n");
out.write("\t\r\n");
out.write("\t \r\n");
out.write("\t\r\n");
out.write("\t\r\n");
out.write("\t\r\n");
out.write("\r\n");
out.write(" \r\n");
out.write(" \r\n");
out.write(" \r\n");
out.write(" \r\n");
out.write("\t\r\n");
out.write("\t 姓名 | \r\n");
out.write("\t 年龄 | \r\n");
out.write("\t 性别 | \r\n");
out.write("\t
\r\n");
for(int i = 0; i < 10;