很久没来了,来mark一个,最近用spring的MVC,碰到ModelAtrribute这个标注,感觉相对其他标注比较难于理解一点,看了一遍源代码,梳理一下,做下记录。
ModelAtrribute标注本身很简单,看下他的定义:
/**
* Annotation that binds a method parameter or method return value
* to a named model attribute, exposed to a web view. Supported
* for {@link RequestMapping} annotated handler classes.
*
* <p>Can be used to expose command objects to a web view, using
* specific attribute names, through annotating corresponding
* parameters of a {@link RequestMapping} annotated handler method).
*
* <p>Can also be used to expose reference data to a web view
* through annotating accessor methods in a controller class which
* is based on {@link RequestMapping} annotated handler methods,
* with such accessor methods allowed to have any arguments that
* {@link RequestMapping} supports for handler methods, returning
* the model attribute value to expose.
*
* @author Juergen Hoeller
* @since 2.5
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {
/**
* The name of the model attribute to bind to.
* <p>The default model attribute name is inferred from the declared
* attribute type (i.e. the method parameter type or method return type),
* based on the non-qualified class name:
* e.g. "orderAddress" for class "mypackage.OrderAddress",
* or "orderAddressList" for "List<mypackage.OrderAddress>".
*/
String value() default "";
}
它可以标注方法(method)和参数(parameter),当标注参数时,表示从session或者impitmodel中获取这个属性对象,然后从request参数获取一些属性值来覆盖ModelAttribute标注的对象中的部分属性。
例如:
@RequestMapping
public void addOrder(@ModelAttribute("order") Order order){
.....
}
对应解析这段代码的地方在org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveHandlerArguments和resolveModelAttribute中,可以仔细看下,另外你会发现,如果参数本身就是一个POJO时,其实你可以不用写ModelAttribute,它会自动根据参数类型来解析出名称并执行与有ModelAttribute标注时一样的逻辑。
他的RequestMapping的方法时都要先执行这个方法,如果有RequestMapping标注,则只是在该方法执行的时候才将该返回结果放入到modelMap中,注意返回对象可以是
Model,Map,View,String或者其他非简单对象,但不能是Long,int,Class这些类型。
对应解析代码在org.springframework.web.bind.annotation.support.HandlerMethodInvoker#invokeHandlerMethod和org.springframework.web.servlet.mvc.annotation。AnnotationMethodHandlerAdapter#getModelAndView 中。getModelAndView 主要是将执行方法后得到的结果放入到modelMap中。