javaweb应用程序开发中文件包含的方法
Servlet 3.0 之前,应用程Java Web 里做文件包含基本只有一条路:用 RequestDispatcher.include()。序开这玩意儿到今天也没过时,发中法只是文件很多人一上来就奔着 Spring 的标签去了,反而把底层的包含机制搞模糊了。
先看最原始的应用程写法。你有一个 header.jsp,序开里面写了导航栏和用户信息,发中法另一个页面 index.jsp 想复用它。文件在 Servlet 里可以这样:
RequestDispatcher rd = request.getRequestDispatcher("/header.jsp"); rd.include(request,包含 response); 注意是 include 不是 forward。forward 会把响应控制权完全交出去,应用程后面的序开代码不再执行;include 是把目标资源的输出插入到当前响应流里,当前 Servlet 继续往下走。发中法这个区别在实际项目里很关键。文件比如你在过滤器中记录日志,包含用 include 才能保证日志代码在页面渲染后仍然执行。
JSP 层面就更常见了。两种指令:<%@ include file="header.jsp" %> 和 <jsp:include page="header.jsp" />。名字看着像,行为差别不小。
前者是静态包含,发生在翻译阶段。容器把 header.jsp 的源码直接拼到当前 JSP 里,合成一个 Servlet 再编译。变量可以直接共享,因为本质上就是一个文件。后者是动态包含,发生在请求处理阶段,当前 JSP 和目标 JSP 各自编译成独立的 Servlet,运行时才把目标的输出合并进来。变量作用域是分开的。
我见过一个项目,页面里用静态包含引入了一个定义 int count = 0; 的片段,结果包含它的三个 JSP 全部编译报错——变量重复定义。换成 <jsp:include> 就没事了。选哪种,取决于你要不要共享变量、被包含文件是否经常变动。静态包含效率高一点,但耦合也重。
到了 Spring MVC 时代,JSP 本身用得少了,但文件包含的需求没消失,只是换了形式。<jsp:include> 在 JSP 视图里照样能用。如果项目用了 Thymeleaf,对应的是 th:replace 和 th:insert。Thymeleaf 的片段表达式更灵活,可以传参数:
<div th:replace="~{ fragments/header :: nav(active='home')}"></div> 被包含的片段里用 th:param 或者片段签名接收参数。这比 JSP 时代的 <jsp:param> 干净不少。
还有一种容易被忽略的情况:在 Servlet 中通过 ServletContext.getResource() 或 getResourceAsStream() 读取文件内容,然后手动写入响应。这不是标准的“包含”,但在需要把静态 HTML 片段嵌入动态页面时有人这么干。问题是路径处理容易出错,而且绕过了容器的请求分发机制,过滤器可能不生效。不推荐,除非你有非常特殊的理由。
文件包含在安全上有个老生常谈的坑:动态包含的路径如果来自用户输入,就可能被利用做本地文件包含甚至远程文件包含。JSP 的 <jsp:include page="${ param.page}" /> 这种写法,攻击者传一个 ?page=../../WEB-INF/web.xml,虽然 JSP 容器一般会限制在 Web 应用目录内,但信息泄露的风险依然存在。参数化路径、白名单校验,这些手段该用就得用。
实际开发中还有个细节:被包含的页面里如果写了 <html>、<head>、<body> 这些标签,包含进来之后页面结构会乱。所以做片段复用的文件,通常只保留内容片段,完整的页面骨架由主页面负责。这个约定看起来简单,但团队里新人多了,总有人往片段里塞完整 HTML,然后样式就莫名其妙地崩了。
选哪种包含方式,我的判断标准很简单:需要共享 Java 变量、片段极少变动,用静态包含;需要运行时决定包含哪个文件、或者片段需要独立编译,用动态包含;模板引擎项目就用引擎自己的片段机制。别为了“统一”硬套一种方案,场景不同,工具就该不同。
(责任编辑:娱乐)
- ·核能行业质保监查员培训班
- ·支付宝漏洞事件
- ·小刀资源网站
- ·支付宝充值码网点
- ·漏洞泄密
- ·资阳反渗透
- ·网站路由
- ·怎么查询网站
- ·小迪推流助手v103
- ·sql网站














