【微服务实战】(七)数据校验J303,全局JSR303异常处理

后端数据校验使用JSR303

一、JSR303的注解

在IDEA中双击shift,搜索ValidationMessages_zh_CN.properties文件有详细JSR303注解说明
【微服务实战】(七)数据校验J303,全局JSR303异常处理_第1张图片
【微服务实战】(七)数据校验J303,全局JSR303异常处理_第2张图片

二、JSR303开启校验

1、开启校验功能@Valid,校验错误以后会有默认的响应
【微服务实战】(七)数据校验J303,全局JSR303异常处理_第3张图片

2、给校验的bean对象后紧跟一个BindResult,就可以获取到校验的结果(接收异常)并手动处理异常
【微服务实战】(七)数据校验J303,全局JSR303异常处理_第4张图片

三、分组校验

分组校验:新增和修改需要判断的不同,修改时,每个参数不用传完,而新增的时候不需要id,修改需要id。(多场景的复杂校验)

分两种情况,修改、新增,在common子模块中创建两个空接口,AddGroup、UpdateGroup

【微服务实战】(七)数据校验J303,全局JSR303异常处理_第5张图片
如果设置了如下情况,则在entity中,所有需要校验的字段的注解中,必须加上groups的参数,否则将不起作用。未分组的字段只有未分组的方法才能校验
【微服务实战】(七)数据校验J303,全局JSR303异常处理_第6张图片

四、自定义校验

1、需要导一个包

<dependency>
    <groupId>javax.validationgroupId>
    <artifactId>validation-apiartifactId>
    <version>2.0.1.Finalversion>
dependency>

2、 自己编写一个自定义的校验注解

package com.tangxz.common.valid;

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;

/**
 * @Info:
 * @Author: 唐小尊
 * @Date: 2020/7/15  14:39
 */
@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {

    String message() default "{com.tangxz.common.valid.ListValue.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    int[] vals () default { };
}

3、 编写一个自定义的校验器

package com.tangxz.common.valid;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;

/**
 * @Info:
 * @Author: 唐小尊
 * @Date: 2020/7/15  14:47
 */
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) {
        if (set.contains(value)){
            return true;
        }
        return false;
    }
}

4、 关联自定义的校验器和自定义的校验注解

【微服务实战】(七)数据校验J303,全局JSR303异常处理_第7张图片

五、统一的异常处理

统一异常处理,处理JSR303异常

在每个springboot的服务中添加一个exception包

package com.tangxz.gulimall.product.exception;

import com.tangxz.common.utils.R;
import com.tangxz.common.exception.BizCodeEnume;
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;

/**
 * @Info: 集中处理product服务的所有异常
 * @Author: 唐小尊
 * @Date: 2020/7/15  13:28
 */
@Slf4j
@RestControllerAdvice(basePackages = "com.tangxz.gulimall.product.controller")
public class GulimallExceptionControllerAdvice {

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleVaildException(MethodArgumentNotValidException e) {
        log.error("数据校验出现问题:{},异常类型:{}", e.getMessage(), e.getClass());
        BindingResult bindingResult = e.getBindingResult();

        Map<String, String> map = new HashMap<>();
        //获取校验的错误结果
        bindingResult.getFieldErrors().forEach((item) -> {
            //获取到的错误提示
            String message = item.getDefaultMessage();
            //获取错误的属性的名字
            String field = item.getField();
            map.put(field, message);
        });
        return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(), BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data", map);
    }

    @ExceptionHandler(value = Throwable.class)
    public R handleException(Throwable throwable){
        log.error("错误",throwable);
        return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    }
}

【微服务实战】(七)数据校验J303,全局JSR303异常处理_第8张图片

你可能感兴趣的:(分布式实战)