一、概述
-
请求转发和响应重定向是web应用中间接访问项目资源(html、js、css、图片、servlet)的两种手段,也是Servlet控制页面跳转的两种手段
-
请求转发通过HttpServletRequest实现,响应重定向通过HttpServletResponse实现
-
请求转发生活举例:张三找李四借钱,李四没有,李四找王五,让王五借给张三。此时张三只知道找了李四,但是张三并不知道李四找了王五,张三只知道自己找了李四后自己银行卡里多了钱,但是这个钱其实是王五给它的。
-
响应重定向生活举例:张三找李四借钱,李四没有,李四让张三去找王五,张三自己再去找王五借钱
二、请求转发
1)请求转发运行逻辑图
2)请求转发特点(背诵)
- 请求转发通过HttpServletRequest对象获取请求转发器实现
- 请求转发是服务器内部的行为,对客户端是屏蔽的
- 客户端只发送了一次请求,,因此微服务只产生了一对 request 和 response对象,请求参数可以传递,请求域中的数据也可以传递
- 客户端地址栏不变
- 服务端只产生了一对请求和响应对象,这一对请求和响应对象会继续传递给下一个资源
- 请求转发可以转发给其他Servlet动态资源,也可以转发给一些静态资源以实现页面跳转
- 请求转发可以转发给WEB-INF下受保护的资源,该方式也是WEB-INF下的资源唯一访问方式
- 请求转发不能转发到本项目以外的外部资源
3)请求转发测试代码
ServletA
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求转发器
// 转发给servlet ok,路径填的是相对路径:相对于当前servlet / web目录
RequestDispatcher requestDispatcher = req.getRequestDispatcher("servletB");
// 转发给一个视图资源 ok
RequestDispatcher requestDispatcher = req.getRequestDispatcher("welcome.html");
// 转发给WEB-INF下受保护的资源 ok,但是如果浏览器直接访问WEB-INF下受保护的资源是访问不到的
RequestDispatcher requestDispatcher = req.getRequestDispatcher("WEB-INF/views/view1.html");
// 转发给外部资源 no,请求转发默认是在我们当前项目中去找,就算你这里写成了一个完整的URL,它也会把它当成当前项目内部某个资源路径,而你项目内部没有任何一个资源跟这个路径匹配上,所以就提示你找不到了。
RequestDispatcher requestDispatcher = req.getRequestDispatcher("http://www.atguigu.com");
// 获取请求参数
String username = req.getParameter("username");
System.out.println(username);
// 向请求域中添加数据
req.setAttribute("reqKey","requestMessage");
// 做出转发动作
requestDispatcher.forward(req,resp);
}
}
ServletB
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("username");
System.out.println(username);
// 获取请求域中的数据
String reqMessage = (String)req.getAttribute("reqKey");
System.out.println(reqMessage);
// 做出响应
resp.getWriter().write("servletB response");
}
}
打开浏览器,输入以下url测试
http://localhost:8080/web03_war_exploded/servletA?username=atguigu
三、响应重定向
1)响应重定向运行逻辑图
2)响应重定向特点(背诵)
- 响应重定向通过HttpServletResponse对象的sendRedirect方法实现
- 响应重定向是在服务端提示下的,客户端的行为;而请求转发是服务器内部的行为,对客户端是屏蔽的
- 响应重定向是服务端通过302响应码和路径,告诉客户端自己去找其他资源,是在服务端提示下的,客户端的行为
- 客户端至少发送了两次请求,客户端地址栏是要变化的
- 服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源
- 因为全程产生了多个HttpServletRequset对象,所以请求参数不可以传递,请求域中的数据也不可以传递
- 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转
- 重定向不可以到给WEB-INF下受保护的资源
- 重定向可以到本项目以外的外部资源
3)响应重定向测试代码
ServletA
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("username");
System.out.println(username);
// 向请求域中添加数据
req.setAttribute("reqKey","requestMessage");
// 响应重定向
// 重定向到servlet动态资源 OK
// resp.sendRedirect()方法干了两件事:1、设置响应状态码为302,同时设置location响应头:servletB
resp.sendRedirect("servletB");
// 重定向到视图静态资源 OK
resp.sendRedirect("welcome.html");
// 重定向到WEB-INF下的资源 NO,因为转发重定向是浏览器自己重新访问这个资源,而WEB-INF下的资源是不能直接通过浏览器访问的
resp.sendRedirect("WEB-INF/views/view1");
// 重定向到外部资源
resp.sendRedirect("http://www.atguigu.com");
}
}

ServletB
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("username");
System.out.println(username);
// 获取请求域中的数据
String reqMessage = (String)req.getAttribute("reqKey");
System.out.println(reqMessage);
// 做出响应
resp.getWriter().write("servletB response");
}
}
- 打开浏览器,输入以下url测试
http://localhost:8080/web03_war_exploded/servletA?username=atguigu
四、总结
都可以如果请求转发响应重定向都可以跳转到这个页面时,我们优先使用重定向,当重定向用不了的,例如我们希望参数继续传递、访问的是WEB-INF下的资源。