一个注解搞定全局参数校验

一、引入maven依赖

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.58</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>${commons-lang3.version}</version>
		</dependency>

		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.9.3</version>
		</dependency>

	</dependencies>

二、自定义参数校验注解和异常

/**
 * @Author: guandezhi
 * @Date: 2019/12/17 16:55
 */
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamValidate {
}
/**
 * @Author: guandezhi
 * @Date: 2019/12/17 17:13
 */
public class ParamValidateException extends RuntimeException {

    public ParamValidateException(String errorMsg) {
        super(errorMsg);
    }

    public ParamValidateException(String errorMsg, Throwable e) {
        super(errorMsg, e);
    }
}

三、定义参数校验切面

/**
 * 参数校验切面
 *
 * @Author: guandezhi
 * @Date: 2019/12/17 15:07
 */
@Slf4j
@Aspect
@Component
public class ParamValidateAspect {

    @Resource
    private LocalValidatorFactoryBean localValidatorFactoryBean;

    /**
     * 切入controller的方法参数加了自定义注解ParamValidate的方法
     */
    @Pointcut("execution(public * com.gdz.demo.controller.*." +
            "*(@com.gdz.demo.annotation.ParamValidate (*),..)) ||" +
            " execution(public * com.gdz.demo.controller.*." +
            "*(..,@com.gdz.demo.annotation.ParamValidate (*)))")

    public void webLog() {
    }

    @Before("webLog()")
    public void before(JoinPoint joinPoint) throws Exception {
        doBefore(joinPoint);
    }

    /**
     * 参数校验
     *
     * @param joinPoint
     */
    private void doBefore(JoinPoint joinPoint) {
        Object paramValue = getMethodParamValue(joinPoint);
        if (paramValue != null) {
            Set<ConstraintViolation<Object>> validErrors = this.localValidatorFactoryBean.validate(paramValue, new Class[]{Default.class});
            Iterator iterator = validErrors.iterator();
            StringBuilder errorMsg = new StringBuilder();

            while (iterator.hasNext()) {
                ConstraintViolation constraintViolation = (ConstraintViolation) iterator.next();
                String error = constraintViolation.getPropertyPath() + ":" + constraintViolation.getMessage();
                errorMsg.append(iterator.hasNext() ? error + "; " : error);
            }
            if (!validErrors.isEmpty()) {
                throw new ParamValidateException(errorMsg.toString());
            }
        }
    }


    /**
     * 获取加了自定义参数校验注解的参数值
     *
     * @param joinPoint
     * @return
     */
    private Object getMethodParamValue(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        /*获取@ParamValidate注解*/
        Annotation[][] parameterAnnotations = signature.getMethod().getParameterAnnotations();
        if (parameterAnnotations != null) {
            for (Annotation[] parameterAnnotation : parameterAnnotations) {
                int paramIndex = ArrayUtils.indexOf(parameterAnnotations, parameterAnnotation);
                for (Annotation annotation : parameterAnnotation) {
                    if (annotation != null && annotation instanceof ParamValidate) {
                        return args[paramIndex];
                    }
                }
            }
        }
        return null;
    }
}

四、全局捕获参数校验异常,并转换成自己想要的格式返回。

/**
 * @Author: guandezhi
 * @Date: 2019/12/17 16:53
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {


    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResultVo<Object> handleException(Exception e) {
        String errorMsg = "";
        ResultVo<Object> resultVo = new ResultVo<>();

        if (e instanceof NullPointerException) {
            errorMsg = "参数空指针异常";
            resultVo.setResultCode(HttpCode.FAIL.getMsgCode());
        } else if (e instanceof ParamValidateException) {
            errorMsg = "请求参数匹配错误," + e.getLocalizedMessage();
            resultVo.setResultCode(HttpCode.ILLEGAL_INPUT.getMsgCode());
        } else {
            errorMsg = e.getMessage();
            resultVo.setResultCode(HttpCode.ERROR.getMsgCode());
            log.error("系统异常:", e);
        }
        resultVo.setResultMsg(errorMsg);
        return resultVo;
    }
}

五、测试一下:只需要在需要校验的参数旁边加上@ParamValidate 即可

/**
 * @Author: guandezhi
 * @Date: 2020/1/17 15:04
 */
@Slf4j
@RestController
public class IndexController {

    @PostMapping("/index")
    public String test(@RequestBody @ParamValidate User user) {
        return "success";
    }
}

其中User实体如下:

/**
 * @Author: guandezhi
 * @Date: 2020/1/17 15:05
 */
@Data
public class User {

    @NotNull(message = "用户名不能为空")
    private String userName;

    @NotBlank
    private String city;

    @Min(value = 1, message = "年龄最小值不能小于1")
    @Max(value = 99, message = "年龄最大值不能大于99")
    private int age;

    @Size(min = 1, max = 3, message = "别名不能少于1个,大于3个")
    private List<String> alias;
}

测试结果如下:

{
  "resultCode": 401,
  "resultMsg": "请求参数匹配错误,alias:别名不能少于1个,大于3个; age:年龄最大值不能大于99; userName:用户名不能为空",
  "data": null
}

代码地址:https://github.com/dezhiguan/paramvalidate.git

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值