diff --git a/spring/Spring core/SpringMVC.md b/spring/Spring core/SpringMVC.md index 1a03a67..e311c37 100644 --- a/spring/Spring core/SpringMVC.md +++ b/spring/Spring core/SpringMVC.md @@ -276,5 +276,55 @@ public void handle(@CookieValue("JSESSIONID") String cookie) { } ``` 如果注解标注参数的类型不是String,会自动执行类型转换。 +#### @ModelAttribute +可以为handler method的参数添加@ModelAttribute注解,在添加该注解之后,参数属性的值可以从Model中进行获取,如果model中不存在则对该属性进行初始化。 +**Model属性会被http servlet param中的值覆盖,如果request param name和field name相同。** +> @ModelAttribute注解,其name的默认值为方法参数或者返回值类型的首字母小写: +> 例如,“orderAddress" for class "mypackage.OrderAddress" + +@ModelAttribute的使用具体可如下所示: +```java +@PostMapping("/owners/{ownerId}/pets/{petId}/edit") +public String processSubmit(@ModelAttribute Pet pet) { + // method logic... +} +``` +参数pet可以通过如下方式进行获取: +1. pet参数已经加上了@ModelAttribute属性,故而可以从model中进行获取 +2. 如果该model attribute已经出现在类级别的@SessionAttribute中,则可以在session中进行获取 +3. 如果model attribute name和request param name或者path variable name相匹配,那么可以通过converter来进行获取 +4. 通过默认的构造器进行初始化 +5. 通过primary constructor进行构造,主构造器参数和servlet request param相匹配 + +在使用@ModelAttribute时,可以创建一个Converter类型的bean对象用于类型转换,当model attribute name和path variable或者request param name相匹配,且Converter对象存在时,会调用该Converter进行类型转换: +```java +@Component +class StringPersonConverter implements Converter { + @Override + public Person convert(String source) { + return new Person("kazusa",true,21); + } +} + +@RestController +public class ModelAttributeController { + + @PostMapping("/hello") + public Person sayHello(@ModelAttribute(name="name",binding=true) Person person, Model model) { + System.out.println(model); + return person; + } +} +``` +在model attribute被获取之后,会执行data binding。WebDataBinder会将request param name和目标对象的field进行匹配,匹配的field会通过类型转换进行注入。 +如果想要访问Model Attribute但是不想使用data binding,可以直接在handler method参数中使用Model,或者将@ModelAttribute注解的binding属性设置为false。 +```java +@PostMapping("update") +public String update(@Valid AccountForm form, BindingResult result, + @ModelAttribute(binding=false) Account account) { + // ... +} +``` +