引言
请求转发与请求重定向的联系与区别,是一道常见的面试题,它们看似都可以跳转链接,实际上,许多细节上却大不相同。
一、请求转发
@Controller public class TestController { // 方式一 @RequestMapping("/forward") public String forward() { return "forward:/hello.html"; } // 方式二 @RequestMapping("/forward2") public void forward2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("hello.html").forward(request, response); } }
注意事项
① 请求转发有两种方式实现,其一是利用框架实现,是一种固定写法;其二是利用 Servlet 提供的 " HttpServletRequest " 和 " HttpServletResponse " 类的对象实现,也是一种固定写法。
② 不管是哪种实现方式,我们都可以看到抓包结果只有一条。可以看见,服务器直接就给前端返回了一个 " 200 " 状态码,表示访问成功。
二、请求重定向
@Controller public class TestController { // 方式一 @RequestMapping("/redirect") public String redirect() { return "redirect:/hello.html"; } // 方式二 @RequestMapping("/redirect2") public void redirect2(HttpServletResponse response) throws IOException { response.sendRedirect("hello.html"); } }
注意事项
① 与请求转发一样,请求重定向也有两种写法,一种是框架提供的,另一种是利用 Servlet 实现。
② 不管是哪种实现方式,我们都可以看到抓包结果有两条。第一条 HTTP 返回的响应头的状态码是 " 302 ",表示 " 临时重定向 ";第二条 HTTP 返回的响应头的状态码是 " 200 ",表示前端访问成功。
总结两者的异同点
共同点:两者都可以实现跳转页面的功能。
不同点:
① 代码不同
② 前后端交互次数不同
经过抓包可以看到,请求转发时,前端与后端只有一次交互;请求重定向时,前端与后端进行了两次交互。
③ 跳转方式不同
请求转发时,后端将跳转好的页面直接返回给了前端;请求重定向时,后端需要先确定前端是一个跳转的请求,只有在前端第二次请求时,才能将页面返回给前端。
举个例子:小明上学忘带铅笔了,所以他就开口向小红借一支铅笔,小红说没有多余的铅笔了,于是小红就向小雨借,小雨是小红的朋友,但是小雨和小明不熟,所以小雨就把铅笔借给了小红,小红最后把铅笔借给了小明。这个过程就是请求转发,本质上,小明只与小红交谈过 ,如果到时候小雨要回铅笔的时候,就应该找小红,而与小明无关了。
再举个例子:如果小明向小强借一支铅笔,小强说没有多余的铅笔了,但是小强告诉小明说:“ 小华有多余的铅笔,你可以找他借。” 那么这时候,小明就直接与小强借铅笔了,之后,如果小华要回铅笔时,就应该直接找小明了,与小强就无关了。这个过程就是请求重定向,小强这个中间人只充当了指路作用。
④ 行为不同
请求转发是服务器端的行为,请求重定向是客户端的行为。
两者的使用场景
请求转发实际上就是一个直接跳转链接的功能,一般来说服务器端很少用到,前端可以直接实现跳转链接。
请求重定向就是一个间接跳转链接的功能,用的较多,常用场景为登录页面,一般第一次请求账号密码无误了,就会进行第二次请求,跳转页面;如果第一次请求验证失败了,那么就无法进行第二次请求了。
另外,请求转发会有一个缺点,比方说,一个 html 文件中包含了一个本地 css 文件的依赖,但是,如果利用请求转发访问当前 html 文件时,可能就会出现 css 文件丢失的情况。