hibernate-validator的基本使⽤
validator是⽤来校验参数使⽤!
⼀般来说校验参数的⼯作可以放在前端去执⾏,但是假如有⼈不经过前端直接调⽤后端的接⼝呢?很可能就出现⾮法数据⽽导致⼀些问题,所有服务端也要做数据的校验。
前端校验是为了提⾼⽤户的体验度,后端校验则是为了保证数据的安全性。
校验参数基本上是⼀个体⼒活,⽽且冗余代码繁多,也影响代码的可读性,我们需要⼀个⽐较优雅的⽅式来解决这个问题。Hibernate Validator 框架刚好解决了这个问题,可以以很优雅的⽅式实现参数的校验,让业务代码和校验逻辑分开,不再编写重复的校验逻辑。
hibernate-validator优势:  1.验证逻辑与业务逻辑之间进⾏了分离,降低了程序耦合度
2.统⼀且规范的验证⽅式,⽆需你再次编写重复的验证代码
            3.你将更专注于你的业务,将这些繁琐的事情统统丢在⼀边
hibernate-validator的maven坐标:
其实spring-boot-starter-web中已经依赖了hibernate-validator
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>
hibernate-validator提供的校验⽅式为在类的属性上加⼊相应的注解来达到校验的⽬的。hibernate-validator提供的⽤于校验的注解如下:
注解说明
@AssertTrue⽤于boolean字段,该字段只能为true
@AssertFalse⽤于boolean字段,该字段只能为false
@CreditCardNumber对信⽤卡号进⾏⼀个⼤致的验证
@DecimalMax只能⼩于或等于该值
@DecimalMin只能⼤于或等于该值
@Email检查是否是⼀个有效的email地址
@Future检查该字段的⽇期是否是属于将来的⽇期
@Length(min=,max=)检查所属的字段的长度是否在min和max之间,只能⽤于字符串
@Max该字段的值只能⼩于或等于该值
@Min该字段的值只能⼤于或等于该值
@NotNull不能为null
@NotBlank不能为空,检查时会将空格忽略
@NotEmpty不能为空,这⾥的空是指空字符串
@Pattern(regex=)被注释的元素必须符合指定的正则表达式
@URL(protocol=,host,port)检查是否是⼀个有效的URL,如果提供了protocol,host等,则该URL还需满⾜提供的条件
⼊门案例
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.xiaoteng</groupId>
<artifactId>validator-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--
spring-boot-starter-web中已经依赖了hibernate-validator
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>
-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
实体类
ity;
import lombok.Data;
import org.straints.Length;
import straints.*;
/**
* @author xiaozhuang
* @date 2022年02⽉26⽇ 14:03
*/
@Data
public class User {
@NotNull(message = "⽤户id不能为空(null)")
private int id;
@NotEmpty(message = "⽤户名不能为空")
@Length(max = 50, message = "⽤户名长度不能超过50")
private String userName;
@Max(value = 100, message = "年龄最⼤为100")
@Min(value = 18, message = "年龄最⼩为18")
private int age;
@Pattern(regexp = "[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$",
message = "邮箱格式不正确")
private String email;
}
controller
ller;
ity.User;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import straints.NotBlank;
springboot其实就是spring
/**
* @author xiaozhuang
* @date 2022年02⽉26⽇ 14:13
*/
@RestController
@RequestMapping("/user")
@Validated //开启校验功能
public class UserController {
//简单数据类型校验
@RequestMapping("/byId")
public String delete(@NotBlank(message = "id不能为空") String id){        System.out.println("id为..." + id);
return "OK";
}
//对象属性校验
@RequestMapping("/save")
public String save(@Validated User user){
System.out.println("" + user);
return "OK";
}
}
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import javax.swing.*;
/**
* @author xiaozhuang
* @date 2022年02⽉26⽇ 14:18
*/
@SpringBootApplication
public class ValidatorApp {
public static void main(String[] args) {
SpringApplication.run(ValidatorApp.class,args);
}
}
启动项⽬,然后访问。
⾸先是简单类型的校验:
1.正常访问
2.不传id
再看控制台报错
接下来是实体类的校验:
1.传⼀个id的报错
这⾥只有三个都传了对于的值才不会报错。并且⽤了它有⼏个问题需要处理。
1.页⾯返回错误也不合适,需要做⼀个全局的异常处理
2.这⾥的参数校验,特别是对象时,当已经有⼀个参数校验不通过了以后,其他的参数也就不需要再校验了,就应该直接返回错误信息了,⽽不是⼀个没有通过,其他的还接着校验,需要做⼀个指定校验时使⽤快速失败返回模式
全局异常处理:这⾥只是针对validator的异常处理
fig;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
/**
* 全局异常处理
*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
public class ExceptionConfiguration {
@ExceptionHandler({ConstraintViolationException.class,BindException.class})
public String validateException(Exception ex, HttpServletRequest request) {
ex.printStackTrace();
String msg = null;
if(ex instanceof ConstraintViolationException){
ConstraintViolationException constraintViolationException =
(ConstraintViolationException)ex;
Set<ConstraintViolation<?>> violations =
ConstraintViolation<?> next = violations.iterator().next();
msg = Message();
}else if(ex instanceof BindException){
BindException bindException = (BindException)ex;
msg = BindingResult().getFieldError().getDefaultMessage();
}
return msg;
}
}
此时页⾯返回的友好提⽰是这样的
指定校验时使⽤快速失败返回模式:这⾥并没有使⽤@Configuration注解,⽽是使⽤⾃定义注解,在需要使⽤它的类上⾯⽤,更加灵活。
fig;
import org.hibernate.validator.HibernateValidator;
import t.annotation.Bean;
import t.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
/**
* @author xiaozhuang
* @date 2022年02⽉26⽇ 14:46
*/
//@Configuration  使⽤它就是所有的都会经过这⾥
public class ValidatorConfiguration {
@Bean
public Validator validator() {
ValidatorFactory validatorFactory =
Validation.byProvider(HibernateValidator.class)
.configure()
//快速失败返回模式
.addProperty("hibernate.validator.fail_fast", "true")
.buildValidatorFactory();
Validator();
}
/
**
* @return 开启快速返回
* 如果参数校验有异常,直接抛异常,不会进⼊到 controller,使⽤全局异常拦截进⾏拦截
*/
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor =
new MethodValidationPostProcessor();
/**设置validator模式为快速失败返回*/
postProcessor.setValidator(validator());
return postProcessor;
}
}
fig;
import t.annotation.Import;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 在启动类上添加该注解来启动表单验证功能---快速失败返回模式
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ValidatorConfiguration.class)  // 代表导⼊失败快速返回的配置类
public @interface EnableFormValidator {
}
这时我们把它可以加在启动类上,也可以放在某个单独的controller类上⾯。
再看效果:
就只校验了age,发⽣错误就直接返回了,没有再对userName进⾏校验了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。