JSR303验证
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- 设置分组接口
public interface UpdateGroup {
}
public interface AddGroup {
}
- 修改实体类(使用lombok自动生成方法)
@Data
public class BrandEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 品牌id
*/
@Null(groups = AddGroup.class,message = "新增不能指定id") //必须为空校验
@NotNull(groups = UpdateGroup.class,message = "更新请指定id") //不能为空校验
@TableId
private Long brandId;
/**
* 品牌名
*/
@NotBlank(message = "品牌名字不能为空",groups = AddGroup.class)
private String name;
/**
* 品牌logo地址
*/
@NotBlank(groups = AddGroup.class)
@URL(message = "URL格式不合法",groups = {AddGroup.class,UpdateGroup.class}) //URL校验
private String logo;
/**
* 介绍
*/
@NotBlank(message = "介绍不能为空",groups = AddGroup.class)
private String descript;
/**
* 显示状态[0-不显示;1-显示]
*/
@NotNull(groups = AddGroup.class)
@ListValue(list = {0,1},groups = {AddGroup.class,UpdateGroup.class},message = "必须提交指定的值") //自定义校验
private Integer showStatus;
/**
* 检索首字母
*/
@NotBlank(groups = {AddGroup.class})
@Pattern(regexp = "^[a-zA-Z]$",message = "检索必须是一个A-Z的首字母",groups = {AddGroup.class,UpdateGroup.class}) //表示属于哪几个分组
private String firstLetter;
/**
* 排序
*/
@NotNull(groups = {AddGroup.class})
@Min(value = 0,groups = {AddGroup.class,UpdateGroup.class}) //最小值校验
private Integer sort;
}
- 控制器校验
@RequestMapping("/save")
//@RequiresPermissions("product:brand:save")
public R save(@Validated(value = AddGroup.class) @RequestBody BrandEntity brand/*, BindingResult result*/){
/* if (result.hasErrors()){
Map<String,String> resp = new HashMap<>(); //手动处理错误
result.getFieldErrors().forEach(e->{
resp.put(e.getField(),e.getDefaultMessage());
});
return R.error().put("data",resp);
}*/
brandService.save(brand);
return R.ok();
}
- 通用异常处理
@RestControllerAdvice
public class GuliMallExceptionHandler {
/**
* 处理参数异常,控制器参数校验不过会抛出异常,被拦截到,然后统一异常处理
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R methodArgumentNotValidExceptionHandle(MethodArgumentNotValidException e){
BindingResult result = e.getBindingResult();
Map<String,String> resp = new HashMap<>();
result.getFieldErrors().forEach(error -> {
resp.put(error.getField(),error.getDefaultMessage());
});
return R.error(BizCode.VALID_EXCEPTION).put("data",resp);
}
/**
* 通用异常返回
* @param exception
* @return
*/
@ExceptionHandler(Exception.class)
public R exceptionHandle(Exception exception){
exception.printStackTrace();
return R.error(BizCode.UNKNOW_EXCEPTION).put("data",exception);
}
}
- 返回结果类
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public R() {
put("code", 0);
put("msg", "success");
}
public static R error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static R error(BizCode bizCode){
return error(bizCode.getCode(),bizCode.getMsg());
}
public static R error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}
- 业务异常代码
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum BizCode {
UNKNOW_EXCEPTION(10000,"系统未知异常"),
VALID_EXCEPTION(10001,"参数校验失败");
private Integer code;
private String msg;
}
-----------------------------自定义校验-----------------------------
- 注解
@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class }) //具体实现类
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {
String message() default "{com.example.common.valid.ListValue.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int[] list() default { }; //校验的类型
}
- 校验方法
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> { //继承接口,表明数据类型
private static final Set<Integer> values = new HashSet<>();
/**
* 初始化方法,将指定的数据填充进set
* @param constraintAnnotation
*/
@Override
public void initialize(ListValue constraintAnnotation) {
int[] arr = constraintAnnotation.list();
Arrays.stream(arr).forEach(values::add);
}
/**
* 判断是否校验成功
* @param integer
* @param constraintValidatorContext
* @return
*/
@Override
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
return values.contains(integer);
}
}