zoukankan      html  css  js  c++  java
  • 服务端跳转和客户端跳转

    先描述一个场景:

    你到一个机关办事,一个是办事窗口的那个人很不客气地说,这个事你别找我,你找xxx窗口,然后你自己跑到xxx窗口,那个窗口的人直接给你办了;还有一个是窗口的人和你说,你等下,他自己跑去找另一个人沟通一番,然后跑回来给你办了。

    前者是redirect重定向,后者便是forward转发。

    重定向redirect和转发forward的流程图如下:

    (1)客户端跳转--重定向redirect

    客户端向服务器发送请求时,服务器返回一个“去访问其他链接”的响应,客户端根据此响应,第二次去访问服务器,服务器给出最终的响应,所以总共有两次请求。客户端跳转时,地址栏会发生改变。

    使用response的rsendRedirect方法:

      重定向格式:response.sendRedirect("path");

    (2)服务端跳转--转发forward

    客户端向服务器发送请求时,服务器发现当前资源给不出回应,服务器需要在内部请求另一个资源的跳转,然后给出响应,这属于1次请求,由于服务器跳转与否客户端并不知道,所以地址栏的url并不会改变。

    使用requestDispatcher对象:

      转发格式:request.getRequestDispatcher("path").forward(response,request)

    使用jsp动作元素:

      <jsp:forward page=""/>

    (3)转发与重定向的区别

    1.地址栏 
    转发:不变,不会显示出转向的地址 
    重定向:会显示转向之后的地址

    2.请求 

    转发:一次请求
    重定向:至少提交了两次请求

    3.数据 
    转发:对request对象的信息不会丢失,因此可以在多个页面交互过程中实现请求数据的共享 
    重定向:request信息将丢失

    4.原理 

    请求转发为服务器内部跳转,跳转一次,客户端接收结果,而不改变url地址,而请求重定向则跳转两次,既将结果返回给客户端,又使客户端的url地址改变。 

    请求转发为为内部跳转,页面请求的对象一直存在,请求重定向则会结束上个页面的请求。

    请求转发的传参使用request对象方法setAttribute(“name”,value),请求重定向只需使用url传参即可。

    (4)实例:

    例子1:

    转发:在返回值前面加"forward:"

    从第一个转发到其他的处理器,是不需要写传递的数据的,因为数据共享

    重定向:在返回值前面加"redirect:

     

    实例2:

    1、常规用法,返回一个View

     1 @RequestMapping(value="/testa", method=RequestMethod.GET)
     2 public String inputData(){
     3     return "testa"; //Spring框架找到对应的View并渲染
     4 }
     5 
     6 @RequestMapping(value="/testa", method=RequestMethod.POST)
     7 public String outputData(HttpServletRequest request){
     8     String userName = request.getParameter("name");
     9     String password = request.getParameter("pwd");
    10     request.setAttribute("name", userName);
    11     request.setAttribute("pwd", password);
    12     return "testb"; //Spring框架找到对应的View并渲染
    13 }

    打开testa网页:

     

    输入用户名:spring,密码:spring:

     

    点击登陆按钮,页面变为如下:

     

    再次刷新,谷歌浏览器提示重新提交表单。

     

    对比图片,发现浏览器的输入框中URL不变,但是不同情况下显示不同的View。跳转时Model共享(表单会被重复提交)。

    2、转发(forward)

     1 @RequestMapping(value="/testa", method=RequestMethod.GET)
     2 public String inputData(){
     3     return "testa"; //Spring框架找到对应的View并渲染
     4 }
     5 
     6 @RequestMapping(value="/testa", method=RequestMethod.POST)
     7 public String outputData(HttpServletRequest request){
     8     String userName = request.getParameter("name");
     9     String password = request.getParameter("pwd");
    10     request.setAttribute("name", userName);
    11     request.setAttribute("pwd", password);
    12     //转发到 /testb 的Controller方法(即outputDataX)上
    13     return "forward:/testb"; 
    14 }
    15 
    16 @RequestMapping(value="/testb", method=RequestMethod.POST)
    17 public String outputDataX(HttpServletRequest request){
    18     return "testb";
    19 }


    打开testa网页:

     

    输入用户名:spring,密码:spring:

     

    点击登陆按钮,页面变为如下:

     

    调试分析:forward后面跟一个资源。当程序运行到return “forward:/testb”时,会执行会执行该资源对应的方法outputDataX。
    另外转发时,浏览器的URL不变。

    再次刷新,谷歌浏览器提示重新提交表单。

     

    3、重定向(redirect)

     1 @RequestMapping(value="/testa", method=RequestMethod.GET)
     2 public String inputData(){
     3     return "testa"; //Spring框架找到对应的View并渲染
     4 }
     5 
     6 @RequestMapping(value="/testa", method=RequestMethod.POST)
     7 public String outputData(HttpServletRequest request){
     8     String userName = request.getParameter("name");
     9     String password = request.getParameter("pwd");
    10     request.setAttribute("name", userName);
    11     request.setAttribute("pwd", password);
    12     //重定向到 /testb 的Controller方法(即outputDataY)上
    13     return "redirect:/testb"; 
    14 }
    15 
    16 @RequestMapping(value="/testb", method=RequestMethod.POST)
    17 public String outputDataX(HttpServletRequest request){
    18     return "testb";
    19 }
    20 
    21 @RequestMapping(value="/testb", method=RequestMethod.GET)
    22 public String outputDataY(HttpServletRequest request){
    23     return "testb";
    24 }


    打开testa网页:

     

    输入用户名:spring,密码:spring:

     

    点击登陆按钮,页面变为如下:

     

    调试分析:redirect后面跟一个资源。当执行到return “redirect:/testb”时,会执行该资源对应个方法outputDataY。由于重定向Model不共享,所以页面无数据显示。
    另外重定向后浏览器的输入框中URL也发生变化。

    刷新后,谷歌浏览器没有提示重新提交表单

     

    总结:
    常说的可以通过redirect: URL防止重复提交表单,就是上面过程的意思。
    原理是对于redirect而言,Request的attribute不会被传递,放到session中,session在跳到页面后马上移除对象。所以你刷新一下后这个值就会丢掉。

    如果你希望Request的attribute被传递,可以使用RedirectAttributes类。

     1 @RequestMapping(value="/testa", method=RequestMethod.GET)
     2 public String inputData(){
     3     return "testa"; //Spring框架找到对应的View并渲染
     4 }
     5 
     6 @RequestMapping(value="/testa", method=RequestMethod.POST)
     7 public String outputData(HttpServletRequest request, RedirectAttributes     redirectAttributes){
     8     String userName = request.getParameter("name");
     9     String password = request.getParameter("pwd");
    10     request.setAttribute("name", userName);
    11     request.setAttribute("pwd", password);
    12     //重定向到 /testb 的Controller方法(即outputDataY)上
    13     //重定向传递参数的两种方法
    14     redirectAttributes.addAttribute("name", userName);
    15     redirectAttributes.addFlashAttribute("pwd", password);
    16 
    17     return "redirect:/testb"; 
    18 }
    19 
    20 @RequestMapping(value="/testb", method=RequestMethod.POST)
    21 public String outputDataX(HttpServletRequest request){
    22     return "testb";
    23 }
    24 
    25 @RequestMapping(value="/testb", method=RequestMethod.GET)
    26 public String outputDataY(HttpServletRequest request){
    27     String userName = request.getParameter("name");
    28     request.setAttribute("name", userName);
    29     return "testb";
    30 }

    运行如下:

     

    上面示例了使用RedirectAttributes传递参数的两种方法:
    1. 使用RedirectAttributes类的addAttribute方法传递参数会跟随在URL后面,如上图谷歌浏览器所示,URL为http://localhost:8080/testb?name=spring
    2. 使用RedirectAttributes类的addFlashAttribute方法传递参数不会跟随在URL后面,会把该参数值暂时保存于session,待重定向URL获取该参数后从session中移除,这里的redirect必须是方法映射路径,jsp无效。你会发现redirect后的jsp页面中pwd只会出现一次,刷新后pwd再也不会出现了。下图为刷新后的结果,密码pwd显示为空。这验证了上面说的,pwd在被访问后就会从session中移除。对于防止重复提交可以使用此方法。

    参考链接:

    https://ask.csdn.net/questions/376121

    https://blog.csdn.net/jiangshangchunjiezi/article/details/88998809

    https://blog.csdn.net/webzhuce/article/details/54564608

  • 相关阅读:
    Windows Server 2019 mmc无法创建单元
    .NET 设置IE代理
    检测WebService是否存在
    C#读取图片像素
    23种设计模式之简单工厂
    WinForm笔记一:文本框只允许输入数字
    ADO.NET笔记(一)XML导入导出和数据库
    winform中文本框的一些案例
    C#中的二进制序列化和Json序列化
    文件流操作(FileStream,StreamReader,StreamWriter)
  • 原文地址:https://www.cnblogs.com/alice-cj/p/11518859.html
Copyright © 2011-2022 走看看