自定义注解实现参数校验

自定义注解实现参数校验

一.定义注解类

/**
 * 用户验证状态是否在指定范围内的注解
 */
@Documented
// JVM会读取注解,同时会保存到class文件中
@Retention(RetentionPolicy.RUNTIME)
// 用于字段或者方法参数
@Target({ElementType.FIELD,ElementType.PARAMETER})
// 指定检验处理类, 可以指定多个
@Constraint(validatedBy = FlagValidatorClass.class)
public @interface FlagValidator {

	// 校验参数是否在某个int 数组中
    int[] value() default {};

	// 出现检验失败的错误消息
    String message() default "flag is not found";

	// 分组
    Class<?>[] groups() default {};
    
    Class<? extends Payload>[] payload() default {};
}

二.定义校验类

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * 状态标记校验器 校验 FlagValidator 注解的地方
 *
 * ConstraintValidator<FlagValidator, Integer>
 *     FlagValidator : 校验的注解
 *     Integer       : 前端传的值
 */
public class FlagValidatorClass implements ConstraintValidator<FlagValidator, Integer> {
    private int[] values;
    // 初始化方法
    @Override
    public void initialize(FlagValidator flagValidator) {
        // 获取到 设置了 FlagValidator 注解参数中的 value 范围
        this.values = flagValidator.value();
    }
    // 校验
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
        boolean isValid = false;
        // 如果参数没有传值则默认是true, 不做检验
        if(value==null){
            //当状态为空时使用默认值
            return true;
        }
        // 否则遍历改参数的 value 看参数值是否在范围内
        for (int item : values) {
            if (item == value) {
                isValid = true;
                break;
            }
        }
        return isValid;
    }
}

如果又需要对Double类型的参数进行类似的校验,则直接复制上面的类,修改类型的范型即可, 这样就会根据参数的类型去找相应的校验器

public class FlagValidatorClass implements ConstraintValidator<FlagValidator, Double> {
	...
}

三.统一异常处理

//如果返回的为json数据或其它对象,添加该注解
@RestControllerAdvice
//@ControllerAdvice
public class GlobalExceptionHandler {
	
   /**
     * 前端参数提交是json格式时校验抛出的异常
     * json格式提交时,采用json数据的数据转换器进行处理,错误时抛出MethodArgumentNotValidException异常
     */
	// 拦截对应的异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    // 指明 400 异常码
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result handlerNotValidException(MethodArgumentNotValidException exception) throws Exception {
    	return handlerNotValidException(exception);
    }

 	/**
     * 仅对于表单提交有效
     * 如果是表单类型的提交,进行参数校验错误时会抛出BindException异常
     */
    // 拦截对应的异常
    @ExceptionHandler(BindException.class)
    // 指明 400 异常码
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result  handlerBindException(BindException exception) {
        return handlerNotValidException(exception);
    }
	
	private ResultDTO handlerNotValidException(Exception e){
        BindingResult result;
        if (e instanceof BindException) {
            BindException exception = (BindException) e;
            // 获取验证失败的结果
            result = exception.getBindingResult();
        } else {
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
            // 获取验证失败的结果
            result = exception.getBindingResult();
        }
        StringBuilder errorMsg =new StringBuilder("校验失败:");
        for (FieldError fieldError : result.getFieldErrors()) {
            errorMsg.append(fieldError.getDefaultMessage()).append(", ");
        }
        // 这里自定义了一个异常码的枚举,其实值就是一个状态码字符串
        //return Result.fail(CoreConstants.E_PARAMETER,errorMsg.toString());
        return Result.fail("5002",errorMsg.toString());
    }
}

其中Result是返给前端的封装类

public class Result<T extends Object>{
    private static final long serialVersionUID = -7387542509934814087L;
    // 成功标志
    private boolean           success;
    // 状态码
    private String            code;
    // 异常消息
    private String            message;
    // 数据
    private T                 data;
	// xxx 这里一些方法省略写了
    public static ResultDTO fail(String code, String msg) {
       ResultDTO result = new ResultDTO(false, null,code, msg);
       return result;
    }
	public ResultDTO(boolean success, Object data, String code, String message) {
        this.data = (T) data;
        this.success = success;
        this.code = code;
        this.message = message;
    }
}

四.效果图

在这里插入图片描述
这里的message格式可以根据自己的需求进行改造

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值