Servlet调用RequestDispatcher.forward前能否向浏览器发送响应?
问题描述
能否在调用RequestDispatcher的forward方法将请求转发至另一个Servlet之前,先通过当前Servlet向浏览器发送响应?
以下代码中,尝试在forward前通过PrintWriter输出内容但未生效,forward后的代码也不执行,希望明确背后的执行机制:
public class ForwardServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setAttribute("message","This message appended in ForwardServlet"); resp.setContentType("text/html"); PrintWriter pr = resp.getWriter(); pr.println("I m in ForwardServlet"); // 尝试向浏览器响应,但未生效,谁在调用RequestDispatcher的forward方法前阻止了PrintWriter对象? RequestDispatcher rd= req.getRequestDispatcher("Servlet1"); rd.forward(req, resp); pr.println("Comeback to ForwardServlet from Servlet1"); // 不会执行,是因为(1)控制不会回到此处?还是(2)PrintWriter对象被阻止? } }
解答
1. 核心结论:不能在forward前向浏览器发送有效响应
Servlet规范中,forward方法的作用是将请求的完整控制权转移给目标Servlet/JSP,由目标资源负责生成最终的响应返回给浏览器。在调用forward之前,当前Servlet写入的内容只会暂存到响应缓冲区,不会立刻发送到浏览器;而forward执行时,容器会自动清空缓冲区,确保目标资源能输出干净的响应。如果此时响应已经被提交(内容已发送到浏览器),调用forward还会直接抛出IllegalStateException。
2. 代码现象的具体原因
forward前的输出未生效
你通过pr.println()写入的内容并没有直接发送到浏览器,而是存在了HttpServletResponse的缓冲区中。当rd.forward()执行时,Servlet容器会清空这个缓冲区,目的是避免当前Servlet的零散输出破坏目标Servlet生成的完整响应,所以之前的内容被丢弃,浏览器看不到。forward后的代码不执行
forward方法执行后,当前Servlet的代码流程会直接中断,控制权完全移交到目标Servlet(即Servlet1),所以pr.println("Comeback...")这行代码根本不会被执行,和PrintWriter是否被阻止无关。这是Servlet规范规定的forward流程:一旦调用forward,当前Servlet后续的处理逻辑就终止了。
内容的提问来源于stack exchange,提问作者Muzaffar Hussain

