Spring中的@Valid 和 @Validated注解你用对了吗
1.概述
本文我们将重点介绍Spring中 @Valid和@Validated注解的区别 。
验证用户输入是否正确是我们应用程序中的常见功能。Spring提供了@Valid和@Validated两个注解来实现验证功能,下面我们来详细介绍它们。
2. @Valid和@Validate注解
在Spring中,我们使用@Valid 注解进行方法级别验证,同时还能用它来标记成员属性以进行验证。
但是,此注释不支持分组验证。@Validated则支持分组验证。
3.例子
让我们考虑一个使用Spring Boot开发的简单用户注册表单。首先,我们只有名称和密码属性:
public class UserAccount {
@NotNull
@Size(min = 4, max = 15)
private String password;
@NotBlank
private String name;
// standard constructors / setters / getters / toString
}
接下来,让我们看一下控制器。在这里,我们将使用带有@Valid批注的saveBasicInfo方法来验证用户输入:
@RequestMapping(value = "/saveBasicInfo", method = RequestMethod.POST)
public String saveBasicInfo(
@Valid @ModelAttribute("useraccount") UserAccount useraccount,
BindingResult result,
ModelMap model) {
if (result.hasErrors()) {
return "error";
}
return "success";
}
现在让我们测试一下这个方法:
@Test
public void givenSaveBasicInfo_whenCorrectInput`thenSuccess() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfo")
.accept(MediaType.TEXT_HTML)
.param("name", "test123")
.param("password", "pass"))
.andExpect(view().name("success"))
.andExpect(status().isOk())
.andDo(print());
}
在确认测试成功运行之后,现在让我们扩展功能。下一步的逻辑步骤是将其转换为多步骤注册表格,就像大多数向导一样。第一步,名称和密码保持不变。在第二步中,我们将获取其他信息,例如age 和 phone。因此,我们将使用以下其他字段更新域对象:
public class UserAccount {
@NotNull
@Size(min = 4, max = 15)
private String password;
@NotBlank
private String name;
@Min(value = 18, message = "Age should not be less than 18")
private int age;
@NotBlank
private String phone;
// standard constructors / setters / getters / toString
}
但是,这一次,我们将注意到先前的测试失败。这是因为我们没有传递年龄和电话字段。
为了支持此行为,我们引入支持分组验证的@Validated批注。
分组验证,就是将字段分组,分别验证,比如我们将用户信息分为两组:BasicInfo和AdvanceInfo
可以建立两个空接口:
public interface BasicInfo {
}
public interface AdvanceInfo {
}
第一步将具有BasicInfo接口,第二步 将具有AdvanceInfo 。此外,我们将更新UserAccount类以使用这些标记接口,如下所示:
public class UserAccount {
@NotNull(groups = BasicInfo.class)
@Size(min = 4, max = 15, groups = BasicInfo.class)
private String password;
@NotBlank(groups = BasicInfo.class)
private String name;
@Min(value = 18, message = "Age should not be less than 18", groups = AdvanceInfo.class)
private int age;
@NotBlank(groups = AdvanceInfo.class)
private String phone;
// standard constructors / setters / getters / toString
}
另外,我们现在将更新控制器以使用@Validated注释而不是@Valid:
@RequestMapping(value = "/saveBasicInfoStep1", method = RequestMethod.POST)
public String saveBasicInfoStep1(
@Validated(BasicInfo.class)
@ModelAttribute("useraccount") UserAccount useraccount,
BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "error";
}
return "success";
}
更新后,再次执行测试,现在可以成功运行。现在,我们还要测试这个新方法:
@Test
public void givenSaveBasicInfoStep1`whenCorrectInput`thenSuccess() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfoStep1")
.accept(MediaType.TEXT_HTML)
.param("name", "test123")
.param("password", "pass"))
.andExpect(view().name("success"))
.andExpect(status().isOk())
.andDo(print());
}
也成功运行!
接下来,让我们看看@Valid对于触发嵌套属性验证是必不可少的。
4.使用@Valid批注标记嵌套对象
@Valid 可以用于嵌套对象。例如,在我们当前的场景中,让我们创建一个 UserAddress 对象:
public class UserAddress {
@NotBlank
private String countryCode;
// standard constructors / setters / getters / toString
}
为了确保验证此嵌套对象,我们将使用@Valid批注装饰属性:
public class UserAccount {
//...
@Valid
@NotNull(groups = AdvanceInfo.class)
private UserAddress useraddress;
// standard constructors / setters / getters / toString
}
5. 总结
@Valid保证了整个对象的验证, 但是它是对整个对象进行验证,当仅需要部分验证的时候就会出现问题。 这时候,可以使用@Validated 进行分组验证。
参考
作者:Jadepeng
出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
Spring中的@Valid 和 @Validated注解你用对了吗的更多相关文章
- Spring 中的事务操作、注解、以及 XML 配置
事务 事务全称叫数据库事务,是数据库并发控制时的基本单位,它是一个操作集合,这些操作要么不执行,要么都执行,不可分割.例如我们的转账这个业务,就需要进行数据库事务的处理. 转账中至少会涉及到两条 SQ ...
- 在spring中常被忽视的注解 @Primary
在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的. 但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary ...
- Spring中Bean管理的常用注解
在Spring中,主要用于管理bean的注解分为四大类:1.用于创建对象.2.用于给对象的属性注入值.3.用于改变作用的范围.4.用于定义生命周期.这几个在开发中经常接触到,也可以说每天都会遇见.其中 ...
- Spring 中基于 AOP 的 @AspectJ注解实例
@AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格.通过在你的基于架构的 XML 配置文件中包含以下元素,@AspectJ 支持是可用的 ...
- Spring中声明式事务的注解@Transactional的参数的总结(REQUIRED和REQUIRES_NEW的与主方法的回滚问题)
一.事务的传播行为1.介绍 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行.2.属性 事务的传播行为可以由传 ...
- 在使用spring中的ContextConfiguration、test注解时出现的错误
错误: 在使用测试注解时出现ContextConfiguration注解和test注解无法正常导包使用的编译异常,如图: 解决办法: 将pom.xml文件中以下依赖管理 中的<scope> ...
- spring中xml配置方式和注解annoation方式(包括@autowired和@resource)的区别
xml文件中配置itemSqlParameterSourceProvider是可以的: <bean id="billDbWriter" class="com.aa. ...
- Spring中的@response和@request注解
@response 标注对象返回的格式为json文本 @requestBody将json对象转换为对应的java类
- spring中使用@PostConstruct和@PreConstruct注解
1.@PostConstruct说明 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法.被@PostCo ...
随机推荐
- HTML引入外部字体
HTML5如何引入外部字体 背景 现在我需要 "Montserrat-ExtraLight ExtraLight"类型的字体,但是html的font-family中找不到这个类型的 ...
- 使用 open 函数 写的代码 用户名登录
先创建文件ha.log 内容: aaa$$123bbb$$456 def dl(user,pas): f = open('ha.log', 'r', encoding="utf-8" ...
- Linux下yum下载依赖包
先安装依赖包yum-plugin-downloadonly [root@node1 ~]# yum install yum-plugin-downloadonly 方法一: [root@node1 ~ ...
- gnuplot取消曲线标题
plot 'File.dat' using 1:2 notitle或者 plot 'File.dat' using 1:2 title ""
- Shell变量、函数
上篇文章初步认识了一下shell脚本及其简单的案例,下面我们再来讲一下shell的进击部分. 一.变量 1.常用系统变量:($HOME.$SHELL.$PWD.$USER) 2.自定义变量: 2.1. ...
- vue实现点击样式高亮
•在data中定义即将渲染的数据,及active data() { return { active:'',//选中样式 }; }, 1 2 3 4 5 6 7 8 9 ...
- MySQL高可用(一)主备同步:MySQL是如何保证主备一致的
主备同步,也叫主从复制,是MySQL提供的一种高可用的解决方案,保证主备数据一致性的解决方案. 在生产环境中,会有很多不可控因素,例如数据库服务挂了.为了保证应用的高可用,数据库也必须要是高可用的. ...
- vue element ui 上传 请求接口
在页面上 http-request: 覆盖默认的上传行为,可以自定义上传的实现 <el-upload class="avatar-uploader" action=&qu ...
- Attention & Transformer
Attention & Transformer seq2seq; attention; self-attention; transformer; 1 注意力机制在NLP上的发展 Seq2Seq ...
- Angular实战之使用NG-ZORRO创建一个企业级中后台框架
前言: 在之前的一篇文章已经介绍过了,公司正在使用NG-ZORRO组件库开发后台应用,并且详细的介绍了Angular开发环境的搭建和项目的创建.这篇文章就是为了让大家熟悉了解我们该如何在Angular ...