当前位置:网站首页>Jsr303 and common validator implementations
Jsr303 and common validator implementations
2022-06-30 17:01:00 【Ibrahimo】
《 Happy people java-validator》 Learning notes
Preface
- Bean Validation - https://beanvalidation.org/, It is
JAVAEE The specification of , No concrete implementation. - Hibernate Validator: - https://hibernate.org/validator/, It is
Concrete implementation.
Traditional parameter verification
Suppose there is a login scenario , The login parameters are LoginForm:
@Data
public class LoginForm {
private String username;
private String password;
}
The verification logic used is as follows :
public void login(LoginForm form){
if(form == null){
throw new RuntimeException("login Login parameters are null");
}
if(form.getUsername() == null || form.getUsername().trim().isEmpty()){
throw new RuntimeException("login Log in as username Non conformity ");
}
if(form.getPassword() == null || form.getPassword().trim().isEmpty()){
throw new RuntimeException("login Log in as password Non conformity ");
}
//todo business....
}
JSR303 standard
What is? Java EE standard
java EE standard Only API, It didn't come true . Concrete implementation , By each manufacturer . for example :
javax.sql.*javax.servletjavax.jmx- …
java se The standard that comes with it

These are not the only , The above is javaee Some common specifications .
For some things that are not above , You need to manually introduce api rely on .
java ee Who made the specification
Java Community Process
from javax To jakarta
oracle Acquisition sun after ,oralce Begin to practice java Business authorization . Forced to java Pressure from the open source community ,oracle take javax standard Donated to eclipse.
But it's not allowed to use javax.*, That's why we have the present jakarta.
So there will be :jakarta.sq.....l
Don't Follow
apache.jakartaConfuse STH with STH else .
JSR303 The implementation of the - Hibernate
maven rely on
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
<exclusions>
<exclusion>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- hibernate-validator It already contains :validation-api <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> -->
<!-- Equivalent to jakarta.validation-api <dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> <version>2.0.1</version> </dependency> -->
<!-- For parsing message Medium el expression -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>9.0.29</version>
</dependency>
UserInfo
@Data
public class UserInfo {
private Long id;
private String name;
private Integer age;
private String email;
private LocalDate birthdate;
}
ValidatorUtil
public class ValidatorUtil {
private static Validator validator;
static {
// involves SPI
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
public static void valid(UserInfo userInfo){
// If the verification object userInfo Not through , Then there is a verification failure message
Set<ConstraintViolation<UserInfo>> set = validator.validate(userInfo);
set.stream().forEach(cv -> {
System.out.println(" attribute :"+cv.getPropertyPath()+", Property value :"+cv.getInvalidValue()+", Verification failed , Trigger rule :"+cv.getMessage());
});
}
}
Validator Initialization flow
Validation.buildDefaultValidatorFactory().getValidator(); The logic can be split into the following two steps :
Validation.buildDefaultValidatorFactory(): obtain ValidatorFactory$1.getValidator();: obtain Validator
obtain ValidatorFactory
public static ValidatorFactory buildDefaultValidatorFactory() {
//1.1 byDefaultProvider() -- return GenericBootstrapImpl();
//1.2 GenericBootstrapImpl.configure() -- according to SPI load javax.validation.spi.ValidationProvider
//1.3 ValidationProvider.buildValidatorFactory();
return byDefaultProvider().configure().buildValidatorFactory();
}
SPI ValidationProvider(SPI) -> hibernate.jar/META-INF/services/javax.validation.spi.ValidationProvider
HibernateValidator
public class HibernateValidator implements ValidationProvider<HibernateValidatorConfiguration> {
@Override
public HibernateValidatorConfiguration createSpecializedConfiguration(BootstrapState state) {
return HibernateValidatorConfiguration.class.cast( new ConfigurationImpl( this ) );
}
@Override
public Configuration<?> createGenericConfiguration(BootstrapState state) {
return new ConfigurationImpl( state );
}
// return ValidatorFactoryImpl
@Override
public ValidatorFactory buildValidatorFactory(ConfigurationState configurationState) {
return new ValidatorFactoryImpl( configurationState );
}
}
The final acquisition of ValidatorFactory: org.hibernate.validator.internal.engine.ValidatorFactoryImpl
obtain Validator
Final Validator type : org.hibernate.validator.internal.engine.ValidatorFactoryImpl
demo1
constraints
@Data
public class UserInfo {
@javax.validation.constraints.NotNull
private Long id;
@javax.validation.constraints.NotEmpty
private String name;
@org.hibernate.validator.constraints.Range
private Integer age;
@javax.validation.constraints.Email
private String email;
private LocalDate birthdate;
}
test-case
public void test01(){
UserInfo userInfo = new UserInfo();
userInfo.setName("");
userInfo.setAge(120);
userInfo.setEmail("www.baidu.com");
ValidatorUtil.valid(userInfo);
}
Execution results

Common constraints constraints
javax.validation.constraints

org.hibernate.validator.constraints
Constraints and Validator Binding relationship of —ConstraintHelper
package org.hibernate.validator.internal.metadata.core;
public class ConstraintHelper {
public ConstraintHelper() {
Map<Class<? extends Annotation>, List<ConstraintValidatorDescriptor<?>>> tmpConstraints = new HashMap<>();
// by NotNull.class binding NotNullValidator.class
putConstraint( tmpConstraints, NotNull.class, NotNullValidator.class );
putConstraint( tmpConstraints, Null.class, NullValidator.class );
putConstraint( tmpConstraints, Email.class, EmailValidator.class );
//......
}
}
Group check
For example, above UserInfo,
- id: stay When added
Don't check, stay When editingcheck id - Other attributes , When adding or editing All check
Define groups -class
public class ValidGroups {
public interface Add{
}
public interface Edit{
}
}
UserInfo
@Data
public class UserInfo {
@javax.validation.constraints.NotNull(groups = {
ValidGroups.Edit.class})
private Long id;
@javax.validation.constraints.NotEmpty(groups = {
ValidGroups.Add.class,ValidGroups.Edit.class})
private String name;
@org.hibernate.validator.constraints.Range(min = 18,message = " Age is less than {value}, A minor ",groups = {
ValidGroups.Add.class,ValidGroups.Edit.class})
private Integer age;
@javax.validation.constraints.Email(groups = {
ValidGroups.Add.class,ValidGroups.Edit.class})
private String email;
private LocalDate birthdate;
}
javax.validation.Validator
public interface Validator {
<T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);
}
ValidatorUtil
public static List<String> valid(UserInfo userInfo,Class validGroup){
Set<ConstraintViolation<UserInfo>> set = validator.validate(userInfo,validGroup);
List<String> list = set.stream().map(cv ->
" attribute :" + cv.getPropertyPath() + ", Property value :" + cv.getInvalidValue() + ", Verification failed , Trigger rule :" + cv.getMessage()
).collect(Collectors.toList());
list.forEach(System.out::println);
return list;
}
Cascade check
UserInfo in grade Grade information , Grade information has its own verification rules .
@Data
public class UserInfo {
// A little ...
@javax.validation.Valid // Cascade check
private Grade grade;
}
@Data
public class Grade {
@NotEmpty
private String gradeNo;
@Range(min = 5,max = 40)
private int classNum;
}
In execution validator.validate(userInfo), If you need to open cascading annotation , You need to use @javax.validation.Valid annotation .
Custom check
Define validation rules constraints
@Target({
FIELD })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {
UserStatusValidator.class }) // Appoint validator
public @interface UserStatus {
String message() default "{user_status It has to be for 100/101/1002}";
Class<?>[] groups() default {
};
Class<? extends Payload>[] payload() default {
};
}
Definition Validator
public class UserStatusValidator implements javax.validation.ConstraintValidator<UserStatus, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
return value == 100 || value == 101 || value == 102;
}
}
failfast check
In the previous article validator, All non-compliance verification information will be collected , To return to .
How to set up , A non-compliance message was found , Return immediately .
Validator failfastValidator = Validation.byProvider(HibernateValidator.class)
.configure().failFast(true).buildValidatorFactory().getValidator();
Not javabean check
UserInfoService
public class UserInfoService {
public String getByName(@NotNull String name) throws NoSuchMethodException {
// check ...
Method method = this.getClass().getDeclaredMethod("getByName", String.class);
ValidatorUtil.validNotBean(this,method,new Object[]{
name});
return "name:" + name;
}
}
ExecutableValidator
public class ValidatorUtil {
private static Validator validator;
private static ExecutableValidator executableValidator;
static {
validator = Validation.buildDefaultValidatorFactory().getValidator();
executableValidator = validator.forExecutables();
}
public static <T> List<String> validNotBean(T object , Method method, Object[] params , Class<?> ... groups){
Set<ConstraintViolation<T>> set = executableValidator.validateParameters(object, method, params, groups);
List<String> list = set.stream().map(cv ->
" attribute :" + cv.getPropertyPath() + ", Property value :" + cv.getInvalidValue() + ", Verification failed , Trigger rule :" + cv.getMessage()
).collect(Collectors.toList());
list.forEach(System.out::println);
return list;
}
}
Springboot check
Springboot Environment building
maven rely on
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.7</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
App The main class
@SpringBootApplication
public class App {
public static void main( String[] args )
{
SpringApplication.run(App.class);
}
}
Controller
@RestController
public class UserInfoController {
@GetMapping("/getByName")
public String getByName(String name){
return "name:" + name;
}
@GetMapping("/addUser")
public String addUser(UserInfo userInfo){
List<String> list = ValidatorUtil.valid(userInfo);
if(list.size() > 0){
return " Verification failed ";
}
return " Add success ";
}
}
Springmvc check - declarative
@javax.validation.Valid
@GetMapping("/addUser2")
public String addUser2(@javax.validation.Valid UserInfo userInfo, BindingResult bindingResult){
if(bindingResult.hasErrors()){
bindingResult.getAllErrors().forEach(error ->{
System.out.println(error.getObjectName()+"::"+error.getDefaultMessage());
});
bindingResult.getFieldErrors().forEach(fieldError -> {
System.out.println(fieldError.getField()+":"+fieldError.getDefaultMessage()+", Values that fail to pass the verification :"+fieldError.getRejectedValue() );
});
}
return " Add success ";
}
@javax.validation.Valid Cannot specify grouping .
@org.springframework.validation.annotation.Validated - Assign groups
@GetMapping("/addUser3")
public String addUser3(@org.springframework.validation.annotation.Validated(ValidGroups.Add.class) UserInfo userInfo, BindingResult bindingResult){
if(bindingResult.hasErrors()){
bindingResult.getAllErrors().forEach(error ->{
System.out.println(error.getObjectName()+"::"+error.getDefaultMessage());
});
bindingResult.getFieldErrors().forEach(fieldError -> {
System.out.println(fieldError.getField()+":"+fieldError.getDefaultMessage()+", Values that fail to pass the verification :"+fieldError.getRejectedValue() );
});
}
return " Add success ";
}
Unified exception handling
controller – nothing BindingResult Handle
@GetMapping("/addUser4")
public String addUser4(@org.springframework.validation.annotation.Validated(ValidGroups.Add.class) UserInfo userInfo){
return " Add success ";
}
If the verification fails , It will throw an exception directly .
@ExceptionHandler
At every controller Add @ExceptionHandler Method of annotation , To deal with the controller Exception information for .
@ExceptionHandler(BindException.class)
public String handlerEx(BindException e){
List<FieldError> fieldErrors = e.getFieldErrors();
StringBuilder sb = new StringBuilder();
fieldErrors.forEach(fe ->
sb.append(" attribute :").append(fe.getField()).append(" Verification failed , reason :").append(fe.getDefaultMessage()).append(";")
);
return sb.toString();
}
Global exception handling -ControllerAdvice
See :SpringMVC- characteristic annotation - @ControllerAdvice part .
Valid and Validate difference
- Validate Support grouping
- Validate Support automatic verification on method parameters .
@GetMapping("/getByName")
// Add... To a method or class @Validated :@Null Fang Youxian
public String getByName(@NotNull String name){
return "name:" + name;
}
At this time @Null Verification does not work , It needs to be Method or class To add @Validate annotation .
When you add this annotation to a class , If the verification fails , Throw out ConstraintViolationException abnormal .
@ExceptionHandler(ConstraintViolationException.class)
public String handlerEx2(ConstraintViolationException e){
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
StringBuilder sb = new StringBuilder();
//TODO ....
return sb.toString();
}
边栏推荐
- 深度学习——(2)几种常见的损失函数
- 【微信小程序】小程序的宿主环境
- 【牛客网刷题系列 之 Verilog快速入门】~ 位拆分与运算
- 几个跨端开发神器
- ArcMap operation series: 80 plane to latitude and longitude 84
- 2022 Blue Bridge Cup group B -2022- (01 backpack to calculate the number of schemes)
- 更多龙蜥自研特性!生产可用的 Anolis OS 8.6 正式发布
- 《网络是怎么样连接的》读书笔记 - 汇总篇
- Hologres shared cluster helps Taobao subscribe to the extreme refined operation
- How to connect the Internet Reading Notes - Summary
猜你喜欢

巩固入门-C#基础变量和常量

Etcd教程 — 第九章 Etcd之实现分布式锁

Bc1.2 PD protocol

【机器学习】K-means聚类分析

Dart: string replace related methods

Data mining knowledge points sorting (final review version)

编译丨迅为iTOP4412开发板Makefile编译

Tencent two sides: @bean and @component are used on the same class. What happens?

Good partner for cloud skill improvement, senior brother cloud of Amazon officially opened today

商单视频播放超2000万!农院改造为何屡被催更?
随机推荐
Niuke.com: minimum cost of climbing stairs
9:第三章:电商工程分析:4:【通用模块】;(待写……)
jspreadsheet/CE JExcel数据字段比给的字段(columns)多会导致空白列的问题解决方案
更多龙蜥自研特性!生产可用的 Anolis OS 8.6 正式发布
数据库系统概论习题册
安全帽佩戴检测算法研究
TCP Socket与TCP 连接
巩固入门-C#基础变量和常量
中航无人机科创板上市:市值385亿 拳头产品是翼龙无人机
Deep learning - (2) several common loss functions
Etcd tutorial - Chapter 9 etcd implementation of distributed locks
名单揭晓 | 2021年度中国杰出知识产权服务团队
[Verilog quick start of Niuke online question series] ~ bit splitting and operation
Lambda表达式_Stream流_File类
备战数学建模35-时间序列预测模型
Multi terminal collaboration of Huawei accounts to create a better internet life
JS Es5 can also create constants?
STL教程7-set、pair对组和仿函数
I implement "stack" with C I
Carry two load balancing notes and find them in the future
