Spring MVC 提供一下几种途径输出模型数据

  1. ModeAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据
  2. Map及Model:入参为 org.springframework.ui.Model、org.springframework.ui.ModelMap或java.util.Map时。处理方法返回时,Map中的数据会自动添加到模型中。
  3. @SessionAttributes:将模型中的某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性。
  4. @ModelAttribute:方法入参标注该注解后,入参的对象就会放到数据模型中。

ModelAndView

  1. 控制器处理方法的返回值如果为ModelAndView,则其既包含视图信息,也包含模型数据信息。
  2. 添加模型数据:
    1. ModelAndView addObject(String attributeName, Object attributeValue)
    2. ModelAndView addAllObject(Map modelMap)
  3. 设置视图
    1. void setView(View view)
    2. void setViewName(Sting viewName)

Map及Model

  1. Spring MVC在内部使用了一个 org.springframework.ui.Model接口存储模型数据
  2. 具体步骤:
    1. Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
    2. 如果方法的入参为Map或Model类,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参访问到模型中的所有数据,可以向模型中添加新的属性数据。

image-20200919161441497.png

  1. Map及Model示例

@ModelAttribute(“user”)
public User getUser() {
User user = new User();
user.setAge(10);
return user;
}
@RequestMapping(“/handle20”)
public String handle20(Map map) {
map.put(“time”, new Date());
User user = (User)map.get(“user”);
user.setEmail(“TongGang”);
return “success”;
}

  1. 2. ```jsp
  2. email:${requestScope.user.email}
  3. <br><br>
  4. time:${requestScope.time}
  5. <br><br>

<a name="6b1f11c8"></a>
## [@SessionAttributes ](/SessionAttributes )

1. 若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttribute,Spring MVC将在模型中对应的属性暂存到HttpSession中。
1. @SessionAttributes处理可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象模型指定哪些模型属性需要放到会话中,
   1. @SessionAttributes(types=User.class)会将隐含模型中的所有类型为User.class的属性添加到会话中。
   1. @SessionAttributes(value={"user1", "user2"})
   1. @SessionAttributes(types={User.class, Dept.class})
   1. @SessionAttributes(value={"user1", "user2"}, type={Dept.class})
3. @SessionAttribute示例
```java
@SessionAttributes("user")
@Controller
@RequestMapping("/hello")
public class HelloWorld() {

    @ModelAttribute("user")
    public User getUser() {
        User user = new User();
        user.setAge(10);
        return user;
    }

    @RequestMapping("/handle21")
    public String handle21(@ModelAttribute("user") User user) {
        user.setAge(22);
        return "redirect:/hello/handle22.action";
    }

    @RequestMapping("/handle22")
     public String handle22(Map<String, Object> map, SessionStatus sessionStatus) {
        User user = (User)map.get("user");
        user.getId(200);
        return "success";
    }   

}

@ModelAttribute

  1. 在方法定义上使用@ModelAttribute注解:Spring MVC在调用目标处理方法前,会先调用在方法级上标注了@ModelAttribue的方法。
  2. 在方法的入参前使用@ModelAttribute注解:
    1. 可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参。
    2. 将方法入参对象添加到模型中。

由@SessionAttribute引发的异常

org.springframework.web.HttpSessionRequiredException:Session attribute ‘user’ required-not found in session

  1. 如果在处理类定义出标注了@SessionAttributes(“xxx”),则尝试从会话中获取该属性,并将其赋给该入参,然后再用请求消息填充该入参对象。如果在会话中找不到对应的属性,则抛出HttpSessionRequiredException异常
    bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest,name);
    if(bindObject == null) {
      raiseSessionRequiredException("Session attribute'" + name + "' required - not found in session")
    }
    

如何避免@SessionAttribute引发的异常

@Controller
@RequestMapping("/user")
@SessionAttribues("user")
public class UserController {
    @ModelAttribute("user")
    public User getUser() {
        // 该方法会忘隐含模型中添加一个名为user的模型属性
        User user = new User();
        return user;
    }

    @RequestMapping(value = "/handle71")
    public String handle71(@ModelAttribute("user") User user) {
        // ...
    }

    @RequestMapping(value = "/handle72")
    public String handle72(ModelMap modelMap, SessionStatus sessionStatus) {
        // ...
    }
}