1. 概述

JavaServer Pages (JSP) 允许通过 Java 和 Java Servlet 将动态内容注入到静态内容中。我们可以向 Java Servlet 发送请求,执行相关逻辑,然后在服务端渲染特定视图供客户端消费。本文将基于 Java 8 和 Jakarta EE 7 提供对 JSP 的全面解析。

我们将先探讨几个 JSP 核心概念:动态内容与静态内容的区别JSP 生命周期JSP 语法指令以及编译时创建的隐式对象

2. JavaServer Pages

JavaServer Pages (JSP) 使 Java 特定数据能被传入或嵌入 .jsp 视图并在客户端消费。

JSP 文件本质上是 .html 文件,但带有一些额外语法和两个初始差异:

  1. 文件扩展名从 .html 改为 .jsp
  2. 在 HTML 标记顶部添加以下标签:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

下面我们深入 JSP 的几个关键概念。

2.1. JSP 语法

向 .jsp 添加 Java 代码有两种方式。首先是使用基础 Scriptlet 语法,将 Java 代码块放在两个 Scriptlet 标签内:

<% Java code here %>

第二种方式是 XML 特定语法:

<jsp:scriptlet>
    Java code here
</jsp:scriptlet>

✅ 关键技巧:可以通过 JSP 在客户端使用条件逻辑,用 if/then/else 子句包裹相关标记块:

<% if (doodad) {%>
    <div>Doodad!</div>
<% } else { %>
    <p>Hello!</p>
<% } %>

例如,当 doodad 为 true 时显示 div 元素,否则显示 p 元素!

2.2. 静态与动态内容

静态内容 是独立于 RESTful、SOAP、HTTP/HTTPS 请求或用户提交信息消费的固定资源。

动态内容 则会响应用户操作或信息而改变!

JSP 技术实现了静态内容动态内容职责的清晰分离:

  • 服务器(Servlet)管理动态内容
  • 客户端(.jsp 页面)作为静态容器,接收注入的动态内容

下面看看 JSP 创建的隐式对象,它们允许你在服务端访问 JSP 相关数据!

2.3. 隐式对象

隐式对象 由 JSP 引擎在编译时自动生成,包括 HttpRequestHttpResponse 等对象,为 Servlet 和 .jsp 交互提供服务端功能。

以下是创建的隐式对象列表:

request
类型:jakarta.servlet.http.HttpServletRequest
暴露所有用户输入数据供服务端使用。

response
类型:jakarta.servlet.http.HttpServletResponse
决定请求后返回客户端的内容。

⚠️ 重点解析 requestresponse 对象(最常用):

protected void doGet(HttpServletRequest request, 
  HttpServletResponse response) throws ServletException, IOException {
    String message = request.getParameter("message");
    response.setContentType("text/html");
    . . .
}
  1. requestresponse 作为方法参数传入
  2. 通过 getParameter() 获取请求参数(如 message
  3. 通过 response 设置响应类型(如 text/html

out
类型:jakarta.servlet.jsp.JspWriter
用于向客户端写入内容。

两种输出方式对比:

// 方式1:JspWriter(缓冲后写入response)
out.print("hello");
out.println("world");

// 方式2:PrintWriter(直接写入response,性能更优)
PrintWriter out = response.getWriter();
out.println("Hello World");

2.4. 其他隐式对象

session
类型:jakarta.servlet.http.HttpSession
在会话期间维护用户数据。

application
类型:jakarta.servlet.ServletContext
存储应用级参数(初始化设置或全局访问)。

exception
类型:jakarta.servlet.jsp.JspException
在错误页面(需声明 <%@ page isErrorPage="true" %>)显示错误信息。

page
类型:java.lang.Object
访问当前 Servlet 信息。

pageContext
类型:jakarta.servlet.jsp.PageContext
默认页面作用域,可访问 request/application/session 属性。

config
类型:jakarta.servlet.ServletConfig
Servlet 配置对象,获取上下文、名称和配置参数。

2.5. 指令

JSP 提供内置指令指定核心功能,由两部分组成:

  1. 指令本身
  2. 赋值的指令属性

三种指令类型:

<%@ page ... %>    <!-- 定义依赖和属性(如contentType) -->
<%@ include ... %> <!-- 指定导入文件 -->
<%@ taglib ... %>  <!-- 指定标签库 -->

示例(JSP 标签版):

<%@ page attribute="value" %>

XML 版本:

<jsp:directive.page attribute="value" />

2.6. 页面指令属性

以下是常用页面指令属性:

属性 示例 说明
autoFlush <%@ page autoFlush="false" %> 控制缓冲区输出(默认 true)
buffer <%@ page buffer="19kb" %> 设置缓冲区大小(默认 8kb)
errorPage <%@ page errorPage="errHandler.jsp" %> 指定错误处理页面
extends <%@ page extends="org.apache.jasper.runtime.HttpJspBase" %> 指定 Servlet 超类
info <%@ page info="This is my JSP!" %> 设置 JSP 文本描述
isELIgnored <%@ page isELIgnored="true" %> 是否忽略 EL 表达式(默认 false)
isErrorPage <%@ page isErrorPage="true" %> 声明当前为错误页面
isThreadSafe <%@ page isThreadSafe="false" %> 是否启用多线程(默认 true)
language <%@ page language="java" %> 脚本语言(默认 Java)
session <%@ page session="true" %> 是否维护 HTTP 会话
trimDirectiveWhitespaces <%@ page trimDirectiveWhitespaces="true" %> 编译时移除空白(默认 false)

3. 三个实战示例

现在我们通过三个基础示例应用上述概念,帮你快速搭建第一个 JSP 服务!

我们将使用 Java 8 和 Jakarta EE 原生功能,演示三种向 .jsp 注入 Java 的方式:

  1. 服务端渲染标记
  2. 直接在 .jsp 嵌入 Java
  3. 请求转发并绑定数据

3.1. Servlet 渲染 HTML

本示例跳过创建 .jsp 文件!我们在 ExampleOne Servlet 中直接构建 HTML 字符串并通过 PrintWriter 写入响应:

public class ExampleOne extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, 
    HttpServletResponse response) throws ServletException, IOException {
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      out.println(
    "<!DOCTYPE html><html>" +
    "<head>" +
    "<meta charset=\"UTF-8\" />" +
    "<title>HTML Rendered by Servlet</title>" +
    "</head>" +
    "<body>" +
    "<h1>HTML Rendered by Servlet</h1></br>" +
    "<p>This page was rendered by the ExampleOne Servlet!</p>" +
    "</body>" +
    "</html>"
     );
   }
}

💡 这里我们直接通过 Servlet 处理请求并生成 HTML,完全绕过了 JSP!使用 PrintWriter 直接写入 response 对象,比 JspWriter 性能更优(无缓冲层)。

3.2. JSP 静态页面嵌入 Java

创建 ExampleTwo.jsp,通过 JSP 标签直接嵌入 Java 代码。这里随机显示一个问候语:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
    <head>
        <title>Java in Static Page Example</title>
    </head>
    <body>
        <h1>Java in Static Page Example</h1>
        <% 
              String[] arr = {"What's up?", "Hello", "It's a nice day today!"}; 
          String greetings = arr[(int)(Math.random() * arr.length)];    
            %>
        <p><%= greetings %></p>
    </body>
</html>

✅ 关键点:在 JSP 标签内声明变量(String[] arr)并初始化,完全无需依赖 Servlet。JSP 生命周期会自动处理这些 Java 代码。

3.3. 带转发的 JSP

最完整的示例!使用 @WebServlet 注解(省去 web.xml 配置):

@WebServlet(
  name = "ExampleThree",
  description = "JSP Servlet With Annotations",
  urlPatterns = {"/ExampleThree"}
)
public class ExampleThree extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
      String message = request.getParameter("message");
      request.setAttribute("text", message);
      request.getRequestDispatcher("/ExampleThree.jsp").forward(request, response);
   }
}

流程解析:

  1. 获取 URL 参数 message
  2. 将参数绑定到 request 对象(属性名 text
  3. 转发请求到 ExampleThree.jsp

对应的 JSP 文件通过 EL 表达式显示绑定数据:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
    <head>
        <title>Java Binding Example</title>
    </head>
    <body>
        <h1>Bound Value</h1>
        <p>You said: ${text}</p>
    </body>
</html>

⚠️ 注意:这里使用 EL 表达式 ${text} 渲染服务端绑定的数据,实现真正的动态交互!

3.4. 动手试试!

将应用导出为 .war 部署到 Tomcat 8!修改 server.xml 添加 Context:

<Context path="/spring-mvc-xml" docBase="${catalina.home}/webapps/spring-mvc-xml">
</Context>

访问地址:http://localhost:8080/spring-mvc-xml/jsp/index.jsp
完整代码参考:GitHub

4. 总结

我们全面覆盖了 JSP 的核心知识:

  • ✅ JSP 的本质与作用
  • ✅ 静态/动态内容分离
  • ✅ 隐式对象与指令系统
  • ✅ 三种实现方式对比

现在你已经掌握了 JSP 的基础用法,可以开始构建自己的动态 Web 应用了!编码愉快!


原始标题:Guide to JavaServer Pages (JSP) | Baeldung