RedirectAttributes的addAttribute方法和addFlashAttribute方法
还是补javaweb不认真学的坑,之前转发已经说过了可以在request中传递数据,而重定向因为是浏览器根据服务器返回的url再起请求,之前的request已经失效了,所以是不能在request中传递数据的。
但是如果确实需要传递参数,可以通过url拼接的方式,在重定向的url后面通过 ?param1=value1¶m2=value2… 的方式来传递参数;或者通过session传递参数。SpringMVC提供了更方便的方法,可以不用自己手动拼url和写session,即RedirectAttributes,它提供了addAttribute方法和addFlashAttribute方法来传递参数。
addAttribute
这个方法比较好理解,就是在url后面拼参数,然后再页面中通过EL表达式从param中取就行了,代码(DispatcherServlet配的是*.do):
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/test.do" method="post">
姓名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
<button type="submit">提交</button>
</form>
</body>
</html>
Controller方法
@RequestMapping("/test.do")
public String doTest(String name, Integer age, RedirectAttributes attributes) {
attributes.addAttribute("myName", name);
attributes.addAttribute("myAge", age);
return "redirect:/result.jsp";
}
result.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>结果</title>
</head>
<body>
<h1>取到的结果</h1>
<h3>param姓名:${param.myName}</h3>
<h3>param年龄:${param.myAge}</h3>
</body>
</html>
提交表单之前:
提交表单之后:
可以看到url确实变成result.jsp,并且后面拼上了参数,这里已经在web.xml中配置了编码过滤器所以post没乱码。这个也比较好理解,用起来也比较方便。
addFlashAttribute
这个方法我纠结了好久,网上搜到的全是这个方法存到session里,页面中直接用EL表达式就能取,但是我试了一下发现根本取不到啊?代码如下:
Controller方法:
@RequestMapping("/test.do")
public String doTest(String name, Integer age, RedirectAttributes attributes) {
attributes.addFlashAttribute("myName", name);
attributes.addFlashAttribute("myAge", age);
return "redirect:/result.jsp";
}
result.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>结果</title>
</head>
<body>
<h1>取到的结果</h1>
<h3>EL姓名:${myName}</h3>
<h3>EL年龄:${myAge}</h3>
</body>
</html>
提交表单后:
可以看到确实重定向到result.jsp了,而且也没有在后面拼参数,但是EL表达式是不能直接取到session里的东西的。接下来在jsp页面里打印一下session里的东西,看到底存到哪了。
在result.jsp中加一段代码,在控制台打印一下session中的内容:
<%
final Enumeration se = session.getAttributeNames();
while (se.hasMoreElements()) {
final String key = (String) se.nextElement();
System.out.println(key + "==" + session.getAttribute(key));
}
%>
控制台输出:
org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS== [
FlashMap [
attributes={myName=张三, myAge=22},
targetRequestPath=/forward_redirect_war_exploded/result.jsp,
targetRequestParams={}
]
]
可以看到session里总共就存了一个东西FLASH_MAPS,里面的FlashMap存了各种东西,所以如果要从通过EL表达式从session中取值,需要格式对了才能取到,不然肯定是拿不到的,所以result.jsp中这么写就可以拿到值:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>结果</title>
</head>
<body>
<h1>取到的结果</h1>
<h3>EL姓名:${sessionScope['org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS'][0]['myName']}</h3>
<h3>EL年龄:${sessionScope['org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS'][0]['myAge']}</h3>
</body>
</html>
提交表单结果:
暂时没想到有什么更好的写法,反正这么写是肯定能取到,但是太麻烦了…
二次转发
还可以通过二次转发的方式取到值,这种方法稍微简单一点,可以直接用EL表达式获取值,也不会因为 在url上拼参数,导致安全性问题,但是因为第二次是转发,所以地址栏最终的url就会比较尴尬,代码如下:
@RequestMapping("/test.do")
public String doTest(String name, Integer age, RedirectAttributes attributes) {
attributes.addFlashAttribute("myName", name);
attributes.addFlashAttribute("myAge", age);
return "redirect:/mid.do";
}
@RequestMapping("/mid.do")
public String Mid() {
return "/result.jsp";
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>结果</title>
</head>
<body>
<h1>取到的结果</h1>
<h3>经二次转发姓名:${myName}</h3>
<h3>经二次转发年龄:${myAge}</h3>
</body>
</html>
提交表单后的结果:
因为第二次是转发,所以地址就尬在mid.do了,体验应该不是很好。目前没想到最好的解决办法,也欢迎补充。