JSP <jsp:include> 教程

<jsp:include> 是 JSP 中一个非常重要的动作标签,用于在请求处理阶段动态地将一个资源的输出包含到当前 JSP 页面中。

jsp include 教程
(图片来源网络,侵删)

什么是 <jsp:include>

想象一下,你正在制作一个网站,很多页面都有共同的头部(header.jsp)和底部(footer.jsp),为了代码复用,你不会在每个页面都把头部和底部的 HTML 代码复制一遍,这时,你就可以使用 <jsp:include> 来“引入”这些公共部分。

它的核心特点是:动态包含


语法

<jsp:include> 标签有两种主要形式:

标准语法(最常用)

<jsp:include page="relativeURL" flush="true" />

或者

jsp include 教程
(图片来源网络,侵删)
<jsp:include page="relativeURL" flush="true">
    <!-- 可以传递参数 -->
    <jsp:param name="paramName" value="paramValue" />
</jsp:include>

参数说明:

  • page (必需): 一个相对路径,指向你想要包含的 JSP、HTML 或其他任何 web 资源,这个路径是相对于当前 JSP 文件的。
  • flush (可选): 布尔值。
    • true: 在包含新资源之前,刷新当前 JSP 页面的输出缓冲区,这是 JSP 2.0 规范之后推荐的做法,可以避免一些问题。
    • false: 不刷新缓冲区(默认值,但不推荐)。
    • 注意:根据 JSP 规范,flush 属性必须设置为 true,虽然一些旧服务器可能允许 false,但为了代码的健壮性和可移植性,请始终使用 flush="true"

工作原理(动态包含 vs. 静态包含)

理解 <jsp:include> 的工作原理是掌握它的关键。

动态包含

<jsp:include> 是在请求处理时执行的。

  1. 客户端请求 main.jsp
  2. JSP 容器(如 Tomcat)开始处理 main.jsp
  3. 当处理到 <jsp:include page="header.jsp" /> 这一行时,容器会暂停main.jsp 的处理。
  4. 容器会去请求并处理 header.jsp
  5. header.jsp输出结果(HTML 代码)被捕获。
  6. 将捕获的 HTML 结果插入main.jsp<jsp:include> 标签所在的位置。
  7. 容器恢复对 main.jsp 剩余代码的处理。

核心思想:包含的是执行后的结果,而不是源代码。

静态包含(<%@ include %>

为了更好地理解动态包含,我们来看看它的“兄弟”——静态包含。

jsp include 教程
(图片来源网络,侵删)

静态包含的语法:

<%@ include file="relativeURL" %>
  • 工作原理:静态包含发生在翻译阶段(JSP 文件被转换为 Java Servlet 的阶段)。
  • 过程:JSP 容器在编译 main.jsp 之前,会将 header.jsp源代码直接“复制粘贴”到 main.jsp<%@ include %> 标签位置,然后作为一个大的 Servlet 进行编译。
  • 结果:最终只有一个 Servlet 文件被生成和执行。

传递参数

<jsp:include> 的一个强大功能是可以在包含页面时传递参数,这就像在调用一个函数时传入参数一样。

示例:

main.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>主页</title>
</head>
<body>
    <h1>欢迎访问我的网站!</h1>
    <!-- 包含导航栏,并传递当前页面参数 -->
    <jsp:include page="navigation.jsp" flush="true">
        <jsp:param name="currentPage" value="home" />
    </jsp:include>
    <p>这里是主页的主要内容。</p>
    <!-- 包含页脚 -->
    <jsp:include page="footer.jsp" flush="true" />
</body>
</html>

navigation.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<nav>
    <ul>
        <li><a href="index.jsp">首页</a></li>
        <li><a href="about.jsp">关于我们</a></li>
        <li><a href="contact.jsp">联系我们</a></li>
    </ul>
    <hr>
    <!-- 接收并显示参数 -->
    <p>您当前正在查看: <strong>${param.currentPage}</strong></p>
</nav>

说明:

  • main.jsp 中,我们使用 <jsp:param> 标签定义了一个名为 currentPage,值为 "home" 的参数。
  • navigation.jsp 中,我们使用 EL 表达式 ${param.currentPage} 来获取这个参数的值。param 是一个内置的 Map 对象,专门用于接收通过 <jsp:param> 传递的参数。

完整实例

让我们创建一个简单的网站结构来演示。

文件结构

webapp/
├── index.jsp
├── header.jsp
├── footer.jsp
└── common/
    └── navigation.jsp

代码实现

header.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<header>
    <h1>我的酷炫网站</h1>
</header>

footer.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<footer>
    <hr>
    <p>&copy; 2025 我的酷炫网站. 保留所有权利.</p>
</footer>

common/navigation.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<nav>
    <a href="index.jsp">首页</a> |
    <a href="about.jsp">lt;/a> |
    <a href="contact.jsp">联系</a>
</nav>

index.jsp (主页面)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>首页 - 我的酷炫网站</title>
</head>
<body>
    <!-- 1. 包含头部 -->
    <jsp:include page="header.jsp" flush="true" />
    <!-- 2. 包含导航栏 -->
    <jsp:include page="common/navigation.jsp" flush="true" />
    <!-- 3. 页面主体内容 -->
    <main>
        <h2>欢迎来到首页!</h2>
        <p>这是首页的主要内容区域。</p>
    </main>
    <!-- 4. 包含底部 -->
    <jsp:include page="footer.jsp" flush="true" />
</body>
</html>

当你访问 index.jsp 时,你会看到完整的页面,其头部、导航、主体和底部都是通过 <jsp:include> 动态组合起来的。


<jsp:include> vs. <%@ include %> (重要对比)

特性 <jsp:include> (动态包含) <%@ include %> (静态包含)
执行阶段 请求处理时 (Runtime) 翻译时 (Translation Time)
包含目标页面的输出结果 (HTML) 包含目标页面的源代码
编译结果 每个被包含的文件独立编译成 Servlet,通过 RequestDispatcher 组合。 所有文件合并成一个 Servlet 进行编译。
变量共享 不能直接共享变量,每个页面有自己的作用域。 可以直接共享变量,因为代码被合并,所以变量名不能冲突。
适用场景 动态变化,或者需要传递参数。 包含静态、固定不变的模板片段,如头部、底部。
性能 理论上稍慢,因为涉及多个请求/响应的转发。 理论上稍快,因为只编译一次。
灵活性 ,可以传递参数,可以包含任何能响应请求的资源。 ,只能包含文件,不能传递参数。

如何选择?

  • 使用 <jsp:include> 当你:

    • 需要向被包含页面传递参数。
    • 被包含页面的内容会根据请求(如用户登录状态、语言等)而改变。
    • 你希望每个模块(JSP)都是独立的,便于维护。
  • 使用 <%@ include %> 当你:

    • 包含的是纯粹的静态模板,内容永远不会变。
    • 你希望所有代码在一个 Servlet 中,可能会有微小的性能优势。
    • 你需要在不同页面间共享一些变量(不推荐这种做法,耦合性太高)。

最佳实践

  1. 优先使用 <jsp:include>:在现代 Web 开发中,由于 <jsp:include> 的灵活性和低耦合性,它通常是更好的选择。
  2. 始终设置 flush="true":遵循 JSP 规范,避免潜在问题。
  3. 用于布局模板:将网站的头部、导航栏、页脚等公共部分用 <jsp:include> 组合,实现页面布局。
  4. 注意路径page 属性是相对于当前 JSP 文件的路径,使用相对路径可以增强项目的可移植性。

<jsp:include> 是 JSP 中实现页面模块化和代码复用的核心工具,通过动态包含的方式,它允许你在运行时灵活地组合不同的页面片段,并支持参数传递,极大地提高了开发效率和代码的可维护性,理解它与静态包含 <%@ include %> 的区别,是成为一名合格 JSP 开发者的关键一步。