标签:
Spring MVC提供了几种将数据添加到模型的方式:使用ModelMap/Model类型的方法参数、方法体内创建ModelAndView实例,如下代码片段所示:
@RequestMapping(value = "/login.htm", method = RequestMethod.GET) public String doLogin(ModelMap modelMap) { BaseMember mockMember = new BaseMember(); mockMember.setLoginName("mockLoginName"); // 向模型添加数据 modelMap.addAttribute("member", mockMember); return "home"; }
@RequestMapping(value = "login2.htm", method = RequestMethod.GET) public ModelAndView doLogin2() { BaseMember mockMember = new BaseMember(); mockMember.setLoginName("mockLoginName"); // 创建ModelAndView实例 ModelAndView mav = new ModelAndView(); mav.addObject("member", mockMember); mav.setViewName("home"); return mav; }
除了以上两种方式之外,Spring MVC还提供了一种基于注解的方式,即使用@ModelAttribute,如下代码片段所示:
@RequestMapping(value = "login3.htm", method = RequestMethod.GET) public String doLogin3(@ModelAttribute("member") BaseMember mockMember){ mockMember.setLoginName("mockLoginName"); return "home"; }
有两种使用@ModelAttribute注解的方法,一种是用于方法,另一种是用于方法的参数。
当@ModelAttribute注解用于方法时,表明了该方法的作用是向模型中存放一个或多个数据,例如:
@ModelAttribute public BaseMember addBaseMember() { BaseMember mockMember = new BaseMember(); mockMember.setLoginName("mockMemberName"); return mockMember; }
方法的返回值将被存放在模型中。而如我们所了解的,模型中的数据都是以键值对的形式存储,但我们似乎并没有为返回值提供键名?这种情况下,一个基于返回值类型的名称将会作为键名,例如方法返回值是一个BaseMember类型的对象,此时“baseMember”将作为默认的键名。通常情况下,这种约定带来了一定程度上的便利,但是当模型中的数据并不全是由我们控制时,这回带来意想不到的问题,因此,较好的方式是显示的提供键名,例如:
@ModelAttribute("mockBaseMember") public BaseMember addBaseMember() { BaseMember mockMember = new BaseMember(); mockMember.setLoginName("mockMemberName"); return mockMember; }
由于方法只能有一个返回值,因此这种形式只能往模型中加入一个数据,我们还有另一种更加通用的方式:
@ModelAttribute public void populateModel(Model model) { BaseMember mockMember = new BaseMember(); mockMember.setLoginName("mockMemberName"); model.addAttribute("mockMember", mockMember); // 其它需要加入到模型的数据 model.addAttribute("currentDate", new Date()); }
以这种方式,我们可以往模型中加入多个需要的数据,仅仅只需要提供一个Model/ModelMap类型的方法参数即可。
当@ModelAttribute注解用于方法参数时,它有了双重功能,即“存/取”。首先,它从模型中取出数据并赋予对应的参数,如果模型中尚不存在,则实例化一个,并存放于模型中;其次,一旦模型中已存在此数据对象,接下来一个很重要的步骤便是将请求参数绑定到此对象上(请求参数名映射对象属性名),这是Spring MVC提供的一个非常便利的机制--数据绑定,之后将专门用一篇文章讨论此话题。
@RequestMapping(value = "/login2.htm", method = RequestMethod.GET) public String doLogin2(@ModelAttribute("baseMember") BaseMember member) { member.setLoginName("loginName"); return "home"; }
上述代码中,如果模型中尚不存在键名为“baseMember”的数据,则首先会调用BaseMember类的默认构造器创建一个对象,如果不存在默认构造器会抛出异常。
严重: Servlet.service() for servlet dispatcher threw exception java.lang.NoSuchMethodException: org.just4fun.spring.web.domain.BaseMember.<init>() at java.lang.Class.getConstructor0(Unknown Source) ......
因此,给实体类提供一个默认构造器是一个好的编程习惯。当请求路径的请求参数或提交的表单与BaseMember的属性名匹配时,将自动将其值绑定到baseMember对象中,非常的便利!这可能是我们使用@ModelAttribute最主要的原因之一。比如:请求路径为http://localhost:8080/spring-web/login2.htm?loginName=myLoginName,baseMember对象中的loginName属性的值将被设置为myLoginName。
正如第2节讨论的,当@ModelAttribute注解用于方法时,与其处于同一个处理类的所有请求方法执行前都会执行一次此方法,这可能并不是我们想要的,因此,我们使用更多的是将其应用在请求方法的参数上,而它的一部分功能与@RequestParam注解是一致的,只不过@RequestParam用于绑定单个参数值,而@ModelAttribute注解可以绑定所有名称匹配的,此外它自动将绑定后的数据添加到模型中,无形中也给我们提供了便利,这也可能是它命名为ModelAttribute的原因。
Spring MVC之@ModelAttribute注解的使用
标签:
原文地址:http://www.cnblogs.com/shucunbin/p/4438711.html