【Spring】抽丝剥茧SpringMVC-ModelAttribute使用方法

本文源码基于SpringMVC 5.2.7

@ModelAttribute 

    @ModelAttribute可以用在方法上,也可以用在参数上。当它用在方法上时候,SpringMVC会将其返回值绑定到model的属性上;当它用在参数上时候,SpringMVC会从model取出对应的属性传给该参数。

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {

	@AliasFor("name")
	String value() default "";

	@AliasFor("value")
	String name() default "";
	
	boolean binding() default true;
}
  • name() : 表示model中的属性名
  • binding() : 表示在参数解析时是否需要执行该属性的databind操作,默认是true

@ModelAttribute必须用在@Controller或者@ControllerAdvice注解的类上,否则SpringMVC收集不到。

用在方法上

@ModelAttribute用在方法上有2个作用:

1 绑定返回值到model的属性上,属性名或由@ModelAttribute,或根据方法返回类型生成。 例如:mypackage.OrderAddress 生成的名字是 orderAddress;List<mypackage.OrderAddress>生成的名字是orderAddressList。

2 如果@ModelAttribute所注解的方法上没有@RequestMapping注解,那么该方法将在请求的处理方法前执行。除了返回值将绑到model上,开发者还可以对model进行一些处理

示例一  没有@RequestMapping,不指定name

定义一个测试类

public class TestModelAttribute {

    private String  testName;

    private String testSource;


    public String getTestName() {
        return testName;
    }

    public void setTestName(String testName) {
        this.testName = testName;
    }

    public String getTestSource() {
        return testSource;
    }

    public void setTestSource(String testSource) {
        this.testSource = testSource;
    }
}

添加一个@ModuleAttribute注解的方法,@ModuleAttribute没有指定name,预期结果是model中增加一个属性,属性名根据TestModelAttribute类名生成得到

@ControllerAdvice
public class DemoControllerAdvice {


    @ModelAttribute
    public TestModelAttribute testInitModel() {
        TestModelAttribute result = new TestModelAttribute();
        result.setTestName("test");
        result.setTestSource("h5");
        return result;
    }

}

运行结果:model里面增加了属性名为"testModelAttribute"的属性

示例二  没有@RequestMapping,通过ModelMap直接向model添加更多的属性

@ControllerAdvice
public class DemoControllerAdvice {


    @ModelAttribute
    public void testInitModel(ModelMap model) {
        model.put("test1", "value1");
        model.put("test2", "value2");
        model.put("test3", "value3");
    }

}

 

用在参数上

     @ModelAttribute用在参数上主要用来进行参数解析,@ModelAttribute对应的参数解析器org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor。过程是将model中name对应的对象赋值给参数,如果该name没有被设置"bindingDisabled",那么将从reques取得数据绑定到参数对象中。

    @ModelAttribute在参数上非必须,即便没有@ModelAttribute注解,只要参数类型是非简单类型,SpringMVC的参数解析器ServletModelAttributeMethodProcessor也会执行上述操作,只不过此时属性name就只能根据参数类型生成。

示例一 有注解@ModelAttribute,并指定name

先在testInitModel中指定name

@ModelAttribute(name = "test")
    public TestModelAttribute testInitModel() {
        TestModelAttribute result = new TestModelAttribute();

        result.setTestName("testName");
        result.setTestSource("H5");

        return result;
    }

在请求的处理方法中增加参数TestModelAttribute,添加@ModelAttribute注解并指定name

@Controller
@RequestMapping("/focuse")
public class DemoController {

    @ResponseBody
    @RequestMapping("hello")
    public String hello(@ModelAttribute(name = "test") TestModelAttribute input) {
        return "hello world!";
    }

}

运行结果-input值来源于model中属性名为"test"的对象

 

示例二 没有注解@ModelAttribute,请求指定参数testName

请求的处理方法上增加TestModelAttribute参数,但是没有注解@ModelAttribute

@Controller
@RequestMapping("/focuse")
public class DemoController {

    @ResponseBody
    @RequestMapping("hello")
    public String hello(TestModelAttribute input) {
        return "hello world!";
    }

}

请求指定参数testName=WithoutAnnotation:127.0.0.1:8080/focuse/hello?testName=WithoutAnnotation

 

总结

在方法上使用场景

场景方法是否有@RequestMapping是否指定name效果
方法上没有指定

在调用请求处理方法前,往model添加指定name的属性,

并根据注解@ModelAttribute的binding属性设置该属性对应的参数是否需要绑定数据

没有不指定

在调用请求处理方法前,往model添加属性,属性的名字根据方法返回类型生成,

并根据注解@ModelAttribute的binding属性设置该属性是否需要绑定数据

指定

在调用请求处理方法之后,往model添加指定name的属性,

并根据注解@ModelAttribute的binding属性设置该属性是否需要绑定数据

不指定

在调用请求处理方法之后,往model添加属性,属性的名字根据方法返回类型生成,

并根据注解@ModelAttribute的binding属性设置该属性是否需要绑定数据

在参数上使用场景

场景是否有注解@ModelAttribute是否指定name效果
参数上没有/

1. 从model取出属性赋值给该参数,属性的名字根据参数类型生成,如果model中没有则根据参数类型创建对象。

2. 根据model中该属性的绑定设置确定是否对参数的对象执行数据绑定

 

指定

1. 从model取出属性赋值给该参数,属性的名字根据参数类型生成,如果model中没有则根据参数类型创建对象。

2. 根据注解@ModelAttribute的binding属性设置是否需要绑定数据

3. 根据model中该属性的绑定设置确定是否对参数的对象执行数据绑定

不指定

1. 从model取出属性赋值给该参数,属性的名字根据参数类型生成,如果model中没有则根据参数类型创建对象。

2. 根据注解@ModelAttribute的binding属性设置是否需要绑定数据

3. 根据model中该属性的绑定设置确定是否对参数的对象执行数据绑定



上一篇 参数解析器HandlerMethodArgumentResolver

下一篇 返回处理器HandlerMethodReturnValueHandler

再下一篇 异步请求WebAsyncManager

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值