Spring MVC 中 @ModelAttribute 注解的妙用
Spring MVC 中 @ModelAttribute 注解的妙用
Spring MVC 提供的这种基于注释的编程模型,极大的简化了 web 应用的开发。其中 @Controller 和 @RestController 注解的组件使用 @RequestMapping、 @ExceptionHandler 等注解来表示请求映射,请求输入,异常处理等,使得开发者能专注于业务逻辑的编写,提高了开发效率。 带注释的控制器具有灵活的方法签名,不必扩展基类,也不需要实现特定的接口。
可以使用 Servlet 的 WebApplicationContext 中的标准 Spring bean 定义来定义控制器 bean。 所有带有 @Controller 注解的类会被自动检测,就像 Spring 通常的扫描方式一样,检测类路径中的 @Component 类,并为它们自动注册 bean 定义。 它也充当注释类的刻板,表示它可以作为一个 Web 组件。
带有 @RequestMapping 注解的方法叫做 Handler Method - 处理器方法,它的参数可以来自很多地方,比如 ServletRequest 、 ServletResponse 、 HttpSession 等。
@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>
Spring MVC 中 @ModelAttribute 注解的妙用的更多相关文章
- Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法
Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法 在Action中方法的返回值都是字符串行,一般情况是返回某个JSP,如: return "xx" ...
- spring 以及 spring mvc 中常用注解整理
spring 以及 spring mvc 中常用注解整理 @RequestMapping(映射路径) @Autowired(注入 bean 对象) 例如: @Autowired private Bas ...
- Spring MVC中基于注解的 Controller
终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法以响 ...
- 0001 - Spring MVC中的注解
1.概述 Spring MVC框架提供了功能强大的注解,大大简化了代码开发的同时也提升了程序的可扩展性 2.注解 2.1.@RequestMapping Spring MVC通过@RequestMap ...
- Spring MVC中@RequestMapping注解使用技巧(转)
@RequestMapping是Spring Web应用程序中最常被用到的注解之一.这个注解会将HTTP请求映射到MVC和REST控制器的处理方法上. 在这篇文章中,你将会看到@RequestMapp ...
- 在Spring MVC中使用注解的方式校验RequestParams
概述 Spring MVC支持Bean Validation,通过这个验证技术,可以通过注解方式,很方便的对输入参数进行验证,之前使用的校验方式,都是基于Bean对象的,但是在@RequestPa ...
- Spring MVC中@ControllerAdvice注解实现全局异常拦截
在网上很多都把Advice翻译成增强器,其实从翻译工具上看到,这个单词翻译是忠告,通知的意思. 首先这个注解实在Spring Web包下,而Spring MVC离不开Spring Web的依赖,所以经 ...
- spring mvc之@ModelAttribute注解
1.@ModelAttribute注释void返回值的方法 @Controller public class HelloModelController { @ModelAttribute public ...
- Spring MVC SessionAttributes ModelAttribute注解
说明 本文主要针对 @SessionAttributes注解 和 @ModelAttribute注解的基础用法进行解析.至于为什么会将这两个注解放在一起,是因为它们之间还是有点影响的. @Sessio ...
随机推荐
- Linux下设置和查看环境变量
Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1 永久的:需要修改配置文件,变量永久生效. 2 临时的:使用export命令声明即可,变量在关闭shell时失效. 设置变量 ...
- 调用wx.request接口时需要注意的几个问题
写在前面 之前写了一篇<微信小程序实现各种特效实例>,上次的小程序的项目我负责大部分前端后台接口的对接,然后学长帮我改了一些问题.总的来说,收获了不少吧! 现在项目已经完成,还是要陆陆续续 ...
- React笔记-事件注册
事件机制 本系列以React v16.8.3为基础进行源码分析 React事件主要分为两部分: 事件注册与事件分发.下面先从事件注册说起. 事件注册 假设我们的程序如下: <!DOCTYPE h ...
- 《Deep Learning》(深度学习)中文版PDF免费下载
<Deep Learning>(深度学习)中文版PDF免费下载 "深度学习"经典著作<Deep Learning>中文版pdf免费下载. <Deep ...
- PAT甲题题解-1106. Lowest Price in Supply Chain (25)-(dfs计算树的最小层数)
统计树的最小层数以及位于该层数上的叶子节点个数即可. 代码里建树我用了邻接链表的存储方式——链式前向星,不了解的可以参考,非常好用: http://www.cnblogs.com/chenxiwenr ...
- VS社区版 使用 OpenCover 获取测试代码覆盖率
注:暂不支持VS2017 Visual Studio 2015 社区版没有集成代码覆盖率的功能,所以想在VS社区版中获取单元测试的代码覆盖率等数据,需要使用到插件 OpenCover. 下载 Open ...
- Vivado绑定外部verilog编辑器
前言 由于Vivado自带的verilog编辑器确实难用,写起来效率不高,因而寻找到了以下教程. 解决方案 引用sublime作为vivado外部verilog编辑器 sublime text中文编码 ...
- 使用VS2013进行C#程序的单元测试
没有按照预期的那样做出成功的单元测试,磕磕绊绊参照了下面两篇博客大致做出来了,所以很有必要记录一下过程. http://www.cnblogs.com/duasonir/p/5299732.html( ...
- 在iOS9 中使用3D Touch
iOS9提供了四类API( Home Screen Quick Action . UIKit Peek & Pop . WebView Peek & Pop 和 UITouch For ...
- ElasticSearch 2 (7) - 基本概念
ElasticSearch 2 (7) - 基本概念 摘要 ElasticSearch的一些基本核心概念,理解这些概念有助于ElasticSearch的学习 准实时NRT(Near Realtime) ...