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

心已赠人 2023-06-30 11:59 59阅读 0赞

一、引入maven依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.projectlombok</groupId>
  8. <artifactId>lombok</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>com.alibaba</groupId>
  12. <artifactId>fastjson</artifactId>
  13. <version>1.2.58</version>
  14. </dependency>
  15. <dependency>
  16. <groupId>org.springframework.boot</groupId>
  17. <artifactId>spring-boot-starter-aop</artifactId>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.apache.commons</groupId>
  21. <artifactId>commons-lang3</artifactId>
  22. <version>${commons-lang3.version}</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>commons-beanutils</groupId>
  26. <artifactId>commons-beanutils</artifactId>
  27. <version>1.9.3</version>
  28. </dependency>
  29. </dependencies>

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

  1. /**
  2. * @Author: guandezhi
  3. * @Date: 2019/12/17 16:55
  4. */
  5. @Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
  6. @Retention(RetentionPolicy.RUNTIME)
  7. @Documented
  8. public @interface ParamValidate {
  9. }
  10. /**
  11. * @Author: guandezhi
  12. * @Date: 2019/12/17 17:13
  13. */
  14. public class ParamValidateException extends RuntimeException {
  15. public ParamValidateException(String errorMsg) {
  16. super(errorMsg);
  17. }
  18. public ParamValidateException(String errorMsg, Throwable e) {
  19. super(errorMsg, e);
  20. }
  21. }

三、定义参数校验切面

  1. /**
  2. * 参数校验切面
  3. *
  4. * @Author: guandezhi
  5. * @Date: 2019/12/17 15:07
  6. */
  7. @Slf4j
  8. @Aspect
  9. @Component
  10. public class ParamValidateAspect {
  11. @Resource
  12. private LocalValidatorFactoryBean localValidatorFactoryBean;
  13. /**
  14. * 切入controller的方法参数加了自定义注解ParamValidate的方法
  15. */
  16. @Pointcut("execution(public * com.gdz.demo.controller.*." +
  17. "*(@com.gdz.demo.annotation.ParamValidate (*),..)) ||" +
  18. " execution(public * com.gdz.demo.controller.*." +
  19. "*(..,@com.gdz.demo.annotation.ParamValidate (*)))")
  20. public void webLog() {
  21. }
  22. @Before("webLog()")
  23. public void before(JoinPoint joinPoint) throws Exception {
  24. doBefore(joinPoint);
  25. }
  26. /**
  27. * 参数校验
  28. *
  29. * @param joinPoint
  30. */
  31. private void doBefore(JoinPoint joinPoint) {
  32. Object paramValue = getMethodParamValue(joinPoint);
  33. if (paramValue != null) {
  34. Set<ConstraintViolation<Object>> validErrors = this.localValidatorFactoryBean.validate(paramValue, new Class[]{Default.class});
  35. Iterator iterator = validErrors.iterator();
  36. StringBuilder errorMsg = new StringBuilder();
  37. while (iterator.hasNext()) {
  38. ConstraintViolation constraintViolation = (ConstraintViolation) iterator.next();
  39. String error = constraintViolation.getPropertyPath() + ":" + constraintViolation.getMessage();
  40. errorMsg.append(iterator.hasNext() ? error + "; " : error);
  41. }
  42. if (!validErrors.isEmpty()) {
  43. throw new ParamValidateException(errorMsg.toString());
  44. }
  45. }
  46. }
  47. /**
  48. * 获取加了自定义参数校验注解的参数值
  49. *
  50. * @param joinPoint
  51. * @return
  52. */
  53. private Object getMethodParamValue(JoinPoint joinPoint) {
  54. Object[] args = joinPoint.getArgs();
  55. MethodSignature signature = (MethodSignature) joinPoint.getSignature();
  56. /*获取@ParamValidate注解*/
  57. Annotation[][] parameterAnnotations = signature.getMethod().getParameterAnnotations();
  58. if (parameterAnnotations != null) {
  59. for (Annotation[] parameterAnnotation : parameterAnnotations) {
  60. int paramIndex = ArrayUtils.indexOf(parameterAnnotations, parameterAnnotation);
  61. for (Annotation annotation : parameterAnnotation) {
  62. if (annotation != null && annotation instanceof ParamValidate) {
  63. return args[paramIndex];
  64. }
  65. }
  66. }
  67. }
  68. return null;
  69. }
  70. }

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

  1. /**
  2. * @Author: guandezhi
  3. * @Date: 2019/12/17 16:53
  4. */
  5. @Slf4j
  6. @ControllerAdvice
  7. public class GlobalExceptionHandler {
  8. @ResponseBody
  9. @ExceptionHandler(value = Exception.class)
  10. public ResultVo<Object> handleException(Exception e) {
  11. String errorMsg = "";
  12. ResultVo<Object> resultVo = new ResultVo<>();
  13. if (e instanceof NullPointerException) {
  14. errorMsg = "参数空指针异常";
  15. resultVo.setResultCode(HttpCode.FAIL.getMsgCode());
  16. } else if (e instanceof ParamValidateException) {
  17. errorMsg = "请求参数匹配错误," + e.getLocalizedMessage();
  18. resultVo.setResultCode(HttpCode.ILLEGAL_INPUT.getMsgCode());
  19. } else {
  20. errorMsg = e.getMessage();
  21. resultVo.setResultCode(HttpCode.ERROR.getMsgCode());
  22. log.error("系统异常:", e);
  23. }
  24. resultVo.setResultMsg(errorMsg);
  25. return resultVo;
  26. }
  27. }

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

  1. /**
  2. * @Author: guandezhi
  3. * @Date: 2020/1/17 15:04
  4. */
  5. @Slf4j
  6. @RestController
  7. public class IndexController {
  8. @PostMapping("/index")
  9. public String test(@RequestBody @ParamValidate User user) {
  10. return "success";
  11. }
  12. }

其中User实体如下:

  1. /**
  2. * @Author: guandezhi
  3. * @Date: 2020/1/17 15:05
  4. */
  5. @Data
  6. public class User {
  7. @NotNull(message = "用户名不能为空")
  8. private String userName;
  9. @NotBlank
  10. private String city;
  11. @Min(value = 1, message = "年龄最小值不能小于1")
  12. @Max(value = 99, message = "年龄最大值不能大于99")
  13. private int age;
  14. @Size(min = 1, max = 3, message = "别名不能少于1个,大于3个")
  15. private List<String> alias;
  16. }

测试结果如下:

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

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

发表评论

表情:
评论列表 (有 0 条评论,59人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SpringBoot 注解校验参数

    在项目开发中我们经常会遇到各种参数校验,尤其是表单参数的校验。当参数不多时我们可以在控制器中手动校验,但是一旦遇到需要校验的参数较多的post接口时,还去一个个的校验的话那会累