Hibernate Validator介绍
校验参数基本上是一个体力活,而且冗余代码繁多,也影响代码的可读性,我们需要一个比较优雅的方式来解决这个问题。Hibernate Validator 框架刚好解决了这个问题,可以以很优雅的方式实现参数的校验,让业务代码和校验逻辑分开,不再编写重复的校验逻辑。
1hibernate-validator优势:
- 验证逻辑与业务逻辑之间进行了分离,降低了程序耦合度
- 统一且规范的验证方式,无需你再次编写重复的验证代码
- 你将更专注于你的业务,将这些繁琐的事情统统丢在一边
2hibernate-validator常用注解
hibernate-validator提供的校验方式为在类的属性上加入相应的注解来达到校验的目的。hibernate-validator提供的用于校验的注解如下:
注解 | 说明 |
---|---|
@AssertTrue | 用于boolean字段,该字段只能为true |
@AssertFalse | 用于boolean字段,该字段只能为false |
@CreditCardNumber | 对信用卡号进行一个大致的验证 |
@DecimalMax | 只能小于或等于该值 |
@DecimalMin | 只能大于或等于该值 |
检查是否是一个有效的email地址 | |
@Future | 检查该字段的日期是否是属于将来的日期 |
@Length(min=,max=) | 检查所属的字段的长度是否在min和max之间,只能用于字符串 |
@Max | 该字段的值只能小于或等于该值 |
@Min | 该字段的值只能大于或等于该值 |
@NotNull | 不能为null |
@NotBlank | 不能为空,检查时会将空格忽略 |
@NotEmpty | 不能为空,这里的空是指空字符串 |
@Pattern(regex=) | 被注释的元素必须符合指定的正则表达式 |
@Future | 检查该字段的日期是否是属于将来的日期 |
@URL(protocol=,host,port) | 检查是否是一个有效的URL,如果提供了protocol,host等,则该URL还需满足提供的条件 |
3hibernate-validator使用
3.1相关依赖
hibernate-validator 6.0.17.Final
<!--底层依赖了hibernate validator的相关校验,无需额外引入hibernate-validator 6.0.17.Final的jar包-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
3.2 校验类与测试Controller
/**
* 使用Hibernate Validator参数校验注解
* 一个属性上可使用多个校验规则
*/
@Data
public class User {
@NotNull(message = "用户id不为空")
private Integer id;
@Length(message = "用户名长度限制为10到40个字符安",max = 40,min = 10)
private String userName;
@Min(value = 18,message = "年龄")
private Integer age;
@NotNull(message = "邮箱地址不为空")
@Email(message = "请输入正确的邮箱地址")
private String email;
}
@RequestMapping("/user")
@RestController
@Validated //开启参数校验规则
public class UserController {
/**
* 简单基础类型校验
* NotNull
* @param id
* @return
*/
@RequestMapping("/delete")
public String delete(@NotNull(message = "id不能为空") Integer id){
return "delete success";
}
/**
* 复杂对象类型校验,会根据对象中相关属性上设置的注解进行验证
* @param user
* @return
*/
@RequestMapping("/save")
public String save(@Validated User user){
return "save success";
}
}
3.3 校验测试
运行启动类,输入请求路径:localhost:8080/user/delete
3.4 校验异常全局处理
通过上述测试显示,当参数校验不通过时,将会直接抛出一个异常页面,对用户不友好。
为了能够在页面友好的显示数据校验结果,可以通过全局异常处理来解决,创建全局异常处理类
/**
* @author lyf
* @projectName demo
* @date 2022/2/9 下午 02:56
* @description 全局参数校验失败处理
* RestControllerAdvice 一个Controller的切面处理类,类上标注了Controller、RestController的才会被此切面增强
* ResponseBody 以Json数据的形式返回
*/
@RestControllerAdvice(annotations={Controller.class, RestController.class})
@ResponseBody
public class GlobalExceptionHandler {
/**
* 异常处理方法
* 当捕获到类型为ConstraintViolationException、BindException的异常时将会进入异常处理方法
* @param ex
* @param request
* @return
*/
@ExceptionHandler(value = {ConstraintViolationException.class, BindException.class})
public ReturnMessage exceptionHandler(Exception ex, HttpServletRequest request){
ReturnMessage returnMessage=new ReturnMessage();
String errorMessage="";
if(ex instanceof ConstraintViolationException){
ConstraintViolationException exception=(ConstraintViolationException)ex;
ConstraintViolation<?> next = exception.getConstraintViolations().iterator().next();
//获得Validator注解上标注的异常数据
errorMessage=next.getMessage();
}else if(ex instanceof BindException){
BindException exception=(BindException)ex;
//获得Validator注解上标注的异常数据
errorMessage=exception.getBindingResult().getFieldError().getDefaultMessage();
}
returnMessage.setMessage(errorMessage);
returnMessage.setCode(501);
returnMessage.setStatus("1");
return returnMessage;
}
}
运行启动类,输入请求路径:http://localhost:8080/user/save?id=15&userName=dhjjhdj
输入的参数不符合校验规则,进入异常切面进行处理,并将异常信息返回