1.导入依赖
<!-- 理论上加入第一个依赖就可以,如果不行可以再把第二个依赖也加进去-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.0.Alpha3</version>
</dependency>
2.在实体类字段名上加入注解及错误提示
/**
* 品牌名
*/
@NotBlank(message = "品牌名不能为空")
private String name;
/**
* 品牌logo地址
*/
@NotEmpty
@URL(message = "URL必须是一和合法的URL地址")
private String logo;
/**
* 介绍
*/
private String descript;
/**
* 显示状态[0-不显示;1-显示]
*/
@NotNull
private Integer showStatus;
/**
* 检索首字母
*/
@NotEmpty
@Pattern(regexp = "/^[a-zA-Z]$/", message = "检索首字母必须是一个字母")
private String firstLetter;
3.在controller具体接口上开启参数校验(@Valid 开启参数校验)
/**
* 保存
*/
@RequestMapping("/save")
public R save(@Valid @RequestBody BrandEntity brand) {
brandService.save(brand);
return R.ok();
}
4.自定义异常类
(1)自定义错误代码及异常信息
public enum BizCodeEnume {
UNKNOW_EXCEPTION(10000,"系统未知异常"),
VALID_EXCEPTION(10001,"参数格式校验失败");
private int code;
private String msg;
BizCodeEnume(int code,String msg){
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
(2)自定义异常
import com.atguigu.common.exception.BizCodeEnume;
import com.atguigu.common.utils.R;
import lombok.extern.log4j.Log4j2;
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;
@Log4j2
@RestControllerAdvice(basePackages = "com.atguigu.gulimail.product.controller")
public class GuLiMallExceptionAdvice {
@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(error->{
errorMap.put(error.getField(),error.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());
}
}
6.分组校验功能
(1)创建分组对应的接口(不需要实现)
public interface AddGroup {
}
public interface UpdateGroup {
}
(2)在对应字段上添加分组
/**
* 品牌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;
/**
* 品牌logo地址
*/
@NotBlank(groups = {AddGroup.class})
@URL(message = "logo必须是一个合法的url地址",groups={AddGroup.class, UpdateGroup.class})
private String logo;
(3)在controller接口上标明那个分组生效,@Validated({AddGroup.class})
@RequestMapping("/save")
public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand) {
brandService.save(brand);
return R.ok();
}
注意:没有分组的字段分组校验不生效,如:
@NotNull
@Min(value = 0)
private Integer sort;
7.自定义校验
-
1)、编写一个自定义的校验注解
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 { };
}
-
2)、编写一个自定义的校验器 ConstraintValidator
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 context
* @return
*/
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
return set.contains(value);
}
}
-
3)、关联自定义的校验器和自定义的校验注解 * @Constraint(validatedBy = { ListValueConstraintValidator.class【可以指定多个不同的校验器,适配不同类型的校验】 }) 4)、自定义校验器的使用
@NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
@ListValue(vals={0,1},groups = {AddGroup.class, UpdateStatusGroup.class})
private Integer showStatus;