Skip to content

JSP 底层编译原理与三大指令详解

本文探讨 JSP (Java Server Pages) 的诞生背景、Tomcat 容器下的底层翻译编译运行原理、3 大脚本元素以及 3 大核心指令。

1. JSP 的诞生背景与优势

在早期 Java Web 开发中,由于只有 Servlet 能够输出动态网页,开发者不得不写大量繁琐的代码:

java
// 纯 Servlet 渲染 HTML 极度痛苦
PrintWriter out = response.getWriter();
out.print("<html><head><title>Home</title></head>");
out.print("body><h1 class='title'>" + username + "</h1></body></html>");

这种模式代码极其臃肿,前端美工无法介入调试样式。

为解决此痛点,SUN 公司推出了 JSP (Java Server Pages)——允许在标准 HTML 页面中嵌入 Java 代码,极大降低了动态网页的开发难度。


2. JSP 的底层编译原理

核心结论JSP 的本质就是一个 Servlet!

JSP 页面不能直接由浏览器解析,它必须经过 Tomcat 容器的翻译与编译过程:

[ 用户访问 index.jsp ]

[ 1. 翻译阶段 (Translation) ] ──→ Tomcat 检查并把 index.jsp 翻译成 `index_jsp.java` 源文件
        ↓                          (存放于 tomcat/work/ 目录下)
[ 2. 编译阶段 (Compilation) ] ──→ 将 `index_jsp.java` 编译成 `index_jsp.class` 字节码文件

[ 3. 运行服务阶段 (Execution) ]──→ Tomcat 加载 class 并调用 `_jspService()` 方法向客户端输出 HTML

底层继承关系

查看编译产生的 .java 文件可以发现,生成的类继承自 org.apache.jasper.runtime.HttpJspBase,而 HttpJspBase 本质上就是继承了 HttpServlet

java
// Tomcat 生成的 index_jsp.java 代码片段
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase {
    public void _jspService(final HttpServletRequest request, 
                            final HttpServletResponse response) {
        // ...
        out.write("<html><head><title>Home</title></head>...");
    }
}

3. JSP 的 3 大脚本元素

在 JSP 页面中,可以通过以下 3 种脚本标签嵌入 Java 逻辑:

脚本元素格式名称作用与翻译结果使用规范
<%! 代码 %>JSP 声明脚本翻译在 Java 类的成员变量成员方法位置慎用!声明的变量是全局共享的,存在线程安全问题
<%= 代码 %>JSP 表达式翻译为 out.print(代码),直接将表达式结果输出到页面尾部决不能加分号 ;
<% 代码 %>JSP 脚本片段翻译在 _jspService() 方法的局部变量/代码块位置可在其中编写普通 Java 流程控制(if/for/try-catch)

示例代码:

html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
    <%-- 1. JSP 表达式输出 --%>
    <h1>欢迎您,<%= request.getAttribute("username") %></h1>

    <%-- 2. JSP 脚本片段控制逻辑 --%>
    <%
        List<String> list = (List<String>) request.getAttribute("items");
        if (list != null) {
            for (String item : list) {
    %>
                <p>项目:<%= item %></p>
    <%
            }
        }
    %>
</body>
</html>

4. JSP 的 3 大核心指令

JSP 指令用以设置整个 JSP 页面的属性、引入导包以及包含外部文件。语法格式为:<%@ 指令名 属性="值" %>

4.1 Page 指令(最常用)

定义 JSP 页面的全局属性(如字符集编码、导入 Java 包、错误页指定):

html
<%@ page language="java" 
         contentType="text/html; charset=UTF-8" 
         pageEncoding="UTF-8" 
         import="java.util.*, java.text.SimpleDateFormat" 
         errorPage="error.jsp" %>

4.2 Include 指令(静态包含)

在翻译阶段将另外一个 JSP 或 HTML 页面的代码直接合并进来,统一编译为一个 .java 文件:

html
<!-- 静态包含:适合包含公共页头 (header.jsp) 或页脚 (footer.jsp) -->
<%@ include file="header.jsp" %>

4.3 Taglib 指令(标签库引入)

用以引入第三方标签库(如 JSTL 标签库、Spring 标签库):

html
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

基于 VitePress 构建 | 技术知识库