注解@Validated不能校验泛型参数,使用Aop来拦截,对属性上有@NotBlank等注解的进行手动校验

文章讲述了在SpringMVC中,@Validated注解对BaseRequest泛型参数的校验不起作用,需借助AOP进行拦截,并在Controller方法前手动验证。同时介绍了如何处理不同类型的异常,如ConstraintViolation异常和自定义异常。
摘要由CSDN通过智能技术生成

Controller 的方法上面加注解@Validated不能校验泛型参数,直接进入到方法中,需要进行手动校验
使用aop来拦截Controller方法,不符合校验的请求参数直接抛出异常

@Data
public class BaseRequest<T> implements Serializable {
    private T params;
}

public class TTRequest<T> extends BaseRequest<T> {
    /**
     * 公共的参数Id
     */
    private String id;
}

    /**
    @Validated 加上不起作用,不支持泛型参数
    **/
    @PostMapping(value = "/test")
    public BaseResponse<> test( @RequestBody TTRequest<xxx> request) {
      
        return BaseResponse.ok();
    }


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.List;
import java.util.Set;

@Aspect
@Component
@Slf4j
public class InterceptControllerAspect {

    private static final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

    @Before(value = "execution(* xxxx.xxxController.*(..))&& args(request,..)")
    public void interceptTenantRequest(JoinPoint joinPoint, TTRequest<?> request) {
        if (request != null) {
            String id = request.getId();
            if (StringUtils.isBlank(id)) {
                throw new BizException("请求参数异常");
            }
            String methodName = joinPoint.getSignature().getName();
            log.info("methodName {}:Intercepted Tenant Request with  Id:{} ", methodName, id);
            validate(request.getParams());
        }
    }

    public static <T> void validate(T t) {
        if (t instanceof List) {
            if (((List<?>) t).size() == 0) {
                throw new BizException("请求参数异常");
            }
        }
        if (t instanceof Set) {
            if (((Set<?>) t).size() == 0) {
                throw new BizException("请求参数异常");
            }
        }
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
        for (ConstraintViolation<T> constraintViolation : constraintViolations) {
            //这里循环获取错误信息,可以自定义格式
            String property = constraintViolation.getPropertyPath().toString();
            String msg = constraintViolation.getMessage();
            throw new BizException(property + msg);
        }
    }

}

接收到异常后,进行全局捕获,统一异常处理

@Slf4j
@ControllerAdvice
public class ControllerHandler {


    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public BaseResponse exceptionHandler(MethodArgumentNotValidException e) {

        BindingResult result = e.getBindingResult();
        String msg=ApiErrorCode.INVALID_PARAM.getMsg();
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            if (CollectionUtils.isNotEmpty(errors)) {
                msg =msg+":"+ errors.stream().map(c -> c.getDefaultMessage()).collect(Collectors.joining(","));
            }
        }
        log.info("param exception>>>>>>>>>>>>>>>>>>>>>>>>>>" + e.getMessage(), e);
        return BaseResponse.fail(msg);
    }

    @ExceptionHandler(BizException.class)
    @ResponseBody
    public BaseResponse exceptionHandler(BizException e) {
        log.info("business exception>>>>>>>>>>>>>>>>>>>>>>>>>>code:{}||message:{}", e.getCode(), e.getMsg());
        return BaseResponse.fail(e.getMsg());
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public BaseResponse exceptionHandler(Exception e) {
        log.error("system exception>>>>>>>>>>>>>>>>>>>>>>>>>>message:" + e.getMessage(), e);
        return BaseResponse.fail("服务器开小差,请稍后重试");
    }
}
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值