前言

在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等,写这些与业务逻辑关系不大的代码个人感觉有两个麻烦:

  • 验证代码繁琐,重复劳动
  • 方法内代码显得冗长
  • 每次要看哪些参数验证是否完整,需要去翻阅验证逻辑代码

hibernate validator(官方文档)提供了一套比较完善、便捷的验证实现方式。

spring-boot-starter-web包里面有hibernate-validator包,不需要引用hibernate validator依赖。

一、常见的注解

Bean Validation 中内置的 constraint     
@Null   被注释的元素必须为 null     
@NotNull    被注释的元素必须不为 null     
@AssertTrue     被注释的元素必须为 true     
@AssertFalse    被注释的元素必须为 false     
@Min(value)     被注释的元素必须是一个数字,其值必须大于等于指定的最小值     
@Max(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值     
@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值     
@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值     
@Size(max=, min=)   被注释的元素的大小必须在指定的范围内     
@Digits (integer, fraction)     被注释的元素必须是一个数字,其值必须在可接受的范围内     
@Past   被注释的元素必须是一个过去的日期     
@Future     被注释的元素必须是一个将来的日期     
@Pattern(regex=,flag=)  被注释的元素必须符合指定的正则表达式     
Hibernate Validator 附加的 constraint     
@NotBlank(message =)   验证字符串非null,且长度必须大于0     
@Email  被注释的元素必须是电子邮箱地址     
@Length(min=,max=)  被注释的字符串的大小必须在指定的范围内     
@NotEmpty   被注释的字符串的必须非空     
@Range(min=,max=,message=)  被注释的元素必须在合适的范围内

二、hibernate validator校验demo

先来看一个简单的demo

public class StudentDto {
@NotBlank(message="名称不能为空")
private String name;
@NotBlank(message="年级不能为空")
@Pattern(regexp="^[0-9]{1,2}$",message="年级不正确")
private String grade;
@Min(value=,message="年龄必须大于6")
@Max(value=,message="年龄必须小于12")
private int age;
@Past(message="出生日期必须是过去的日期")
private Date birthDate; ....set get方法省略
    @ApiOperation(value="hibernate validate验证")
@PostMapping("/validate")
public Object validate(@RequestBody @Valid StudentDto studentDto,BindingResult result){
Map<String,Object> retMap = new HashMap<String,Object>();
if(result.hasErrors()){
for (ObjectError error : result.getAllErrors()) {
System.out.println(error.getDefaultMessage());
}
}
return retMap;
}

post接口请求,输入

{
"age": 1,
"birthDate": "2019-12-20",
"grade": "string",
"name": "string"
}

结果输入

年级不正确
年龄必须大于6

三、hibernate的校验模式

细心的读者肯定发现了:上面例子中一次性返回了所有验证不通过的集合,通常按顺序验证到第一个字段不符合验证要求时,就可以直接拒绝请求了。Hibernate Validator有以下两种验证模式:

1、普通模式(默认是这个模式)

普通模式(会校验完所有的属性,然后返回所有的验证失败信息)

2、快速失败返回模式

快速失败返回模式(只要有一个验证失败,则返回),(hibernate.validator.fail_fast:true  快速失败返回模式    false 普通模式)

@Configuration
public class ValidatorConfiguration {
@Bean
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
//(hibernate.validator.fail_fast:true  快速失败返回模式    false 普通模式)
.addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator(); return validator;
}
}

四、hibernate的两种校验

1、@RequestBody校验

以上所述是@RequestBody校验

2、@RequestParam校验

一般在处理Get请求(或参数比较少)的时候,会使用@RequestParam校验方式:如

@ApiOperation(value="hibernate validate param验证")
@GetMapping("/validateParem")
public Object validateParam(
@RequestParam(name = "grade", required = true) int grade,
@RequestParam(name = "classroom", required = true) int classroom){
Map<String,Object> retMap = new HashMap<String,Object>();
System.out.println(grade + "," + classroom);
return retMap;
}

使用@Valid注解,对RequestParam对应的参数进行注解,是无效的,需要使用@Validated注解来使得验证生效。如下所示:

a.此时需要使用MethodValidationPostProcessor 的Bean:

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
postProcessor.setValidator(validator());
return postProcessor;
}

b.方法所在的Controller上加注解@Validated

@RestController
@Validated
public class HelloController {
@ApiOperation(value="hibernate validate param验证")
@GetMapping("/validateParem")
public Object validateParam(
@Range(min = , max = , message = "年级只能从1-9")
@RequestParam(name = "grade", required = true) int grade,
@Min(value = , message = "班级最小只能1")
@Max(value = , message = "班级最大只能99")
@RequestParam(name = "classroom", required = true) int classroom){
Map<String,Object> retMap = new HashMap<String,Object>();
System.out.println(grade + "," + classroom);
return retMap;
}
}

c.返回验证信息提示

可以看到:验证不通过时,抛出了ConstraintViolationException异常,使用同一捕获异常处理:

@ControllerAdvice
@Component
public class GlobalExceptionHandler {
@ExceptionHandler
@ResponseBody
@ResponseStatus
public String handle(ValidationException exception) {
if(exception instanceof ConstraintViolationException){
ConstraintViolationException exs = (ConstraintViolationException) exception;
Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
for (ConstraintViolation<?> item : violations) {
//打印验证不通过的信息
System.out.println(item.getMessage());
}
}
return "bad request, " ;
}
}

d.验证

浏览器发起请求  http://localhost:8080/validateParem?grade=11111&classroom=22222

配置快速失败返回的MethodValidationPostProcessor 时输出信息如下:

年级只能从1-9

3、model校验

a.需要引入的包

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

b.待校验的model

@Data
public class Demo2 {
@Length(min = , max = , message = "length长度在[5,17]之间")
private String length; /**@Size不能验证Integer,适用于String, Collection, Map and arrays*/
@Size(min = , max = , message = "size在[1,3]之间")
private String age; @Range(min = , max = , message = "range在[150,250]之间")
private int high; @Size(min = ,max = ,message = "list的Size在[3,5]")
private List<String> list;

c.验证model

@Autowired
private Validator validator; @RequestMapping("/validateModel")
public void demo3(){
Demo2 demo2 = new Demo2();
demo2.setAge("111");
demo2.setHigh();
demo2.setLength("ABCDE");
demo2.setList(new ArrayList<String>(){{add("111");add("222");add("333");}});
Set<ConstraintViolation<Demo2>> violationSet = validator.validate(demo2);
for (ConstraintViolation<Demo2> model : violationSet) {
System.out.println(model.getMessage());
}
}

b.验证

后台会打印如下信息:

range在[150,250]之间

4、对象级联校验

对象内部包含另一个对象作为属性,属性上加@Valid,可以验证作为属性的对象内部的验证:(验证Demo2示例时,可以验证Demo2的字段)

a.待验证的model Demo2,Demo3

@Data
public class Demo2 {
@Size(min = ,max = ,message = "list的Size在[3,5]")
private List<String> list; @NotNull
@Valid
private Demo3 demo3; @Data
public class Demo3 {
@Length(min = , max = , message = "length长度在[5,17]之间")
private String extField;

b.级联校验

    @Autowired
private Validator validator; @GetMapping("/validateModelCascade")
public void demo3(){
Demo2 demo2 = new Demo2();
demo2.setList(new ArrayList<String>(){{add("111");add("222");add("333");}});
Demo3 demo3 = new Demo3();
demo3.setExtField("22");
demo2.setDemo3(demo3);
Set<ConstraintViolation<Demo2>> violationSet = validator.validate(demo2);
for (ConstraintViolation<Demo2> model : violationSet) {
System.out.println(model.getMessage());
}
}

c.验证,后台打印如下:

length长度在[5,17]之间

5、分组校验

暂无

五、自定义验证器

暂无

六、参考资料

参考资料:

转自:https://www.cnblogs.com/mr-yang-localhost/p/7812038.html

引用:http://docs.jboss.org/hibernate/validator/4.2/reference/zh-CN/html_single/#validator-gettingstarted

springboot使用hibernate validator的更多相关文章

  1. springboot使用hibernate validator校验,Bean Validation校验

    第一个地址:springboot使用hibernate validator校验,Bean Validation校验

  2. springboot使用hibernate validator校验

    一.参数校验 在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等,写这些与业务逻辑关系不大的代码个人感觉有两个麻烦: 验证代码繁琐,重复劳动 方法内代码显得冗长 每次要 ...

  3. springboot使用hibernate validator校验方式

    一.参数校验 在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等,写这些与业务逻辑关系不大的代码个人感觉有两个麻烦: 验证代码繁琐,重复劳动 方法内代码显得冗长 每次要 ...

  4. SpringBoot整合Hibernate Validator实现参数验证功能

    在前后端分离的开发模式中,后端对前端传入的参数的校验成了必不可少的一个环节.但是在多参数的情况下,在controller层加上参数验证,会显得特别臃肿,并且会有许多的重复代码.这里可以引用Hibern ...

  5. Java笔记 #07# Hibernate Validator

    Hibernate Validator是Spring Boot默认附带的标准校验API(javax.validation)实现. 应用实例(配合切面) 采用注解定义切面.java @Aspect @C ...

  6. SpringBoot 2 快速整合 | Hibernate Validator 数据校验

    概述 在开发RESTFull API 和普通的表单提交都需要对用户提交的数据进行校验,例如:用户姓名不能为空,年龄必须大于0 等等.这里我们主要说的是后台的校验,在 SpringBoot 中我们可以通 ...

  7. spring 项目中使用 hibernate validator验证输入参数

    1 hibernate validator 官方文档:https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_si ...

  8. 用spring的@Validated注解和org.hibernate.validator.constraints.*的一些注解在后台完成数据校验

    这个demo主要是让spring的@Validated注解和hibernate支持JSR数据校验的一些注解结合起来,完成数据校验.这个demo用的是springboot. 首先domain对象Foo的 ...

  9. java.lang.NoClassDefFoundError: org/hibernate/validator/internal/engine/DefaultClockProvider

    ①在springboot的spring-boot-starter-web默认引入了以下依赖: <dependency> <groupId>com.fasterxml.jacks ...

随机推荐

  1. nginx反向代理 和部分优化

    准备环境  : 两台web服务     安装http  写入文档  并启动 yum -y install httpd echo "192.168.2.100" > /var/ ...

  2. Vue全家桶高仿小米商城

    大家好,我是河畔一角,时隔半年再次给大家带来一门重量级的实战课程:<Vue全家桶高仿小米商城>,现在很多公司都在参与到商城的构建体系当中,因此掌握一套商城的标准开发体系非常重要:商城的开始 ...

  3. SX1276/SX1278和SXSX1262的详细参数对比

    SX1276/SX1278和SX1262的对比    SX1262是Semtech公司新推出的一款sub-GHz无线收发器.SX1262芯片最大的买点是它的低功耗和超远距离的传输.SX1262接收电流 ...

  4. go学习第三天、数据类型

    基本数据类型 bool string int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr byte // alias ...

  5. 2017 CCPC杭州 题解

    2017CCPC杭州题目PDF Problem A. Super-palindrome 题解: 给你一个字符串,每一步可以将一个字符替换为另一个字符,问你最少多少步可以使得,该字符串任意奇数子串为回文 ...

  6. CoderForces999F-Cards and Joy

    F. Cards and Joy time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  7. 【CSS】330- 手把手教你玩转 CSS3 3D 技术

    点击上方"前端自习课"关注,学习起来~ CSS3的3D起步 要玩转css3的3d,就必须了解几个词汇,便是透视(perspective).旋转(rotate)和移动(transla ...

  8. Nginx(三)--Nginx 的高可用

    1. Nginx 进程模型简介 多进程+多路复用 master 进程 . worker 进程  启动nginx,查看nginx的线程,可以发现: [root@localhost ~]# ps -ef ...

  9. 深入理解Linux的I/O复用之epoll机制

    0.概述 通过本篇文章将了解到以下内容: I/O复用的定义和产生背景 Linux系统的I/O复用工具演进 epoll设计的基本构成 epoll高性能的底层实现 epoll的ET模式和LT模式 epol ...

  10. Mysql数据库优化一:集群(读写分离)之主从服务器的安装与配置

    Mysql数据库的集群(读写分离),说白了就是将读操作和写操作分开在不同的服务器上实现,以达到提高效率的目的. 大致原理如下: 数据库中的所有操作都是有日志记录的(前提是要打开这个日志记录功能) 1. ...