1、给Bean属性添加校验注解:javax.validation.constraints,并定义自己的message提示
2、在Controller方法参数贴上@Valid注解开启校验功能
3、BindingResult可以获取到校验的结果,编写异常处理类使用@RestControllerAdvice、@ExceptionHandler标注方法处理校验异常
import com.atguigu.common.exception.BizCodeEnume;
import com.atguigu.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
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.atguigu.gulimall.product.controller")
public class GulimallExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleValidException(MethodArgumentNotValidException e){
log.error("数据校验出现的问题:{},异常类型:{}",e.getMessage(),e.getClass());
BindingResult bindingResult = e.getBindingResult();
Map<String,String> errorMap = new HashMap<>();
bindingResult.getFieldErrors().forEach(fieldError -> {
errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());
});
return R.error(BizCodeEnume.VALID_EXCEPTION.getCode(),BizCodeEnume.VALID_EXCEPTION.getMsg()).put("data",errorMap);
}
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable){
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
}
解决多场景的复杂校验
1、给校验注解标注什么情况需要进行校验
package com.atguigu.common.valid;
public interface AddGroup {
}
**
* 品牌id
*/
@NotNull(message = "修改必须指定品牌id",groups = {UpdateGroup.class})
@Null(message = "新增不能指定品牌id",groups = {AddGroup.class})
@TableId
private Long brandId;
/**
* 品牌名
*/
@NotBlank(message = "品牌名必须提交",groups = {AddGroup.class,UpdateGroup.class})
private String name;
2、默认没有指定分组的校验注解不会生效,只会在@Validated({UpdateGroup.class})生效
/**
* 保存
*/
@RequestMapping("/save")
public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand/*, BindingResult result*/){
/*if(result.hasErrors()){
Map map = new HashMap<>();
// 1.获取校验的错误结果
result.getFieldErrors().forEach(item -> {
// FieldError获取到错误提示
String message = item.getDefaultMessage();
// 获取错误的属性的名字
String field = item.getField();
map.put(field,message);
});
return R.error(400,"提交的数据不合法").put("data",map);
}*/
brandService.save(brand);
return R.ok();
}
/**
* 修改
*/
@RequestMapping("/update")
public R update(@Validated({UpdateGroup.class}) @RequestBody BrandEntity brand){
brandService.updateById(brand);
return R.ok();
}
1、引入依赖
<dependency>
<groupId>javax.validationgroupId>
<artifactId>validation-apiartifactId>
<version>2.0.1.Finalversion>
dependency>
/**
* 显示状态[0-不显示;1-显示]
*/
@NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
@ListValue(vals = {0,1}, groups = {AddGroup.class, UpdateStatusGroup.class})
private Integer showStatus;
2、编写一个自定义的校验注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {
String message() default "{com.atguigu.common.valid.ListValue.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int[] vals() default { };
}
ValidationMessages.properties
com.atguigu.common.valid.ListValue.message=必须提交指定的值
3、编写一个自定义的校验器
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {
private Set<Integer> set = new HashSet<>();
// 初始化方法
@Override
public void initialize(ListValue constraintAnnotation) {
int[] vals = constraintAnnotation.vals();
for(int val : vals){
set.add(val);
}
}
// 判断是否校验成功
/**
* @param value 需要校验的值
* @param constraintValidatorContext
* @return
*/
@Override
public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
return set.contains(value);
}
}
4、关联自定义的校验器和自定义的校验注解
@Constraint(validatedBy = { ListValueConstraintValidator.class })