Spring MVC 转发和重定向

本文介绍Spring MVC中转发和重定向的区别。

转发和重定向

 开始Java EE时,可能会对转发(forward)和重定向(redirect)这个两个概念不清楚。本文先通过代码实例和运行结果图片感性 认识二者的区别,然后给出二者的定义。

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

@RequestMapping(value="/testa", method=RequestMethod.GET)
public String inputData(){
    return "testa"; //Spring框架找到对应的View并渲染
}

@RequestMapping(value="/testa", method=RequestMethod.POST)
public String outputData(HttpServletRequest request){
    String userName = request.getParameter("name");
    String password = request.getParameter("pwd");
    request.setAttribute("name", userName);
    request.setAttribute("pwd", password);
    return "testb"; //Spring框架找到对应的View并渲染
 }

打开testa网页:

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

这里写图片描述

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

这里写图片描述

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

这里写图片描述

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

2、转发(forward)

@RequestMapping(value="/testa", method=RequestMethod.GET)
public String inputData(){
    return "testa"; //Spring框架找到对应的View并渲染
}

@RequestMapping(value="/testa", method=RequestMethod.POST)
public String outputData(HttpServletRequest request){
    String userName = request.getParameter("name");
    String password = request.getParameter("pwd");
    request.setAttribute("name", userName);
    request.setAttribute("pwd", password);
    //转发到 /testb 的Controller方法(即outputDataX)上
    return "forward:/testb"; 
}

@RequestMapping(value="/testb", method=RequestMethod.POST)
public String outputDataX(HttpServletRequest request){
    return "testb";
}

打开testa网页:

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

这里写图片描述

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

这里写图片描述

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

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

这里写图片描述

3、重定向(redirect)

@RequestMapping(value="/testa", method=RequestMethod.GET)
public String inputData(){
    return "testa"; //Spring框架找到对应的View并渲染
}

@RequestMapping(value="/testa", method=RequestMethod.POST)
public String outputData(HttpServletRequest request){
    String userName = request.getParameter("name");
    String password = request.getParameter("pwd");
    request.setAttribute("name", userName);
    request.setAttribute("pwd", password);
    //重定向到 /testb 的Controller方法(即outputDataY)上
    return "redirect:/testb"; 
}

@RequestMapping(value="/testb", method=RequestMethod.POST)
public String outputDataX(HttpServletRequest request){
    return "testb";
}

@RequestMapping(value="/testb", method=RequestMethod.GET)
public String outputDataY(HttpServletRequest request){
    return "testb";
}

打开testa网页:

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

这里写图片描述

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

这里写图片描述

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

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

这里写图片描述

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

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

@RequestMapping(value="/testa", method=RequestMethod.GET)
 public String inputData(){
  return "testa"; //Spring框架找到对应的View并渲染
 }

 @RequestMapping(value="/testa", method=RequestMethod.POST)
 public String outputData(HttpServletRequest request, RedirectAttributes redirectAttributes){
  String userName = request.getParameter("name");
  String password = request.getParameter("pwd");
  request.setAttribute("name", userName);
  request.setAttribute("pwd", password);
  //重定向到 /testb 的Controller方法(即outputDataY)上
  //重定向传递参数的两种方法
  redirectAttributes.addAttribute("name", userName);
  redirectAttributes.addFlashAttribute("pwd", password);

  return "redirect:/testb"; 
 }

 @RequestMapping(value="/testb", method=RequestMethod.POST)
 public String outputDataX(HttpServletRequest request){
  return "testb";
 }

 @RequestMapping(value="/testb", method=RequestMethod.GET)
 public String outputDataY(HttpServletRequest request){
  String userName = request.getParameter("name");
  request.setAttribute("name", userName);
  return "testb";
 }

运行如下:

这里写图片描述

上面示例了使用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中移除。对于防止重复提交可以使用此方法。

定义

作为一个经验丰富的servlet/JSP程序员,必须知道转发和重定向的区别。 转发比重定向快,因为重定向经过客服端,而转发没有。但是,又是采用重定向更好,若需要重定向到一个外部网站,则无法使用转发。

个人理解:好比服务器窗口A点餐,窗口B取餐。转发就是浏览器到服务器窗口A点餐,点完餐后,服务器内部从窗口B取餐,把饭菜直接给浏览器。重定向就是浏览器到服务器窗口A点餐,服务器不帮助浏览器从窗口B取餐,而是告知浏览器到B取餐。浏览器得到信息后再向窗口B发出取餐要求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值