前言

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

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

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. Hadoop原生搭建

    版本:(centos7.6) 在开始搭建平台前我已经预装了MySQL ps:MySQL创建用户并授权: grant all privileges on *.* to ' with grant opti ...

  2. 《Windows内核安全与驱动开发》阅读笔记 -- 索引目录

    <Windows内核安全与驱动开发>阅读笔记 -- 索引目录 一.内核上机指导 二.内核编程环境及其特殊性 2.1 内核编程的环境 2.2 数据类型 2.3 重要的数据结构 2.4 函数调 ...

  3. 一条数据的HBase之旅,简明HBase入门教程1:开篇

    [摘要] 这是HBase入门系列的第1篇文章,主要介绍HBase当前的项目活跃度以及搜索引擎热度信息,以及一些概况信息,内容基于HBase 2.0 beta2版本.本系列文章既适用于HBase新手,也 ...

  4. Ubuntu18.04安装openCV4.1.2

    Ubuntu18.04下安装openCV4.1.2 注意: 在整个安装过程中,包括后期QT的使用中不要出现中文路径.会很坑的. 一.下载openCV4.1.2 可以再官网进行下载https://ope ...

  5. Exponial

    Description Everybody loves big numbers (if you do not, you might want to stop reading at this point ...

  6. redis第一讲【redis的描述,linux和docker下的安装使用】

    Redis(REmote DIctionary Server):是什么 redis(远程字典服务器),是完全开源免费的,高性能的k/v分布式内存数据,热门的Nosql数据库 Redis可以干什么: 内 ...

  7. 167. 两数之和 II - 输入有序数组

    给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2. 说明: 返回的下标值( ...

  8. 大数据学习笔记——Java篇之集合框架(ArrayList)

    Java集合框架学习笔记 1. Java集合框架中各接口或子类的继承以及实现关系图: 2. 数组和集合类的区别整理: 数组: 1. 长度是固定的 2. 既可以存放基本数据类型又可以存放引用数据类型 3 ...

  9. 服务网格数据平面的关键:层层剖析Envoy配置

    Envoy是一种高性能C++分布式代理,专为单个服务和应用程序设计.作为Service Mesh中的重要组件,充分理解其配置就显得尤为重要.本文列出了使用Envoy而不用其他代理的原因.并给出了Env ...

  10. AJAX 多次调用,后面的会覆盖前面的内容/数据

    1.有的时候,同一个请求链接,需要传递不同的参数,发起多个请求.因此我采用了for循环. 1.1 此处是需要传递的参数 function behavioranalysisReqstue(type) { ...