一、什么时候使用@NotBlank注解
在Spring项目中,微服务之间常采用Restful接口。那么问题来了,当前段调用后端接口,或者后端微服务接口被其它微服务调用时,我们不可能只依赖接口调用方对参数准确性进行检查,接口提供方也需要在入口对参数准确进行检查。
如:接口中关键参数是个一个员工对象Employee为例,员工对象实体类定义如下:
public class Employee {
/** 姓名 */
public String name;
/** 年龄 */
public Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Contoller中定义一个增加员工的add接口,如下:
@Controller
public class TestController {
@RequestMapping("/add")
@ResponseBody
public String add(Employee employee) {
//TODO 保存到数据库
return "新增员工成功";
}
}
现在,我们需要对接口参数进行检查,需员工的名称不能为空、且长度不超过10个字符,如何做呢?Controller中增加判断如下:
@Controller
public class TestController {
@RequestMapping("/add")
@ResponseBody
public String add(Employee employee) {
String name = employee.getName();
if(name == Null || name.trim().length() == 0) {
return "员工名称不能为空";
}
if(name.trim().length() > 0) {
return "员工名称不能超过10个字符";
}
//TODO 保存到数据库
return "新增员工成功";
}
}
运行测试,可以发现检查结果符合预期。
现在,我们又需要增加对员工年龄的限制,必须在20~50岁。怎么办呢?继续在Controller中添加判断:
@Controller
public class TestController {
@RequestMapping("/add")
@ResponseBody
public String add(Employee employee) {
String name = employee.getName();
if(name == Null || name.trim().length() == 0) {
return "员工名称不能为空";
}
if(name.trim().length() > 0) {
return "员工名称不能超过10个字符";
}
Integer age = employee.getAge();
if(age == Null) {
return "员工年龄不能为空";
}
if(age < 20 || age > 50) {
return "员工年龄不能小于20或大于50";
}
//TODO 保存到数据库
return "新增员工成功";
}
}
那么问题来了,现在员工对象Employee就2个字段,我们就写了10多行的代码验证,要是有20个字段,岂不是要写100多行代码?通常来说,当一个方法中的无效业务代码量过多时,往往代码设计有问题,当然这不是我们所想看到都结果。
有人会说,把对应的校验过程抽象成独立的验证方法吧:
@Controller
public class TestController {
@RequestMapping("/add")
@ResponseBody
public String add(Employee employee) {
String result = vaild(employee);
if(result != Null) {
return result ;
}
//TODO 保存到数据库
return "新增员工成功";
}
}
String valid(Employee employee) {
String name = employee.getName();
if(name == Null || name.trim().length() == 0) {
return "员工名称不能为空";
}
if(name.trim().length() > 0) {
return "员工名称不能超过10个字符";
}
Integer age = employee.getAge();
if(age == Null) {
return "员工年龄不能为空";
}
if(age < 20 || age > 50) {
return "员工年龄不能小于20或大于50";
}
return null;
}
这样来看,我们的Controller业务方法就清爽多了。但本质上编码量没有减少,只是换了位置封装。
Spring提供的@NotBlank、@valid很好实现如上消息valid检查
- 使用@valid首先要要引入其依赖
- 如果是SpringBoot项目,引入web开发包,就不需要再单独引入@valid依赖了、因为他存在于Web开发包中的最核心之中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
- 如果不是SpringBoot项目,要在Maven的Pom中显式引入@valid依赖,如下:
//方法1
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
//方法2
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.1.Final</version>
</dependency>
- 引入依赖后,如何使用呢?
- 在Employee实体类上加上注解:
public class Employee {
/** 姓名 */
@NotBlank(message = "请输入名称")
@Length(message = "名称不能超过个 {max} 字符", max = 10)
public String name;
/** 年龄 */
@NotNull(message = "请输入年龄")
@Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
public Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
- 在Controller对应的参数上,加上@valid注解,如下:
public class TestController {
@RequestMapping("/add")
@ResponseBody
public String add(@valid Employee employee) {
//TODO 保存到数据库
return "新增员工成功";
}
}
此时,Controller方法就会对@valid注解的参数 根据 类中的@NotBlank等注解进行检查,检查失败,返回注解中message指定的消息。效果与前面自己写代码检查一致。
【注】:@NotBlank等注解时,一定要和@valid一起使用,不然@NotBlank不起作用。
- 既然对参数进行了检查,就肯定会有检查结果。如果我们需要用一个东西来存放验证结果,做法也很简单,在参数直接添加一个BindingResult。如下:
public class TestController {
@RequestMapping("/add")
@ResponseBody
public String add(@valid Employee employee, BindingResult bindingResult) {
//TODO 保存到数据库
return "新增员工成功";
}
}
*如果想获取保存的验证结果,样例如下:
public class TestController {
@RequestMapping("/add")
@ResponseBody
public String add(@valid Employee employee, BindingResult bindingResult) {
//检查所有字段是否验证通过
if(bindingResult.hasErrors()) {
//验证失败,返回第一条错误信息
return bindingResult.getALLErrors().get(0).getDefaultMessage();
}
//TODO 保存到数据库
return "新增员工成功";
}
}
二、类似@NotBlank使用方式的注解
@NotNull:不能为null,但可以为empty
@NotEmpty:不能为null,而且长度必须大于0
@NotBlank:只能作用在String上,不能为null,而且调用trim()后,长度必须大于0。(trim()删除字符串的头尾空白符)
样例辅助理解:
1.String name = null;则注解检查结果:
@NotNull: false
@NotEmpty:false
@NotBlank:false
2.String name = "";则注解检查结果:
@NotNull:true
@NotEmpty: false
@NotBlank: false
3.String name = " ";则注解检查结果:
@NotNull: true
@NotEmpty: true
@NotBlank: false
4.String name = "Great answer!";则注解检查结果:
@NotNull: true
@NotEmpty:true
@NotBlank:true
其他注解:
@Length(message = "名称不能超过个 {max} 字符", max = 10)
public String name;
/** 年龄 */
@Range(message = "年龄范围为 {min} 到 {max} 之间",min = 1,max = 100)
public Integer age;
@Size(message = "兴趣最多选择{max}个", max = 5)
private List<String> hobbyList;
注意:@Email注解报红 是因为新版本需要validation启动器
解决方法:在pom.xml 加入下面依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>