请求转发与重定向

1. 请求转发与重定向的定义

  • 请求转发(Forward):请求转发是服务器行为,它只产生一次请求,客户端请求到达服务器之后中会发生一次转发,之后服务器才将结果发送到客户端。

  • 请求重定向(Redirect):重定向是客户端(浏览器)行为,它会产生两次请求每次都是从客户端发起。当客户端发送request1给第一个服务器端时,第一个服务器端返回一个response1给客户端,紧接着客户端(浏览器)继续发送request2给第二个服务器端,第二个服务器端返回一个response2给客户端。

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

2.1 请求方式

  • 请求转发(Forward):发生在服务端程序内部,当服务器端收到一个客户端的请求之后,会先将请求,转发给目标地址,再将目标地址返回的结果转发给客户端(浏览器)。

  • 请求重定向(Redirect):发生在客户端与多个服务端之间,服务器端接收到客户端的请求之后,会给客户端返回了一个临时响应头,这个临时响应头中记录了,客户端需要再次发送请求(重定向)的 URL 地址。客户端再收到了地址之后,将发送一个新的请求给该URL 地址。

  • 注意事项:

    • 重定向时不管第一次请求时的方式是什么,第二次请求时方式都是GET;而转发时,两次的方式是一样的

2.2 数据共享

  • 请求转发是服务器端实现的,所以整个执行流程中,客户端(浏览器端)只需要发送一次请求,因此整个交互过程中使用的都是同一个 Request 请求对象和一个 Response 响应对象,所以整个请求过程中,请求和返回的数据是共享的

  • 而请求重定向客户端发送两次完全不同的请求,所以两次请求中的数据是不同的,要想传内容或者参数只能在url路径后面添加参数例如:url地址?参数名称=参数值;response.sendRedirect(“url地址?参数名称=参数值”)


2.3 资源访问

  1. 请求转发(Forward):

    • 请求转发是服务器内部调用的地址请求,因此请求转发的路径必须是同一个Web容器下的URL,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。因为转发行为是浏览器只做了一次访问请求,在客户浏览器路径栏显示的仍然是其第一次访问的路径(转发不会改变url路径),也就是说客户是感觉不到服务器做了转发的。
    • 转发可以访问WEB-INF下资源,重定向不能直接访问WEB-INF下资源
      • WEB-INF属于服务器私有目录【服务器内部可以访问,浏览器不能直接访问】。
    • 在过滤器中,如果使用转发后,则不会进入过滤器中。因为转发是一次请求,进入服务器后,已经经过了过滤器。当进行转发后,没有重新发请求,则不会再进入到过滤器中。如果是重定向,则是重客户端重新发的请求,则还是会进入过滤器,再访问目标资源。
  2. 请求重定向(Redirect):

    • 重定向是对浏览器的请求直接做出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求。重定向行为是浏览器做了至少两次的访问请求的,在客户浏览器路径栏显示的是其重定向的路径(url路径会改变),因此重定向可以访问服务器外的资源,客户也可以观察到地址的变化的。

3. 请求转发和重定向的选择

  1. 页面变更:重定向后,url路径会改变;转发不会改变url路径,还是原先的访问路径,在应用中往往增删改使用重定向。比如我们在使用完增删改后,如果路径不改变,则继续刷新,会出现增删改异常;而查询需要使用转发,转发后,可实时变更使用request传值。
  2. 内部资源访问:
    • 在同一Web应用程序的两个请求间传递数据时,在转发与重定向之间,只能通过转发实现
    • 对内部安全页面跳转则必须使用转发,例如转发到内部[WEB-INF]下的安全页面,则必须使用转发,使用重定向则访问不了。
  3. 外部资源访问:如果需要跳转到其它服务器上的资源,则必须使用重定向,比如访问百度。
  4. 如果既想要实现路径跳转又需要实现数据共享,使用请求转发!如果只是纯粹的想要实现路径跳转,我们可以使用重定向,但是优先选择请求转发,因为转发效率更高

4. SpringMVC请求转发和重定向

  • 转发路径规则:如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录

4.1 请求转发

  • 特点:请求转发地址栏不会发生改变、只发送一次请求、能携带原有的参数,但只可以在同一个服务器中进行转发。

  • 文件夹目录结构如下:

  1. 传统的请求转发:

    • 控制器中的代码:
    // 传统的请求转发
    @RequestMapping("/fun1")
    public void fun1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("hobby","fun1");
        request.getRequestDispatcher("/WEB-INF/manager/teacher.jsp").forward(request,response);
        System.out.println("fun1");
    }
    
    • 在webapp目录下的:WEB-INF/manager/teacher.jsp中的代码:
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>这是老师页面</title>
        </head>
        <body>
            老师喜欢:<%= request.getAttribute("hobby")%>
        </body>
    </html>
    
    • 访问localhost:80/fun1,页面效果:
      在这里插入图片描述


  2. SpringMVC中不经过视图解析器的请求转发:

    // SpringMVC中不经过视图解析器的请求转发(不携带数据)
    @RequestMapping("/fun2")
    public String fun2() {
        System.out.println("fun2");
        return "forward:/WEB-INF/worker/doctor.jsp";
    }
    
    // SpringMVC中不经过视图解析器的请求转发(携带数据)
    @RequestMapping("/fun3")
    public ModelAndView fun3(ModelAndView modelAndView) {
        modelAndView.addObject("hobby","fun3");
        modelAndView.setViewName("forward:/WEB-INF/worker/doctor.jsp");
        System.out.println("fun3");
        return modelAndView;
    }
    

  3. SpringMVC中经过视图解析器的请求转发:

    // SpringMVC中经过视图解析器的请求转发(不携带数据)
    @RequestMapping("/fun4")
    public String fun4() {
        System.out.println("fun4");
        return "/WEB-INF/worker/doctor.jsp";
    }
    
    // SpringMVC中经过视图解析器的请求转发(携带数据)
    @RequestMapping("/fun5")
    public ModelAndView fun5(ModelAndView modelAndView) {
        modelAndView.addObject("hobby","fun5");
        modelAndView.setViewName("/WEB-INF/worker/doctor.jsp");
        System.out.println("fun5");
        return modelAndView;
    }
    

  4. SpringMVC在控制器之间转发,并共享数据:

    @RequestMapping("/test1")
    public ModelAndView test1(ModelAndView modelAndView) {
        System.out.println("test1");
        modelAndView.addObject("hobby","football");
        modelAndView.setViewName("/test2");
        return modelAndView;
    }
    
    @RequestMapping("/test2")
    public ModelAndView test2(ModelAndView modelAndView, HttpServletRequest request) {
        System.out.println("test2");
        modelAndView.setViewName("/WEB-INF/manager/teacher.jsp");
        Object hobby = request.getAttribute("hobby");
        System.out.println(hobby);
        return modelAndView;
    }
    /*控制台结果如下
    test1
    test2
    football
    */
    
    • 访问localhost:80/test1,页面效果:
      在这里插入图片描述

4.2 重定向

  1. 传统的重定向:

    @RequestMapping("/test3")
    public void fun1(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.sendRedirect("/index.jsp");
    }
    

  2. SpringMVC中不带参数的重定向:重定向不能访问WEB-INF下的资源

    @RequestMapping(value = "/test4")
    public String test4() {
        return "redirect:/test.jsp";
        // return "redirect:/WEB-INF/student.jsp";
    }
    
    @RequestMapping(value = "/test5")
    public ModelAndView test5() {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("redirect:/index.jsp");
        // mv.setViewName("redirect:/WEB-INF/student.jsp");
        return mv;
    }
    

  3. SpringMVC中带参数的重定向:

    • redirectAttributes.addAttributie(“prama”,value); 这种方法相当于在重定向链接地址上追加传递的参数。上面示例相当于请求 http://localhost:8080/test.jsp?param=1。

      @RequestMapping("/test6")
      private String test6(RedirectAttributes redirectAttributes ) {
          redirectAttributes.addAttribute("param", 1);
          return "redirect:/test.jsp";
      }
      

      在这里插入图片描述

    • redirectAttributes.addFlashAttributie(“prama”,value); 方法是隐藏了参数,链接地址上不直接暴露,用(@ModelAttribute(value = “prama”)String prama)的方式获取参数。

      @RequestMapping("/test7")
      private String test7(RedirectAttributes redirectAttributes ) {
          redirectAttributes .addFlashAttribute("param", 1001);
          return "redirect:/test8";
      }
      
      // 接收参数
      @RequestMapping("/test8")
      @ResponseBody
      private String test8(@ModelAttribute("param") String param) {
          System.out.println(param); // 输出1001
          return "hello";
      }
      

参考博客:

  1. 请求转发与重定向_重定向是两次请求的原因是因为request对象的不同吗_梁云亮的博客-CSDN博客
  2. 请求转发与重定向到底有哪些区别?_重定向和请求转发区别_一一哥Sun的博客-CSDN博客
  3. springmvc请求转发和重定向_springmvc 请求转发_梁云亮的博客-CSDN博客
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值