请求转发和包含
请求转发和请求包含都表示由多个Servlet共同处理一个请求。例如,客户端请求服务器的AServlet,而AServlet处理不了当前的请求,就转发或包含给BServlet,由BServlet处理或共同处理该请求。具体如图1-1所示:
图1-1 请求转发和请求包含原理图
由图1-1可知,请求转发和请求包含都是一次请求中,那么服务器只会创建一个request对象和一个response对象,因此AServlet的request和response与BServlet中的request和response是同一个request和response。我们知道request对象是一个域对象,既然AServlet和BServlet的request对象是同一个,那么就可以在AServlet中向request域中存放数据,然后在BServlet中从request域中获取。这就是request域的域范围,在一个请求链中。
- 请求转发
请求转发是Servlet将请求转发给别的Servlet或服务器其他资源,无需客户端任何行为。可以通过以下方式实现请求转发:
request.getRequestDispatcher(“转发资源路径”).forward(request,response)
- getRequestDispatcher(String path):该方法的返回值类型是RequestDispatcher,可以理解它是一个调度器,该方法的参数是指明要转发或包含的资源路径;
- forward(ServletRequest req,ServletResponse res):该方法是RequestDispatcher接口的方法,将请求从一个 servlet 转发到服务器上的另一个资源(servlet、JSP 文件或 HTML 文件)。此方法允许一个 servlet 对请求进行初步处理,并使另一个资源生成响应。需要传递两个参数,这两个参数是当前Servlet的request对象和response对象传递过去的。
通过下图形象理解请求转发,如图1-2所示:
图1-2 请求转发
图1-2满足java_ee_api文档对forward()方法的定义,客户端请求AServlet,而最终是由BServlet做出响应。
- 请求包含
请求包含是指多个Servlet共同处理一个请求。以下方式可以实现请求包含:
request.getRequestDispatcher(“包含资源路径”).include(request,response)
- include(ServletRequest request,ServletResponse response):该方法是RequestDispatcher接口的方法,表示包含。它的参数同forward()方法的参数一样都是由当前Servlet传递过去的。
通过下图来形象理解请求包含,如图1-3所示:
图1-3 请求包含
- 请求转发和请求包含的比较
(1)相同点
请求转发和请求包含都是在一个请求范围内,多个Servlet之间使用的同一个request对象和response对象。
(2)不同点
- 如果在AServlet中请求转发到BServlet,那么在AServlet中不允许再输出响应体,即不能使用response.getWriter()和response.getOutputStream()向客户端输出,这一工作交由BServlet来完成;如果是由AServlet请求包含BServlet,则没有这个限制。
- 请求转发不能设置响应体,但是可以设置响应头,简单来说就是“留头不留体”,例如:
response.setContentType("text/html;charset=utf-8”);
而请求包含不仅可以设置响应头,还可以设置响应体,简单来说就是“留头又留体“;
- 请求包含大多应用在jsp页面中,完成多页面的合并;
- 请求转发大多应用在Servlet中,转发目标大多是jsp页面。