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. Linux下设置和查看环境变量

    Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1 永久的:需要修改配置文件,变量永久生效. 2 临时的:使用export命令声明即可,变量在关闭shell时失效. 设置变量 ...

  2. 调用wx.request接口时需要注意的几个问题

    写在前面 之前写了一篇<微信小程序实现各种特效实例>,上次的小程序的项目我负责大部分前端后台接口的对接,然后学长帮我改了一些问题.总的来说,收获了不少吧! 现在项目已经完成,还是要陆陆续续 ...

  3. React笔记-事件注册

    事件机制 本系列以React v16.8.3为基础进行源码分析 React事件主要分为两部分: 事件注册与事件分发.下面先从事件注册说起. 事件注册 假设我们的程序如下: <!DOCTYPE h ...

  4. 《Deep Learning》(深度学习)中文版PDF免费下载

    <Deep Learning>(深度学习)中文版PDF免费下载 "深度学习"经典著作<Deep Learning>中文版pdf免费下载. <Deep ...

  5. PAT甲题题解-1106. Lowest Price in Supply Chain (25)-(dfs计算树的最小层数)

    统计树的最小层数以及位于该层数上的叶子节点个数即可. 代码里建树我用了邻接链表的存储方式——链式前向星,不了解的可以参考,非常好用: http://www.cnblogs.com/chenxiwenr ...

  6. VS社区版 使用 OpenCover 获取测试代码覆盖率

    注:暂不支持VS2017 Visual Studio 2015 社区版没有集成代码覆盖率的功能,所以想在VS社区版中获取单元测试的代码覆盖率等数据,需要使用到插件 OpenCover. 下载 Open ...

  7. Vivado绑定外部verilog编辑器

    前言 由于Vivado自带的verilog编辑器确实难用,写起来效率不高,因而寻找到了以下教程. 解决方案 引用sublime作为vivado外部verilog编辑器 sublime text中文编码 ...

  8. 使用VS2013进行C#程序的单元测试

    没有按照预期的那样做出成功的单元测试,磕磕绊绊参照了下面两篇博客大致做出来了,所以很有必要记录一下过程. http://www.cnblogs.com/duasonir/p/5299732.html( ...

  9. 在iOS9 中使用3D Touch

    iOS9提供了四类API( Home Screen Quick Action . UIKit Peek & Pop . WebView Peek & Pop 和 UITouch For ...

  10. ElasticSearch 2 (7) - 基本概念

    ElasticSearch 2 (7) - 基本概念 摘要 ElasticSearch的一些基本核心概念,理解这些概念有助于ElasticSearch的学习 准实时NRT(Near Realtime) ...