返回介绍

D.1 JSP 概述

发布于 2025-04-22 20:10:07 字数 7030 浏览 0 评论 0 收藏 0

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 应用程序的目录结构

图片 9

图 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。