Request Dispatcher 的 forward () 和 include () 有什么区别?
RequestDispatcher(请求调度器)是 Servlet/JSP 中用于在服务器内部转发 / 包含资源的核心接口,forward()(转发)和include()(包含)是其两个核心方法,本质都是服务器内部操作(客户端无感知),但执行逻辑、响应处理、使用场景差异显著:
核心区别对比表:
| 维度 | forward ()(请求转发) | include ()(请求包含) |
|---|---|---|
| 执行逻辑 | 将请求完全移交到目标资源,当前资源停止输出; | 执行目标资源并获取其输出,再回到当前资源继续输出; |
| 响应控制权 | 目标资源完全接管响应(当前资源的输出会被忽略); | 当前资源保留响应控制权,目标资源的输出嵌入当前响应; |
| 输出内容 | 仅目标资源的输出发送到客户端; | 当前资源 + 目标资源的输出合并后发送到客户端; |
| 调用时机 | 需在当前资源未输出任何内容前调用(否则抛异常); | 可在当前资源任意位置调用(即使已有输出); |
| 响应状态码 / 头信息 | 由目标资源设置(当前资源的设置会被覆盖); | 由当前资源设置(目标资源的设置会被忽略); |
| 适用场景 | 业务逻辑跳转(如登录成功跳转到首页); | 页面组件复用(如包含页眉、页脚、公共导航); |
| 等价 JSP 标签 | <jsp:forward>; |
<jsp:include>; |
具体行为说明:
(1)forward ()(请求转发)
执行流程:
- 客户端发送请求到 A.jsp/Servlet;
- A 调用
forward(),服务器将请求对象(request)、响应对象(response)传递给 B.jsp/Servlet; - A 停止所有输出,B 完全处理请求并生成响应;
- 服务器将 B 的响应返回给客户端(地址栏仍显示 A 的 URL)。
关键限制:调用
forward()前,当前资源不能有任何内容输出到客户端(包括空白字符、HTML 标签),否则会抛出IllegalStateException(响应已提交)。示例:
1
2
3// Servlet中调用forward
RequestDispatcher rd = request.getRequestDispatcher("/index.jsp");
rd.forward(request, response);
(2)include ()(请求包含)
执行流程:
- 客户端发送请求到 A.jsp/Servlet;
- A 执行到
include()时,服务器将请求 / 响应传递给 B.jsp/Servlet,执行 B 并获取其输出; - B 的输出嵌入到 A 的响应中,A 继续执行剩余逻辑;
- 服务器将 A+B 的合并响应返回给客户端。
关键特点:即使 A 已有输出,
include()仍可正常执行;B 的响应头会被忽略,仅保留输出内容。示例:
1
2
3
4
5// JSP中通过脚本调用include(等价于<jsp:include>)
<%
RequestDispatcher rd = request.getRequestDispatcher("/footer.jsp");
rd.include(request, response);
%>
核心总结:
forward()是 “跳转”:目标资源替代当前资源,仅返回目标的响应;include()是 “嵌入”:目标资源的内容嵌入当前资源,返回合并的响应;- 两者均共享同一个
request对象(可传递请求参数 / 属性),但forward()更侧重逻辑跳转,include()更侧重页面组件复用。



