处理模型数据
Spring MVC 提供了以下几种途径输出模型数据:
- ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加
模型数据
- Map 及 Model: 入参为 org.springframework.ui.Model,org.springframework.ui.
ModelMap 或 java.uti.Map 时, 处理方法返回时, Map
中的数据会自动添加到模型中.
- @SessionAttributes: 将模型中的某个属性暂存到
HttpSession 中, 以便多个请求之间可以共享这个属性
- @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中
注: 下面的代码均来自上一篇的注解代码之后的测试代码!!
ModelAndView
控制器处理方法的返回值如果为 ModelAndView, 则其既
包含视图信息, 也包含模型数据信息.
添加模型数据:
- - MoelAndView addObject(String attributeName, Object
- attributeValue)
- - ModelAndView addAllObject(Map<String, ?> modelMap)
设置视图:
- - void setView(View view)
- - void setViewName(String viewName)
TestRequestMapping.java
- @RequestMapping("/testModelAndView")
- public ModelAndView testModelAndView(){
- String viewName="success";
- ModelAndView andView = new ModelAndView(viewName);
- andView.addObject("time", new Date());
- return andView;
- }
- index.jsp
- <a href="springmvc/testModelAndView">testModelAndView</a>
- success.jsp;
- time:${requestScope.time}
总结: SpringMVC 会把 ModelAndView 的 model 中数据放入到 request 域对象中
Map 及 Model
Spring MVC 在内部使用了一个 org.springframework.ui.Model 接口存储模型数据
具体步骤
- Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器.
- 如果方法的入参为 Map 或 Model 类型, Spring MVC 会将隐含模型的引用传
递给这些入参. 在方法体内, 开发者可以通过这个入参对象访问到模型中的所有数
据, 也可以向模型中添加新的属性数据
目标方法可以添加 Map 类型 (实际上是 Model 或者 ModelMap 类型) 的参数
TestRequestMapping.java
- @RequestMapping("/testMap")
- public String testMap(Map<String, Object> map){
- map.put("name", "MrChengs");
- return "success";
- }
- indexjsp
- <a href="springmvc/testMap">testMap</a>
- success.jsp
- name:${requestScope.name}
@SessionAttributes
只能放在类的上面
若希望在多个请求之间共用某个模型属性数据, 则可以在
控制器类上标注一个 @SessionAttributes, Spring MVC
将在模型中对应的属性暂存到 HttpSession 中.
@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(value)
还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(type)
- @SessionAttributes(types=User.class) 会将隐含模型中所有类型
为 User.class 的属性添加到会话中.
- - @SessionAttributes(value={"user1", "user2"})
- - @SessionAttributes(types={User.class, Dept.class})
- - @SessionAttributes(value={"user1", "user2"},
- types={Dept.class})
TestRequestMapping.java
- @SessionAttributes(value="user")
- @Controller
- @RequestMapping("/springmvc")
- public class TestRequestMapping {
- @RequestMapping("/testSessionAttributes")
- public String testSessionAttributes(Map<String,Object> map){
- User user = new User("MrChangs", "1234", "1287@qq.com");
- map.put("user", user);
- return "success";
- }
- }
- index.jsp
- <a href="springmvc/testSessionAttributes">testSessionAttributes</a>
- success.jsp
- user requestScope:${requestScope.user}
- <br>
- <br>
- user sessionScope:${sessionScope.user}
@ModelAttribute
模拟修改数据路中的数据, 有些不能修改.
- index.jsp
- <!--
- 模拟修改操作
- 1. 原始数据: id=1,name=MrChengs,pw=1234,email=MrChengs@qq.com
- 2. 密码不能修改
- 3. 表单回显, 模拟操作直接在表单填写对应的额属性值
- -->
- <form action="springmvc/ModelAttribute" method="post">
- <input type="hidden" name="id" value="1">
- <br>
- name:<input type="text" name="username" value="MrChengs">
- <br>
- email:<input type="text" name="email" value="MrChengs@qq.com">
- <br>
- <input type="submit" value="submit">
- </form>
- // 标记的方法会在每个目标方法执行之前被调用
- //1. 由 @ModelAttribute 标记的方法, 会把每个目标之前被 springmvc 调用
- //2.@MOdelAttribute 注解也可以来修饰目标方法 pojo 类型的入参, 其 value 属性值如下作用
- //2.1)springmvc 会使用 value 属性值在 implicitModel 中查找对应的对象, 若存在直接传入到目标方法的入参中
- //2.2)springmvc 会把 value 为 key,pojo 类型对象为 value, 存到 request 中
- @ModelAttribute
- public void getUser(@RequestParam(value="id",required=false) Integer id,
- Map<String,Object> map){
- if(id != null){
- User user = new User(1, "MrChengs", "1234", "MrChengs@qq.com");
- System.out.println("得到一个参数");
- // 注意: 这里的 key 为 users, 如果改为 users 等其他字符, 等不到结果, 程序可以正常的执行
- // 解决方法在下面的代码中
- map.put("users", user);
- }
- }
- @RequestMapping("/ModelAttribute")
- public String testModelAttribute(@ModelAttribute("users")User user){
- System.out.println("update:" + user);
- return "success";
- }
在 success 页面:
可以使用如下的方法获得打印值
user:${requestScope.users}
如果不添加 @ModelAttribut, 在测试中代码的值为 null
运行过程:
1. 执行 @ModelAttribute 注解修饰的方法, 把数据取出防砸 map 中, map 的 key 为 user
2.SpringMVC 从 Map 中取出 User 对象, 并把表单请求参数放到赋给给该 user 对象多的对应属性
3.SpringMVC 把上述对象传入目标方法的参数
注意: 在 MOdelAttribute 修饰的方法中, 放入 map 的键需要和入参第一个字母小写的字符串一致
SpringMVC 确定目标方法 POJO 类型入参的过程:
1. 确定一个 key
2. 在 implicitModel 中查找对应的 key 对象, 若存在, 则作为入参传入
3. 在 implicitModel 中不存在 key 对象, 则查找当前的 Handler, 是都使用了 @SessionAttribute 对应的 value 值若存在则直接传入到方法的入参中, 不存在抛异常
4. 若 Handler 没由标识的 @SessionAttribute 注解或者 @Session Attribute 的 value 值不包含 key, 则会通过 反射来创建 pojo 类型的参数, 作为目标方法的参数
5.SpringMVC 会把 key 和 value 保存到 impliciModel 中, 进而会保存早 request 中
关于 @SessionAttribute 的异常
java 类:
注意这里 @SessionAttribute(user)和方法中的 user 同名
- @SessionAttributes(value="user")
- @Controller
- @RequestMapping("/springmvc")
- public class TestRequestMapping {
- @RequestMapping("/ModelAttribute")
- public String testModelAttribute(User user){
- System.out.println("update:" + user);
- return "success";
- }
- }
在 ModelAttribute 方法的 user
没找到就去 @SeeionAttribute 中找
所以此时会报错 ---- 抛异常
解决方案:
1. 写 ModelAttribute 注解下的方法
2. 表明一个 modelAttribute, 在第一次查找中赋值, 不在第二次找 SeesionAttribute
public String testModelAttribute(@ModelAttribute("acbc")User user){
十月 16, 2018 4:38:06 下午 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet [springDispatcherServlet] in context with path [/Spring_MVC_01] threw exception [Session attribute 'user' required - not found in session] with root cause
- org.springframework.web.HttpSessionRequiredException: Session attribute 'user' required - not found in session
- at org.springframework.Web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.raiseSessionRequiredException(AnnotationMethodHandlerAdapter.java:791)
- @ModelAttribute
在方法定义上使用 @ModelAttribute 注解: Spring MVC
在调用目标处理方法前, 会先逐个调用在方法级上标注了
@ModelAttribute 的方法.
在方法的入参前使用 @ModelAttribute 注解:
- 可以从隐含对象中获取隐含的模型数据中获取对象, 再将请求参数定到对象中, 再传入入参
- 将方法入参对象添加到模型中
由 @SessionAttributes 引发的异常
- org.springframework.Web.HttpSessionRequiredExcept:
- Session attribute 'user' required - not found in session
如果在处理类定义处标注了 @SessionAttributes("xxx"), 则尝试从会话中获取该属性, 并将其赋给该入参, 然后再用
请求消息填充该入参对象. 如果在会话中找不到对应的属性, 则抛出 HttpSessionRequiredException 异常
如何避免 @SessionAttributes 引发的异常
来源: https://www.cnblogs.com/Mrchengs/p/9940917.html