getRequestDispatcher()转发和sendRedirect()重定向介绍与比较
文章目录
- 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="<%=basePath%>">
<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="<%=basePath%>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="<%=basePath%>">
<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.请求转发与重定向的区别
- 请求转发是一个请求一次响应,而重定向是两次请求两次响应。
- 请求转发地址不变化,而重定向会显示后一个请求的地址。这是因为请求转发是服务器的行为,是由容器控制的转向,整个过程处于同一个请求中,因此客户端浏览器不会显示转向后的地址;但重定向是客户端的行为,重新发送了请求,整个过程不在同一个请求中,因此客户端浏览器会显示跳转后的地址。
- 请求转发只能转发到本项目其它Servlet,而重定向不只能重定向到本项目的其它Servlet,还能定向到其它项目。
- 请求转发是服务端行为,只需给出转发的Servlet路径,而重定向需要给出requestURI,既包含项目名
- request.getRequestDispatcher()是请求转发,前后页面共享一个request,返回的是一个RequestDispatcher对象, response.sendRedirect()是重新定向,前后页面不是一个request,
- RequestDispatcher.forward()是在服务器端运行,HttpServletResponse.sendRedirect()是通过向客户浏览器发送命令来完成,所以RequestDispatcher.forward()对于浏览器来说是“透明的”,而HttpServletResponse.sendRedirect()则不是
- 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里面 <a href=“${pageContext.request.contextPath}/jsp/login.jsp” .>登录</a.> , 实际访问地址: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()的区别