Spring MVC 中 @ModelAttribute 注解的妙用

Spring MVC 提供的这种基于注释的编程模型,极大的简化了 web 应用的开发。其中 @Controller@RestController 注解的组件使用 @RequestMapping@ExceptionHandler 等注解来表示请求映射,请求输入,异常处理等,使得开发者能专注于业务逻辑的编写,提高了开发效率。 带注释的控制器具有灵活的方法签名,不必扩展基类,也不需要实现特定的接口。

可以使用 ServletWebApplicationContext 中的标准 Spring bean 定义来定义控制器 bean。 所有带有 @Controller 注解的类会被自动检测,就像 Spring 通常的扫描方式一样,检测类路径中的 @Component 类,并为它们自动注册 bean 定义。 它也充当注释类的刻板,表示它可以作为一个 Web 组件。

带有 @RequestMapping 注解的方法叫做 Handler Method - 处理器方法,它的参数可以来自很多地方,比如 ServletRequestServletResponseHttpSession 等。

@ModelAttribute

在控制器的处理器方法参数上添加 @ModelAttribute 注释可以访问模型中的属性,如果不存在这个模型,则会自动将其实例化,产生一个新的模型。 模型属性还覆盖了来自 HTTP Servlet 请求参数的名称与字段名称匹配的值,也就是请求参数如果和模型类中的域变量一致,则会自动将这些请求参数绑定到这个模型对象,这被称为数据绑定,从而避免了解析和转换每个请求参数和表单字段这样的代码。 例如:

@PostMapping("/componies/{componyId}/departments/{departmentId}/edit")
public String processSubmit(@ModelAttribute Department department) { }

这个处理器方法中的 department 参数会被从以下几个来源进行匹配绑定:

  • 已经定义过的模型方法(带有 @ModelAttribute 的方法,后面解释)
  • HTTP Session 中和字段名匹配的会话方法(带有 @SessionAttribute 的方法,和模型方法类似,只是作用域不同)
  • 经过 URL 转换器解析过的路径变量
  • 该模型类的默认构造方法
  • 调用具有与 Servlet 请求参数匹配的参数的 “主构造函数”; 参数名称通过 JavaBeans @ConstructorProperties 或通过字节码中的运行时保留参数名称确定。

虽然一般都是使用模型方法 Model method 来使用属性填充模型,但另一种方法是依靠 Converter<String,T> 识别 URI 路径变量来绑定。在下面的例子中,模型属性名称 “user” 与 URI 路径变量 “user” 匹配,并且通过将 String 类型的用户名交给给已注册的 Converter<String,User> 这个转换器来生成创建模型:

@PutMapping("/users/{user}")
public String saveUser(@ModelAttribute("user") User user) {
// ...
}

在获得模型属性实例之后,请求数据就会被绑定到模型属性上。 WebDataBinder 负责将 Servlet 请求参数名称(查询参数或表单字段)和目标模型对象上的字段名称进行匹配。 必要时会将属性的类型进行转换后再填充对应字段。

数据绑定不能保证不会出错,发生错误时默认情况下会抛出 BindException 异常,但要在处理器方法中识别出这些错误,需要在 @ModelAttribute 后面添加一个 BindingResult 类型的参数,需要注意的是:这个参数必须和模型属性参数 (@ModelAttribute 参数)相邻,如下所示:

@PostMapping("/owners/{componyId}/departments/{departmentId}/edit")
public String processSubmit(@ModelAttribute("compony") Compony compony, BindingResult result) {
if (result.hasErrors()) {
return "componyForm";
}
// ...
}

这个例子表示如果用户提交的表单不符合预期的匹配规则,就会返回视图 componyForm

有时候我们需要获得一个不带数据绑定的模型属性,也就是需要在处理器方法中使用 new 关键字来实例化一个对象。但是在 Spring MVC 中就不用这么麻烦了,我们可以将模型注入控制器并直接访问它,或者可以添加 @ModelAttribute(binding = false) 来表示不需要绑定数据,如下所示:

@ModelAttribute
public UserForm setUpForm() {
return new UserForm();
} @ModelAttribute

public User findUser(@PathVariable String userId) {

return userRepository.findOne(userId);

} @PostMapping("update")

public String update(@Valid UserUpdateForm form, BindingResult result,

@ModelAttribute(binding=false) User user) {

// ...

}

在参数上添加 javax.validation.Valid 注解或 Spring 的 @Validated 注解,就可以在数据绑定后使用字段校验功能了,就像这样:

@PostMapping("/componies/{componyId}/departments/{departmentId}/edit")
public String processSubmit(@Valid @ModelAttribute("department") Department department, BindingResult result) {
if (result.hasErrors()) {
return "departmentForm";
}
// ...
}

这样写和在方法体中写 model.addAttribute("compony",compony) 是等价的。

需要注意的是 @ModelAttribute 注解如果不加,按照 BeanUtils 中的 isSimpleProperty 方法来判断,如果不属于简单类型的参数,都会被自动视为 ModelAttribute

欢迎访问 郑保乐的博客

      </div>
</div>
</div>
posted @
2019-02-26 17:13 
星朝 
阅读(...) 
评论(...) 
编辑 
收藏

Spring MVC 中 @ModelAttribute 注解的妙用的更多相关文章

  1. Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法

    Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法 在Action中方法的返回值都是字符串行,一般情况是返回某个JSP,如: return "xx" ...

  2. spring 以及 spring mvc 中常用注解整理

    spring 以及 spring mvc 中常用注解整理 @RequestMapping(映射路径) @Autowired(注入 bean 对象) 例如: @Autowired private Bas ...

  3. Spring MVC中基于注解的 Controller

         终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法以响 ...

  4. 0001 - Spring MVC中的注解

    1.概述 Spring MVC框架提供了功能强大的注解,大大简化了代码开发的同时也提升了程序的可扩展性 2.注解 2.1.@RequestMapping Spring MVC通过@RequestMap ...

  5. Spring MVC中@RequestMapping注解使用技巧(转)

    @RequestMapping是Spring Web应用程序中最常被用到的注解之一.这个注解会将HTTP请求映射到MVC和REST控制器的处理方法上. 在这篇文章中,你将会看到@RequestMapp ...

  6. 在Spring MVC中使用注解的方式校验RequestParams

    概述   Spring MVC支持Bean Validation,通过这个验证技术,可以通过注解方式,很方便的对输入参数进行验证,之前使用的校验方式,都是基于Bean对象的,但是在@RequestPa ...

  7. Spring MVC中@ControllerAdvice注解实现全局异常拦截

    在网上很多都把Advice翻译成增强器,其实从翻译工具上看到,这个单词翻译是忠告,通知的意思. 首先这个注解实在Spring Web包下,而Spring MVC离不开Spring Web的依赖,所以经 ...

  8. spring mvc之@ModelAttribute注解

    1.@ModelAttribute注释void返回值的方法 @Controller public class HelloModelController { @ModelAttribute public ...

  9. Spring MVC SessionAttributes ModelAttribute注解

    说明 本文主要针对 @SessionAttributes注解 和 @ModelAttribute注解的基础用法进行解析.至于为什么会将这两个注解放在一起,是因为它们之间还是有点影响的. @Sessio ...

随机推荐

  1. pandas 初识(三)

    Python Pandas 空值 pandas 判断指定列是否(全部)为NaN(空值) import pandas as pd import numpy as np df = pd.DataFrame ...

  2. ELK日志方案--使用Filebeat收集日志并输出到Kafka

    1,Filebeat简介 Filebeat是一个使用Go语言实现的轻量型日志采集器.在微服务体系中他与微服务部署在一起收集微服务产生的日志并推送到ELK. 在我们的架构设计中Kafka负责微服务和EL ...

  3. JWT总结

    Json web token (JWT) 什么是JWT? Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该toke ...

  4. Windos 下python2.7安装 pymssql 解决方案

    最近在学python,到安装pymssql这一块遇到了不少问题. 第一:如何安装python 模块,也是最主要的问题. 可以这么理解:在安装python其它模块之前,可以先安装一个负责安装模块的模块. ...

  5. YOLO(You Only Look Once)

    参考 YOLO(You Only Look Once)算法详解 YOLO算法的原理与实现 一.介绍 YOLO算法把物体检测问题处理成回归问题,用一个卷积神经网络结构就可以从输入图像直接预测boundi ...

  6. 开源中文分词框架分词效果对比smartcn与IKanalyzer

    一.引言: 中文分词一直是自然语言处理的一个痛处,早在08年的时候,就曾经有项目涉及到相关的应用(Lunce构建全文搜索引擎),那时的痛,没想到5年后的今天依然存在,切分效果.扩展支持.业务应用等方面 ...

  7. 原生 js 封装get ,post, delete 请求

    现在的项目中都在用VUE 以及react 等MVC, MVVM  框架. 丢弃了原始的JQ .不可能为了个$.ajax();而把JQ引进来吧. 在vue1的开发中 提供了 vueResouce, vu ...

  8. php多进程pcntl学习(一)

    pcntl在windows下无法使用,linux编译php时加上参数--enable-pcntl 即可.第一次使用pcntl模块,遇到了一些坑也慢慢填上了,这里简单记录下. 1. 子进程之间变量无法共 ...

  9. 关于C++内联函数

    关于C++内联函数有以下实验: 有三段测试代码 1.手动展开内联函数. 2.非内联函数. 3.inline标记的内联函数.(函数只有一行代码,以确保函数被内联) 测试三种情况: VS工程在Releas ...

  10. php 有意思的小题

    /** * 你的是一个数字和一个字符串进行比较,PHP会把字符串转换成数字再进行比较.* PHP转换的规则的是:若字符串以数字开头,则取开头数字作为转换结果,若无则输出0.***/1)$a =”abc ...