一、JSR303是什么?
JSR 303是Java中的一个数据校验规范,也被称为Bean Validation。它定义了一套注解,用于对Java对象进行数据校验。。
二、使用
@Valid开启校验写在controller需要进行校验的字段上
示例:
@RequestMapping("/save")
public R save(@Valid @RequestBody Entity entity){
service.save(entity);
return R.ok();
}
1.常用注解
以下注解写在实体类的字段上
注解 | 作用 | 示例 |
@NotNull | 属性值不能为空 | @NotNull(message = "属性值不能为空") |
@NotEmpty | 用于校验集合属性值不能为空 | @NotEmpty(message = "属性值不能为空") |
@NotBlank | 用于校验字符串属性值不能为空或空白字符 | @NotBlank(message = "属性值不能为空或空白字符") |
@Size | 用于校验字符串、集合或数组的长度是否在指定范围内 | @Size(min = 1, max = 10, message = "属性值长度必须在1到10之间") |
@Min | 用于校验数值属性值的最小值 | @Min(value = 0, message = "属性值必须大于等于0") |
@Max | 用于校验数值属性值的最大值 | @Max(value = 100, message = "属性值必须小于等于100") |
@Pattern | 用于校验字符串属性值是否匹配指定的正则表达式 | @Pattern(regexp = "[A-Za-z0-9]+", message = "属性值必须由字母和数字组成") |
用于校验字符串属性值是否符合电子邮件格式 | @Email(message = "属性值必须是有效的电子邮件地址") | |
@AssertTrue | 用于校验boolean类型属性值必须为true | @AssertTrue(message = "属性值必须为true") |
@AssertFalse | 用于校验boolean类型属性值必须为false | @AssertFalse(message = "属性值必须为false") |
@DecimalMin | 用于校验浮点的最小值 | @DecimalMin(value = "0.0", inclusive = true, message = "数字必须大于等于0") |
@DecimalMax | 用于校验浮点的最大值 | @DecimalMax(value = "100.0", inclusive = true, message = "数字必须小于等于100") |
@Digits | 用于校验数字的整数位数和小数位数。 | @Digits(integer = 5, fraction = 2, message = "数字必须为5位整数和2位小数") |
@Future | 用于校验日期或时间必须是将来的 | @Future(message = "日期必须是将来的") |
@Past | 用于校验日期或时间必须是过去的 | @Past(message = "日期必须是过去的") |
@pattern | 根据正则校验数据 | @Pattern(regexp = "^[a-zA-Z]$",message = "必须是一个字母") |
2.分组校验
当属性在不同的场景下,需要使用不同的校验规则便可以使用分组校验
如:id这个字段在新增时我们需要让他为空,修改时则不能为空
2.1.创建标识接口
public interface AddGroup {
}
public interface UpdateGroup {
}
2.2在注解中设置分组
@NotNull(message = "修改时id不能为空",groups = {UpdateGroup.class})
@Null(message = "新增时id必须为空",groups = {AddGroup.class})
private Long Id;
@Validated设置分组
// 新增
@RequestMapping("/save")
public R save(@Validated({AddGroup.class}) @RequestBody Entity entity){
service.save(entity);
return R.ok();
}
// 修改
@RequestMapping("/update")
public R update(@Validated({UpdateGroup.class}) @RequestBody Entity entity){
service.updateById(entity);
return R.ok();
}
三、自定义校验注解
1.编写自定义注解
package com.buba.common.valid;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
@Constraint(
validatedBy = {OneOfConstrainValidator.class} // 关联自定义校验器
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneOf {
String message() default "{com.buba.common.valid.OneOf.message}"; // 报错提示信息
Class<?>[] groups() default {}; // 分组
Class<? extends Payload>[] payload() default {};
int[] values() default {};
}
在resources目录下创建ValidationMessages.properties文件编写报错提示信息
com.buba.common.valid.OneOf.message=只能是传入数据的其中之一
2.编写自定义校验器
package com.buba.common.valid;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class OneOfConstrainValidator implements ConstraintValidator<OneOf,Integer> {
private Set<Integer> set = new HashSet<>();
// 初始化方法
@Override
public void initialize(OneOf constraintAnnotation) {
int[] values = constraintAnnotation.values();
for (int value : values) {
set.add(value);
}
}
/**
* 判断是否校验成功
* @param integer 需要校验的值
* @param constraintValidatorContext
* @return
*/
@Override
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
return set.contains(integer);
}
}
3.关联注解和校验器
在自定义注解上添加
// 关联自定义校验器
@Constraint(
validatedBy = {OneOfConstrainValidator.class}
)
4.该注解应用场景
// 控制显示状态[0-不显示;1-显示]
@OneOf(values = {1,0})
private Integer showStatus
四、异常捕获
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestControllerAdvice(basePackages = "com.controller")
public class ExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleVaildException(MethodArgumentNotValidException e){
log.error("数据校验出现异常{},异常类型:{}",e.getMessage(),e.getClass());
BindingResult result = e.getBindingResult();
Map<String, String> map = new HashMap<>();
// 1.获取全部的错误消息
result.getFieldErrors().forEach(f->{
// 2.获取错误提示
String message = f.getDefaultMessage();
// 3.获取错误的属性
String field = f.getField();
map.put(field,message);
});
return R.error(400,"上传的数据不合法").put("data",map);
}
@ExceptionHandler(value = Throwable.class)
public R handException(Throwable t){
return R.error(400,"系统出现异常");
}
}