文章目录

  • 1. request.getRequestDispatcher()
    • 1.1请求转发和请求包含的区别
    • 1.2request域
  • 2.response.sendRedirect()
  • 3.请求转发与重定向的区别
    • 比较测试

1. request.getRequestDispatcher()

getRequestDispatcher()包含两个重要方法,分别是请求转发和请求包含。一个请求跨多个Servlet时,需要使用请求转发和请求包含。

首先需要获得一个RequestDispatcher 对象:
RequestDispatcher rd = request.getRequestDispatcher("/MyServlet");
然后

  • 请求转发: rd.forward( request , response );
  • 请求包含: rd.include( request , response);

    需注意的是,无论是请求转发还是请求包含,都在一个请求范围内!使用同一个request和response!

1.1请求转发和请求包含的区别

  • 请求转发:由下一个Servlet完成响应体,当前Servlet可以设置响应头(留头不留体)。
    举个例子,AServlet请求转发到BServlet,那么AServlet不能够使用response.getWriter() 和response.getOutputStream()向客户端输出响应体,但可以使用response.setContentType(“text/html;charset=utf-8”) 设置响应头。而在BServlet中可以输出响应体。
  • 请求包含:由两个Servlet共同完成响应体(留头又留体)。同样用上面的例子,AServlet请求包含到BServlet,那么AServlet既可以设置响应头,也可以完成响应体。

下图是请求转发的流程,最后返给客户端的response只是BServlet的,而AServlet的响应不会在客户端显示出来。

下图是请求包含流程,因为BServelt的响应返回给AServlet时携带了responseB,所以AServlet的响应中包含了BServlet的响应,最后返给客户端的响应是两者之和。

1.2request域

request是Java四大域对象之一,正是它提供了请求转发和请求包含的功能。一个请求会创建一个request对象,若在一个请求中跨越了多个Servlet,那么这些Servlet可以使用request来共享数据。同一个请求范围内使用request.setAttribute()和request.getAttribute()来传值!前一个Servlet调用setAttribute()保存值,后一个Servlet调用getAttribute()获取值

2.response.sendRedirect()

response和request一样都是jsp内置对象,request是获取用户的请求,response处理用户请求。sendRedirect()函数的作用是重定向网页,向浏览器发送一个特殊的Header,然后由浏览器来做重定向,转到指定的页面。下面创建四个页面,首先是sex.jsp,有一个下拉列表和提交按钮确定,选择“男”,就跳转到male.jsp,选择“女”就跳转到female.jsp,中间通过sex_action.jsp进行重定向

<!-- sex.jsp --><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href=""><title>Sex Select's page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"><meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"></head><body>    <form action="c03/sex_action.jsp" method="post">        <select name="sex">            <option></option>            <option></option>        </select>        <button type="submit">提交</button>    </form></body></html>
<!-- sex_action.jsp --><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href=""><title>My JSP 'sex_action.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"><meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"></head><body>    <%         request.setCharacterEncoding("UTF-8");        String sex = request.getParameter("sex");        out.println(sex);        if("男".equals(sex)) {            response.sendRedirect("male.jsp");            return;        }        else if("女".equals(sex)) {            response.sendRedirect("female.jsp");            return;        }    %></body></html>

3.请求转发与重定向的区别

  1. 请求转发是一个请求一次响应,而重定向是两次请求两次响应。
  2. 请求转发地址不变化,而重定向会显示后一个请求的地址。这是因为请求转发服务器的行为,是由容器控制的转向,整个过程处于同一个请求中,因此客户端浏览器不会显示转向后的地址;但重定向客户端的行为,重新发送了请求,整个过程不在同一个请求中,因此客户端浏览器会显示跳转后的地址。
  3. 请求转发只能转发到本项目其它Servlet,而重定向不只能重定向到本项目的其它Servlet,还能定向到其它项目。
  4. 请求转发是服务端行为,只需给出转发的Servlet路径,而重定向需要给出requestURI,既包含项目名
  5. request.getRequestDispatcher()是请求转发,前后页面共享一个request,返回的是一个RequestDispatcher对象, response.sendRedirect()是重新定向,前后页面不是一个request,
  6. RequestDispatcher.forward()是在服务器端运行,HttpServletResponse.sendRedirect()是通过向客户浏览器发送命令来完成,所以RequestDispatcher.forward()对于浏览器来说是“透明的”,而HttpServletResponse.sendRedirect()则不是
  7. ServletContext.getRequestDispatcher(String url)中的url只能使用绝对路径; 而ServletRequest.getRequestDispatcher(String url)中的url可以使用相对路径。因为ServletRequest具有相对路径的概念;而ServletContext对象无次概念。

请求转发示意图

重定向示意图

比较测试

环境准备:
login.jsp 所在目录: /webapp/ jsp/ login.jsp
servelt /GoHallCI
工程名字: /MyShopping

实际测试:

1、req.getRequestDispatcher(“jsp/login.jsp”).forward(req, resp); 测试结果: 可转发,实际访问地址:http://localhost:8080/MyShopping/GoHallCI?type=login
1、req.getRequestDispatcher(“/jsp/login.jsp”).forward(req, resp); 测试结果:可转发 实际访问地址:http://localhost:8080/MyShopping/GoHallCI?type=login
1、req.getRequestDispatcher(“/login.jsp”).forward(req, resp); 测试结果:不可转发 实际访问地址,找不到
1、req.getRequestDispatcher(“login.jsp”).forward(req, resp); 测试结果:不可转发 实际访问地址 ,找不到
1、req.getRequestDispatcher(req.getContextPath()+“login.jsp”).forward(req, resp); 实际访问地址,找不到 [/MyShoppinglogin.jsp] 未找到
1、req.getRequestDispatcher(req.getContextPath()+“/login.jsp”).forward(req, resp); 实际访问地址,找不到 [/MyShopping/login.jsp] 未找到
1、req.getRequestDispatcher(req.getContextPath()+“jsp/login.jsp”).forward(req, resp); 实际访问地址,找不到 [/MyShoppingjsp/login.jsp] 未找到
1、req.getRequestDispatcher(req.getContextPath()+“/jsp/login.jsp”).forward(req, resp); 实际访问地址,找不到 [/MyShopping/jsp/login.jsp] 未找到
1、req.getRequestDispatcher(req.getContextPath()+“/GoHallCI”).forward(req, resp); 实际访问地址,[找不到 http://localhost:8080/MyShopping/GoHallCI?type=login]
1、req.getRequestDispatcher(“/MyShopping/jsp/login.jsp”).forward(req, resp); 实际访问地址,找不到 文.件[/MyShopping/jsp/login.jsp] 未找到
1、req.getRequestDispatcher(“/GoHallCI”).forward(req, resp); 实际访问地址 http://localhost:8080/MyShopping/GoHallCI?type=login
req.getRequestDispatcher()后面如果还有语句,那么在转发页面,后台仍然会执行对应语句,直到语句执行结束!
2、在jsp里面 登录 , 实际访问地址:http://localhost:8080/MyShopping/jsp/login.jsp
3、resp.sendRedirect(req.getContextPath()+“/hall”); 测试结果 : 可重定向 实际重定向地址:http://localhost:8080/MyShopping/hall
3、resp.sendRedirect(“jsp/login.jsp”); 测试结果: 可重定向,实际访问地址:http://localhost:8080/MyShopping/jsp/login.jsp**
3、resp.sendRedirect(“/jsp/login.jsp”); 测试结果:不可重定向 实际访问地址:http://localhost:8080/jsp/login.jsp
3、resp.sendRedirect(“/login.jsp”); 测试结果:不可重定向 实际访问地址,http://localhost:8080/login.jsp
3、resp.sendRedirect(“login.jsp”); 测试结果:不可重定向 实际访问地址 ,http://localhost:8080/MyShopping/login.jsp
3、resp.sendRedirect(req.getContextPath()+“login.jsp”); 测试结果:不可重定向 实际访问地址,http://localhost:8080/MyShoppinglogin.jsp
3、resp.sendRedirect(req.getContextPath()+“/login.jsp”); 测试结果:不可重定向 实际访问地址,http://localhost:8080/MyShopping/login.jsp
3、resp.sendRedirect(req.getContextPath()+“jsp/login.jsp”); 测试结果:不可重定向 实际访问地址,http://localhost:8080/MyShoppingjsp/login.jsp
3、resp.sendRedirect(req.getContextPath()+“/jsp/login.jsp”); 测试结果:可重定向 实际访问地址 http://localhost:8080/MyShopping/jsp/login.jsp
3、resp.sendRedirect(req.getContextPath()+“/GoHallCI”); 测试结果 :可重定向 实际访问地址,http://localhost:8080/MyShopping/GoHallCI
3、resp.sendRedirect(“/MyShopping/jsp/login.jsp”); 测试结果:可重定向 实际访问地址,http://localhost:8080/MyShopping/jsp/login.jsp
3、resp.sendRedirect(“/GoHallCI”); 测试结果:不可重定向 实际访问地址 http://localhost:8080/GoHallCI

小结:
req.getRequestDispatcher() 的url 只能使用 jsp/login.jsp的相对路径或者/jsp/login.jps的绝对路径访问,支持填写servlet
resp.sendRedirect() 除了支持 jsp/login.jsp的相对路径,还支持自己拼接全路径 req.getContextPath()+”/jsp/login.jsp,也可以自己直接写全,/MyShopping/jsp/login.jsp

参考博文(侵删):
关于request.getRequestDispatcher()的两个方法以及request域
细谈getRequestDispatcher()与sendRedirect()的区别

getRequestDispatcher()与sendRedirect()的区别