使用springMVC 做重定向时,出现重定向 redirect 的问题 当我在程序中做重定向: modelAndView.setViewName("redirect:" + "http://tes

使用springMVC 做重定向时,出现重定向 redirect 的问题

当我在程序中做重定向:
modelAndView.setViewName("redirect:" + "http://test.h5pay.jd.com/degrade?merchant=22318136&orderId=1177151445977076639213333333&sign=3d12b75777760135aa5771e88849d70a&aggregate=juhe");
return modelAndView;
时, 跳转到目标主机的controller时,获取到的相关参数为:

orderId=1177151445977076639213333333,QR777777777871
sign=3d12b75777760135aa5771e88849d70a,696196f2efe9e4b6c8cbc969d5ff26ff
其中我在程序中有赋值:
modelAndView.addObject("orderId", "QR777777777871");
modelAndView.addObject("sign", "696196f2efe9e4b6c8cbc969d5ff26ff");

原因:
spring MVC框架controller间跳转,需重定向,会将我modelAndView中放置的属性值,拼接到重定向url后导致

1. 需求背景
    需求:spring MVC框架controller间跳转,需重定向。有几种情况:
不带参数跳转,
带参数拼接url形式跳转,
带参数不拼接参数跳转,页面也能显示。
传统的:可以通过在 redirect:select.do?id=""&name="";这样拼接来实现,也可以实现,但是如果参数中有中文,就会出现问题。
RedirectAttributes是 spring  mvc 3.1版本之后出来的一个功能,专门用于重定向之后还能带参数跳转的,
                    这里用它的addAttribute方法,这个实际上重定向过去以后你看url,是它自动给你拼了你的url。
他有两种带参的方式:
第一种: 
attr.addAttribute("param", value);  
这种方式就相当于重定向之后,在url后面拼接参数,这样在重定向之后的页面或者控制器再去获取url后面的参数就可以了,但这个方式因为是在url后面添加参数的方式,所以暴露了参数,有风险
例:
1
2
3
attr.addAttribute( "name" "123" );  
attr. addAttribute ( "success" "success" );
return   "redirect:/index" ;

这样就相当于:return "redirect:/index?name=123&success=success"

第二种: 
attr.addFlashAttribute("param", value);
这种方式也能达到重新向带参,而且能隐藏参数,其原理就是放到session中,session在跳到页面后马上移除对象。所以你刷新一下后这个值就会丢掉
例:
1
2
3
attr.addFlashAttribute( "status" , "999" );
attr.addFlashAttribute( "message" , "登录失败" );
return   "redirect:/toLogin" ;

这种方式确实能重定向带参,但是有个问题,这个只能重定向到页面上,也就是说重定向的这个 页面视图,能用el表达式直接获取你带参的值,比如status 和message ,都能获取。 可是我重定向到另一个Controller的时候,这 个控制器里面没法获取这两个参数

我现在有个需求:登录成功,直接重定向其他页面,登录失败,又得重定向到登录页面,直接return的还不行,但是又要带状态码和提示等参数,所以想到用 RedirectAttributes的addFlashAttribute 方式。但是重定向到/toLogin这个控制器里面的时候,获取不到 addFlashAttribute 当初添加的属性。
具体事例:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
                //通过直接获取getFlashAttributes的map,然后获取带参,但是获取不到
        Map<String, String> map=(Map<String, String>) attr.getFlashAttributes();
        System.out.println(map.get( "status" ));
        System.out.println(map.get( "message" ));
          
         //addFlashAttribute 即将flashAttribute属性添加到request的OutputFlashMap中,以被重定向后的request获取
         //所以我通过获取OutputFlashMap的方式来取值,却发现maps不为空,但是里面的参数没有
        Map<String, Object> maps=RequestContextUtils.getOutputFlashMap(request);
        System.out.println(maps.get( "status" ));
        System.out.println(maps.get( "message" ));
          
         //因为OutputFlashMap和InputFlashMap  都是由FlashMapManager来管理的
         //对于每一次请求一个 “input” flash map 会被创建,来存储来自任何之前请求的
         //flash attribute 还有一个 “output” flash map 会被创建,来存储任何我们存储在这个请求中的,之后的请求参数
         //这里我获取getInputFlashMap,看看能不能获取到参数,但是还是map2直接为null
        Map<String, String> map2=(Map<String, String>)RequestContextUtils.getInputFlashMap(request);
        System.out.println(map2.get( "status" ));
        System.out.println(map2.get( "message" ));

查了很多资料,包括看了spring mvc的官方文档,对于这个重定向之后参数怎么获取都没有什么明确的解释
包括上述三种方式,包括我直接获取参数的方式都不行,于是放弃了RedirectAttributes来传参

最后还是用session来解决,重定向之前设置session,重定向之后拿值移除session。

效果是做完了,但是心里一直纠结这个,所以发帖,看看各位能不能用RedirectAttributes的addFlashAttribute 方式,并且在另一个控制器里面获取这个添加的参数值
我觉得可以使用modelAndView或者modelMap都可以解决吧

使用 redirectAttributes.getFlashAttributes();是取不到的 ;这地方要用request来取
public ModelAndView getItemList(HttpServletRequest request) {
Map&lt;String, ?&gt; map = RequestContextUtils.getInputFlashMap(request);
if (map != null) {
System.out.println(map.get(&quot;flashParams&quot;) + &quot;这次终于取到啦&quot;);
}
}
这样就可以取到你想要的值啦

原文:https://my.oschina.net/u/2273085/blog/398374
 
spring MVC框架 controller间跳转 ,需重定向。有几种情况:不带参数跳转,带参数拼接url形式跳转,带参数不拼接参数跳转,页面也能显示。
    首先先来介绍一下不带参数的重定向:
    我在后台一个controller跳转到另一个controller,为什么有这种需求呢,是这样的。我有一个列表页面,然后我会进行新增操作,新增在后台完成之后我要跳转到列表页面,不需要传递参数,列表页面默认查询所有的。
       方式一:使用ModelAndView(这是Spring 2.0的时候所用到的方法)
        return new ModelAndView("redirect:/toList");
        这样可以重定向到toList这个方法
        方式二:返回String
        return "redirect:/ toList "; 
注意: 重定向只能重定向到另一个请求中,如果需要直接跳转到页面中,直接通过
return "toList ";  类似于这种,跳转页面时,不能添加redirect ,除非是先跳转到另一次请求,再回到页面时
    然后在说一下带参数的重定向
    第二种情况,列表页面有查询条件,跳转后我的查询条件不能丢掉,这样就需要带参数的了,带参数可以拼接url

        方式一:自己手动拼接url
        new ModelAndView("redirect:/toList?param1="+value1+"&param2="+value2);
        这样有个弊端,就是传中文可能会有乱码问题。

        方式二:用RedirectAttributes,这个是发现的一个比较好用的一个类
        这里用它的addAttribute方法,这个实际上重定向过去以后你看url,是它自动给你拼了你的url。
        使用方法:
       public String test(RedirectAttributes attributes) 
{
attributes.addAttribute("test", "hello");
return "redirect:/test/test2";
}
        这样在toController这个方法中就可以通过获得参数的方式获得这个参数,再传递到页面。过去的url还是和方式一一样的。如果你细心的看重定向之后的url地址的话,你就会发现其实和上面的地址是一样的,这样也会出现上面那个方法出现的问题。
    重点来了, 咱们介绍一个不会出现中文乱码 ,而且不会在你的Url上出现你所要传递的数据的,这样就可以保证你在传递数据的安全
        public String red(RedirectAttributes attributes) 
{
attributes.addFlashAttribute("test", "hello");
return "redirect:/test/test2";
}
   咱们用上面的方法进行数据传递你就会发现不会再Url上出现你要传递的数据,那么数据放到哪里去了,我 们就来看看这是Spring 3.0新出现的特性,attributes.addFlashAttribute("test", "hello")实际存储的属性在flashmap,那么flashmap又是什么呢?
    Flash 属性 和 RedirectAttribute:通过FlashMap存储一个请求的输出,当进入另一个请求时作为该请求的输入,典型场景如重定向(POST- REDIRECT-GET模式,1、POST时将下一次需要的数据放在FlashMap;2、重定向;3、通过GET访问重定向的地址,此时 FlashMap会把1放到FlashMap的数据取出放到请求中,并从FlashMap中删除;从而支持在两次请求之间保存数据并防止了重复表单提 交)。
     Spring Web MVC提供FlashMapManager用于管理FlashMap,默认使用SessionFlashMapManager,即数据默认存储在session中
    既然知道了怎么回事,那么我们就可以把它提取出来,怎么提取呢,很多人会说,既然存在session中,那就从session中获取,结果发现没有,那怎么办?
    下面我就给大家提供两个方法让大家把addFlashAttribute中的数据提取出来
    方法一:利用httpServletRequest
    public String test2(HttpServletRequest request)
{
Map<String,?> map = RequestContextUtils.getInputFlashMap(request); 
System.out.println(map.get("test").toString());
return "/test/hello";
}
     方法二:利用Spring提供的标签@ModelAttribute
public String test2(@ModelAttribute("test") String str)
{
System.out.println(str);
return "/test/hello";
}

详解SpringMVC重定向传参数的实现

本篇文章主要介绍了详解SpringMVC重定向传参数的实现,我们可以使用重定向的方式,改变浏览器的地址栏,防止表单因为刷新重复提交。有兴趣的可以了解一下。
在spring的一个controller中要把参数传到页面,只要配置视图解析器,把参数添加到Model中,在页面用el表达式就可以取到。但是,这样使用的是forward方式,浏览器的地址栏是不变的,如果这时候浏览器F5刷新,就会造成表单重复提交的情况。所以,我们可以使用重定向的方式,改变浏览器的地址栏,防止表单因为刷新重复提交。
jsp文件:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri=" http://java.sun.com/jsp/jstl/core " %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " http://www.w3.org/TR/html4/loose.dtd ">
< html >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8" >
< title >login</ title >
</ head >
< body >
    
  < form id = "form1" action = "/demo/user/login" method = "post" >
    账号:< input type = "text" name = "name" /></ br >
    密码:< input type = "password" name = "password" /></ br >
    < input type = "submit" value = "submit" />
      
  </ form >
  
</ body >
</ html >
controller:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.demo.controller;
  
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
  
/**
  * @author lpj
  * @date 2016年7月10日
  */
@Controller
@RequestMapping ( "/user" )
public class DemoController {
  
   @RequestMapping ( "/login" )
   public String login( @RequestParam Map<String, String> user, Model model) {
    System.out.println( "用户提交了一次表单" );
    String username;
     if (user.get( "name" ).isEmpty()) {
      username = "Tom" ;
    } else {
      username = user.get( "name" );
    }
    model.addAttribute( "msg" , username);
//    return "home";//此方式跳转,页面刷新会重复提交表单
     return "redirect:/home.jsp" ;
  }
  
}
由于重定向相当于2次请求,所以无法把参数加在model中传过去。在上面例子中,页面获取不到msg参数。要想获取参数,可以手动拼url,把参数带在后面。
Spring 3.1 提供了一个很好用的类:RedirectAttributes。 使用这个类,我们可以把参数随着重定向传到页面,不需自己拼url了。
把上面方法参数中的Model换成RedirectAttributes,参数就自动跟在url后了。
但是,这样页面不能用el获取到,还要另外处理,所以,我们还有一种方式,不拼url,用el获取参数,就像普通转发一样。
还是使用RedirectAttributes,但是这次不用addAttribute方法,spring为我们准备了新方法,addFlashAttribute()。
这个方法原理是放到session中,session在跳到页面后马上移除对象。所以你刷新一下后这个值就会丢失。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.demo.controller;
  
import java.util.Map;
  
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
  
/**
  * @author lpj
  * @date 2016年7月10日
  */
@Controller
@RequestMapping ( "/user" )
public class DemoController {
  
   @RequestMapping ( "/login" )
// public String login(@RequestParam Map<String, String> user, Model model) {
   public String login( @RequestParam Map<String, String> user, RedirectAttributes model) {
    System.out.println( "用户提交了一次表单" );
    String username;
     if (user.get( "name" ).isEmpty()) {
      username = "Tom" ;
    } else {
      username = user.get( "name" );
    }
    model.addFlashAttribute( "msg" , username);
//   return "home";//此方式跳转,页面刷新会重复提交表单
     return "redirect:/user/toHome" ;
  }
    
   @RequestMapping ( "/toHome" )
   public String home( @ModelAttribute ( "msg" ) String msg, Model model) {
    System.out.println( "拿到重定向得到的参数msg:" + msg);
    model.addAttribute( "msg" , msg);
     return "home" ;
  }
}
这边我们使用@ModelAttribute注解,获取之前addFlashAttribute添加的数据,之后就可以正常使用啦。
需要例子代码的可以点此下载: http://xiazai.jb51.net/201701/yuanma/springmvcdemo_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

重定向:
(1)第一种情况:不需要传递参数。
方式一:使用ModelAndView
return new ModelAndView("redirect:/toList");
这样可以重定向到toList这个方法
方式二:返回String
return "redirect:/ toList ";
 
(2)第二种情况:带参数
拼接url,用RedirectAttributes,这里用它的addAttribute方法,这个实际上重定向过去以后你看url 
,是它自动给你拼了你的url。
使用方法:
attr.addAttribute("param", value);
return "redirect:/namespace/toController";
这样在toController这个方法中就可以通过获得参数的方式获得这个参数,再传递到页面。

不拼接url:
@RequestMapping("/save")
public String save(@ModelAttribute("form") Bean form, RedirectAttributes attr )
throws Exception {
String code = service.save(form);
if(code.equals("000")){
attr.addFlashAttribute ("name", form.getName()); 
attr.addFlashAttribute("success", "添加成功!");
return "redirect:/index";
}else{
attr.addAttribute ("projectName", form.getProjectName()); 
attr.addAttribute("enviroment", form.getEnviroment()); 
attr.addFlashAttribute("msg", "添加出错!");
return "redirect:/maintenance/toAddConfigCenter";
}
}
注意:1.使用RedirectAttributes的addAttribute方法传递参数会跟随在URL后面,如上代码即为 
http:/index.action?a=a
2. 使用addFlashAttribute不会跟随在URL后面,会把该参数值暂时保存于session, 
待重定向url获取该参数后从session中移除, 这里的redirect必须是方法映射路径,jsp无效 。你会 
发现redirect后的jsp页面中b只会出现一次,刷新后b再也不会出现了,这验证了上面说的,b被访问 
后就会从session中移除。对于重复提交可以使用此来完成.

另外,如果使用了RedirectAttributes作为参数,但是没有进行redirect呢?这种情况下不会 
将RedirectAttributes参数传递过去,默认传forward对应的model,官方的建议是:
p:ignoreDefaultModelOnRedirect="true" />
设置下RequestMappingHandlerAdapter 的ignoreDefaultModelOnRedirect属性,这样可以提高效率 
,避免不必要的检索。

当保存POJO到数据库后,要返回成功页面,如果这个时候要带点信息,则要这样:
@RequestMapping(value = "/user/save", method = RequestMethod.POST)
public ModelAndView saveUser(UserModel user, RedirectAttributes redirectAttributes) 
throws Exception {
redirectAttributes.addFlashAttribute("message", "保存用户成功!");//使用 
addFlashAttribute,参数不会出现在url地址栏中
return "redirect:/user/save/result";
}
 
转发:
返回ModelAndView :
@RequestMapping(value="/test",method=RequestMethod.GET)
public ModelAndView testForward(ModelAndView model){

model.setViewName("forward:index.jsp");
return model;
}
如上代码,如果返回modelAndView 则可以如红色标注,添加forward即可,若想重定向,可把 
forward替换成redirect便可达到目的。

返回String:

@RequestMapping(value="/forward",method=RequestMethod.GET)
public String testForward(){
return "forward:/index.action";
}
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值