使用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
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 map=(Map) attr.getFlashAttributes();
System.out.println(map.get(
"status"
));
System.out.println(map.get(
"message"
));
//addFlashAttribute 即将flashAttribute属性添加到request的OutputFlashMap中,以被重定向后的request获取
//所以我通过获取OutputFlashMap的方式来取值,却发现maps不为空,但是里面的参数没有
Map 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 map2=(Map)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<String, ?> map = RequestContextUtils.getInputFlashMap(request);
if (map != null) {
System.out.println(map.get("flashParams") + "这次终于取到啦");
}
}
这样就可以取到你想要的值啦
原文: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+"¶m2="+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 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
" %>
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 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 user, Model model) {
public
String login(
@RequestParam
Map 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
原文链接:
http://blog.csdn.net/u011851478/article/details/51872977
spring mvc 重定向,转发和传参
重定向:
(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";
}