- 内容提要
- 作者简介
- 译者简介
- 前言
- HTTP
- Servlet 和 JSP
- 下载 Spring 或使用 STS 与 Maven/Gradle
- 手动下载 Spring
- 使用 STS 和 Maven/Gradle
- 下载 Spring 源码
- 本书内容简介
- 下载示例应用
- 第 1 章Spring 框架
- 第 2 章模型 2 和 MVC 模式
- 第 3 章Spring MVC 介绍
- 第 4 章基于注解的控制器
- 第 5 章数据绑定和表单标签库
- 第 6 章转换器和格式化
- 第 7 章验证器
- 第 8 章表达式语言
- 第 9 章JSTL
- 第 10 章国际化
- 第 11 章上传文件
- 第 12 章下载文件
- 第 13 章应用测试
- 附录 A Tomcat
- 附录 B Spring Tool Suite 和 Maven
- 附录 C Servlet
- 附录 D JavaServer Pages
- 附录 E 部署描述符
D.1 JSP 概述
JSP 页面本质上是一个 Servlet。然而,用 JSP 页面开发比使用 Servlet 更容易,主要有两个原因。首先,不必编译 JSP 页面;其次,JSP 页面是一个以 jsp 为扩展名的文本文件,可以使用任何文本编辑器来编写它们。
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 页面的第一次调用的实际花费总比后来的花费多,因为它涉及转换和编译。为了解决这个问题,可以执行下列动作之一:
配置应用程序,使所有的 JSP 页面在应用程序启动时被调用(实际上也可视为转换和编译),而不是在第一次请求时调用。
预编译 JSP 页面,并将其部署为 Servlet。
JSP 自带的 API 包含 4 个包:
javax.servlet.jsp。包含 Servlet/JSP 容器用于将 JSP 页面转换为 Servlet 的核心类和接口。其中的两个重要成员是 JspPage 和 HttpJspPage 接口。所有的 JSP 页面实现类必须实现 JspPage 或 HttpJspPage 接口。在 HTTP 环境下,实现 HttpJspPage 接口是显而易见的选择。
javax.servlet.jsp.tagext。包括用于开发自定义标签的类型。
javax.el。提供了统一表达式语言的 API。
javax.servlet.jsp.el。提供了一组必须由 Servlet/JSP 容器支持以便在 JSP 页面中使用表达式语言的类。
除了 javax.servlet.jsp.tagext,我们很少直接使用 JSP API。事实上,编写 JSP 页面时,我们更关心 Servlet API,而非 JSP API。当然,我们还需要掌握 JSP 语法,本附录后续会进一步说明。JSP API 在开发 JSP 容器或 JSP 编译器时被广泛使用。
可以在以下网址查看 JSP API:
https://docs.oracle.com/javaee/7/api/javax/servlet/jsp/ package-summary.html
JSP 页面可以包含模板数据和语法元素。这里,语法元素是一些具有特殊意义的 JSP 转换符。例如,“<%”是一个元素,因为它表示在 JSP 页面中的 Java 代码块的开始。“%>”也是一个元素,因为它是 Java 代码块的结束符。除语法元素之外的一切都是模板数据。模板数据会原样发送给浏览器。例如,JSP 页面中的 HTML 标记和文字都是模板数据。
清单 D.1 给出一个名为 welcome.jsp 的 JSP 页面。它是发送一个客户问候的简单页面。注意,同 Servlet 相比,JSP 页面是如何更简单地完成同样的事情的。
清单 D.1 welcome.jsp
<!DOCTYPE html>
<html>
<head><title>Welcome</title></head>
<body>
Welcome
</body>
</html>
在 Tomcat 中,welcome.jsp 页面在第一次请求时被转换成名为 welcome_jsp 的 Servlet。你可以在 Tomcat 工作目录下的子目录中找到生成的 Servlet,该 Servlet 继承自 org.apache.jasper. runtime.HttpJspBase,这是一个抽象类,它继承自 javax.servlet.http.HttpServlet 并实现了 javax. servlet.jsp.HttpJspPage。
下面是为 welcome.jsp 生成的 Servlet。如果觉得不好理解,可以先跳过它。当然,能够理解它更好。
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class welcome_jsp extends
org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long>
_jspx_dependants;
private javax.el.ExpressionFactory _el_expressionfactory;
private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long>
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 {
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");
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("<html>\n");
out.write("<head><title>Welcome</title></head>\n");
out.write("<body>\n");
out.write("Welcome\n");
out.write("</body>\n");
out.write("</html>");
} catch (java.lang.Throwable t) {
if (!(t instanceof
javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
out.clearBuffer();
} catch (java.io.IOException e) {
}
if (_jspx_page_context != null)
_jspx_page_context.handlePageException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
正如我们在上面的代码中看到的,JSP 页面的主体是_jspService 方法。这个方法被定义在 HttpJspPage 中,并被 HttpJspBase 的 service 方法调用。下面的代码来自 HttpJspBase 类。
public final void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
_jspService(request, response);
}
要覆盖 init 和 destroy 方法,可以参见 D.5。
一个 JSP 页面不同于一个 Servlet 的另一个方面是,前者不需要添加注解或在部署描述符配置映射 URL。应用程序目录中的每一个 JSP 页面可以直接在浏览器中输入路径页面来访问。图 D.1 给出了 D1 应用程序的目录结构
图 D.1 D1 应用程序的目录结构
D1 应用程序的结构非常简单,由一个空的 WEB-INF 目录和 welcome.jsp 页面构成。
可以通过如下 URL 访问 welcome.jsp 页面。
http://localhost:8080/jspdemo/welcome.jsp
注意
添加新的 JSP 界面后,无需重启 Tomcat。
清单 D.2 展示了如何在 JSP 页面中使用 Java 代码来生成动态页面。清单 D.2 中的 todaysDate.jsp 页面显示了今天的日期。
清单 D.2 todaysDate.jsp 页面
<%@page import="java.util.Date"%>
<%@page import="java.text.DateFormat"%>
<!DOCTYPE html>
<html>
<head><title>Today's date</title></head>
<body>
<%
DateFormat dateFormat =
DateFormat.getDateInstance(DateFormat.LONG);
String s = dateFormat.format(new Date());
out.println("Today is " + s);
%>
</body>
</html>
todaysDate.jsp 页面将几个 HTML 标签和字符串“今天是”以及今天的日期发送到浏览器。
请注意两件事情。首先,Java 代码可以出现在 JSP 页面中的任何位置,并通过“<%”和“%>”包括起来。其次,可以使用 page 指令的 import 属性导入在 JSP 页面中使用的 Java 类型,如果没有导入的类型,必须在代码中写出 Java 类的全路径名称。
<%...%>块称为 scriplet,并在 D.5 部分进一步讨论。page 将在 C.4 部分详细讨论。
现在可以通过如下 URL 访问 todaysDate.jsp 页面。
http://localhost:8080/jspdemo/todaysDate.jsp
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论