Servlet 有两个缺点是没法克服的:首先,写在 Servlet 中的全部 HTML 标签必须包含 Java 字符串,这使得处理HTTP响应报文的工做十分繁琐;第二,全部的文本和 HTML 标记是硬编码,致使即便是表现层的微小变化,如改变背景颜色,也须要从新编译。html
JavaServer Pages(JSP)解决了上述两个问题。同时,JSP 不会取代 Servlet,相反,它们具备互补性。
JSP 页面本质上是一个 Servlet。然而,用 JSP 页面开发比使用 Servlet 更容易。首先,没必要编译 JSP 页面;其次,JSP 页面是一个以 jsp 为扩展名的文本文件,可使用任何文本编辑器来编写它们。 java
JSP 不须要添加注解或在部署描述符配置映射 URL。应用程序目录中的每个JSP页面能够直接在浏览器中输入路径页面来访问。添加新的 JSP 界面后,无需重启 Tomcat。apache
JSP页面在JSP容器中运行,一个Servlet容器一般也是JSP容器。例如,Tomcat 就是一个 Servlet/JSP 容器。
当一个 JSP 页面第一次被请求时,Servlet/JSP 容器主要作如下两件事情:浏览器
1. 把 JSP 页面转换到 JSP 页面实现类,该实现类是一个实现 javax.servlet.jsp.JspPage 接口或子接口 javax.servlet.jsp.HttpJspPage 的 Java 类。JspPage 是 javax.servlet.Servlet 的子接口,这使得每个 JSP 页面都是一个 Servlet。该实现类的类名由 Servlet/JSP 容器生成。若是出现转换错误,则相关错误信息将被发送到客户端。
2. 若是转换成功,Servlet/JSP 容器随后编译该 Servlet 类,并装载和实例化该类,像其余正常的 Servlet 同样执行生命周期操做。安全
对于同一个 JSP 页面的后续请求,Servlet/JSP 容器会先检查 JSP 页面是否被修改过。若是是,则该 JSP 页面会被从新转换、编译并执行。若是不是,则执行已经在内存中的 JSP Servlet。
这样一来,一个JSP页面的第一次调用的实际花费总比后来的花费多。session
JSP页面能够包含模板数据和语法元素(如:'<%'元素表示Java代码块的开始)。除语法元素以外的一切都是模板数据。模板数据会原样发送给浏览器。例如,JSP页面中的HTML标记和文字都是模板数据。jsp
在 Tomcat 中,welcome.jsp 页面在第一次请求时被转换成名为 welcome_jsp 的 Servlet。你能够在 Tomcat 工做目录下的子目录中找到生成的 Servlet,该 Servlet 继承自 org.apache.jasper.
runtime.HttpJspBase,这是一个抽象类,它继承自 javax.servlet.http.HttpServlet 并实现了 javax.
servlet.jsp.HttpJspPage。编辑器
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ page import="java.util.Date" %> <%@ page import="java.text.DateFormat" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Date</title> </head> <body> <% DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG); out.println(dateFormat.format(new Date())); %> </body> </html>
JSP支持两种不一样的注释格式:学习
Servlet 容器会传递几个对象给它运行的 Servlet。例如,能够经过 Servlet 的 service 方法获取 HttpServletRequest 和 HttpServletResponse 对象。在 JSP 中,能够经过隐式对象来访问上述对象。编码
pageContext 提供了上下文信息,能够用于获取和设置属性(getAttribute, setAttribute)。属性值可被存储在4个范围之一:页面(JSP),请求(ServletRequest),会话(HttpSession),应用程序(ServletContext)。
public void setAttribute(String name, Object value); // page scope public Object getAttribute(String name); // page scope public void setAttribute(String name, Object value, int scope); public Object getAttribute(String name, int scope);
out 引用了一个 javax.servlet.jsp.JspWriter 对象,这相似于你在调用 HttpServletResponse 的 getWriter 方法时获得 java.io.PrintWriter。能够经过调用它的 print 方法将消息发送到浏览器。
指令指示 JSP 转换器如何把 JSP 页面转换为 Servlet。
<%@ page attribute1="value1" attribute2="value2" ... %>
attributes :
大部分 page 指令能够出如今页面的任何位置,但当 contentType 或 pageEncoding 属性时,必须出如今 Java 代码发送任何内容以前。
page 指令也能够出现屡次,但出现屡次的指令属性必须具备相同的值,import 属性除外,多个包含 import 属性的 page 指令的结果是累加的。
include 指令将其余文件中的内容包含到当前JSP页面。
<%@ include file="url" %>
taglib 指令引入一个自定义标签集合的定义,包括库路径、自定义标签。
<%@ taglib uri="uri" prefix="prefixOfTag" %>
脚本程序是 java 代码块,以"<%"符号开始,以"%>"符号结束。
Today is <% out. print(Calendar.getInstance().getTime()); %>
表达式会被JSP容器执行,并使用隐式对象 out 的打印方法输出结果。表达式以
"<%="开始,并由"%>"结束。表达式无需分号结尾。
Today is <%= Calendar.getInstance().getTime() %>
声明以"<%!"开始,以"%>"结束,声明页面中使用的变量和方法。
<%! public String getTodaysDate() { return new Date().toString(); } %> <!DOCTYPE html> <html> <head><title>Declarations</title></head> <body> Today is <%= getTodaysDate() %> </body> </html>
在 JSP 页面中,一个声明能够出如今任何地方,而且一个页面能够有多个声明。
可使用声明来重写 JSP 页面,实现类的 init 和 destroy 方法。经过声明 jsplnit 方法,来重写 init 方法。经过声明 jspDestroy 方法,来重写 destory 方法。
注意:尽可能不要在 JSP 页面中编写 Java 代码。除非应用程序只包含一个或两个简单的 JSP 页面,而且永远不会增加;不然,你应该采用模型2,它规定 JSP 页面仅用于显示 Java 对象中的值。
动做是第三种类型的语法元素,它们被转换成 Java 代码来执行操做,如访问一个 Java 对象或调用方法。
useBean将建立一个关联 Java 对象的脚本变量。这是早期分离表示层和业务逻辑的努力之一。随着其余技术的发展,如自定义标签和表达语言,如今不多使用useBean方式。
setProperty 动做可对一个 Java 对象设置属性,而 getProperty 则会输出 Java 对象的一个属性。
include 动做用来动态地引入另外一个资源。能够引入另外一个 JSP 页面,也能够引入一个 Servlet 或一个静态的 HTML 页面。
<! DOCTYPE html> <html><head> <title>Include action</title> </head> <body> <jsp:include page="menu.jsp"> <jsp:param name="text" value="How are you?"/> </jsp:include> </body></html>
对于 include 指令,资源引入发生在页面转换时,即当 JSP 容器把页面转换为生成的 Servlet 时。而 include 动做,资源引入发生在请求页面时。所以,使用 include 动做是能够传递参数的,而 include 指令不支持。
forward 动做把当前页面转向到其余资源。
<jsp:forward page="login.jsp"> <jsp:param name="text" value="Please login"/> </jsp:forward>
用于传递参数。能够经过 request.getParameter(String name) 取出参数值。
用于指定插件。
page 指令的 isErrorPage 属性标志一个 JSP 页面是否为错误页面。
page 指令的 errorPage 属性指向错误处理页面。
<%-- errorHandler.jsp --%> <%@ page isErrorPage="true" %> <! DOCTYPE html><html> <head><title>Error</title></head> <body> An error has occurred.<br/> Error message: <% out.print1n(exception. toString()); %> </body></html>
<%@ page errorPage="errorHandler.jsp"%> Deliberately throw an exception <% Integer. parseInt("Throw me"); %>
参考资料:《Spring MVC 学习指南》 Paul Deck 著