JSR303分组校验和自定义校验注解

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 })

你可能感兴趣的:(JSR303分组校验和自定义校验注解)