zoukankan      html  css  js  c++  java
  • 使用validator-api来验证spring-boot的参数

    作为服务端开发,验证前端传入的参数的合法性是一个必不可少的步骤,但是验证参数是一个基本上是一个体力活,而且冗余代码繁多,也影响代码的可阅读性,所以有没有一个比较优雅的方式来解决这个问题?

    这么简单的问题当然早就有大神遇到并且解决了,这一篇文章主要讲一下解决基于spring-boot的验证参数的比较好的方法:利用validator-api来进行验证参数。

    spring-boot-starter-web包里面有hibernate-validator包,它提供了一系列验证各种参数的方法,所以说spring-boot已经帮我们想好要怎么解决这个问题了。

    这篇文章针对spring-boot里面的spring-mvc介绍三种方式来验证参数。

    (一):这个方法在网上大部分都可以查到,先假设我们的restful的接口接受一个GradeAndClassroomModel类型的对象,并且这个类被定义成

    @Data
    public class GradeAndClassroomModel {  
    @Range(min = 1, max = 9, message = "年级只能从1-9")  
    private int grade;  
    @Range(min = 1, max = 99, message = "班级只能从1-99")  
    private int classroomNumber;
    }

    利用validator提供的一系列注解,比如本例中的@Range,就可以表示参数的范围和出错时候的提示信息。还有很多其他注解,这里就不一一列出

    然后我们的Controller层的代码为

    @RequestMapping(value = "/paramErrorTest", method = RequestMethod.GET)
    public String paramErrorTest(    
      @Valid    
      @ModelAttribute    
      GradeAndClassroomModel gradeAndClassroomModel, 
      BindingResult result) {  
      return classroomService.getTeacherName(gradeAndClassroomModel.getGrade(), gradeAndClassroomModel.getClassroomNumber());
    }

    其中如果验证出错,result对象里面就会有错误信息,然后可以自己进行处理。

    (二): 针对上面的例子,会有人说,就两个参数,为什么要作为对象呢?会不会太麻烦?确实,如果只有少数对象,直接把参数写到Controller层,然后在Controller层进行验证就可以了。

    @RequestMapping(value = "/teacherName", method = RequestMethod.GET)
    public String teacherName(
      @Range(min = 1, max = 9, message = "年级只能从1-9")        
      @RequestParam(name = "grade", required = true) 
      int grade,  
      @Min(value = 1, message = "班级最小只能1")    
      @Max(value = 99, message = "班级最大只能99")      
      @RequestParam(name = "classroom", required = true)    
      int classroom) {  
    return classroomService.getTeacherName(grade, classroom);
    }

    如果直接把validator提供的注解移除来写到请求参数上面的话是不是就可以了呢?答案是错,为什么这样不能成功的验证参数呢?具体原因大家可以参考官方文档:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/htmlsingle/#validation-beanvalidation-spring-method

    上面的文档已经说的很清楚了,所以我们需要创建一个Bean

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {  
      return new MethodValidationPostProcessor();
    }

    然后在类方法上面加上注解@Validated

    @RestController
    @RequestMapping("/spring-boot/classroom")
    @Validated
    public class ClassroomController {
     ...
    }

    然后之前没有生效的注解@Range@Min@Maxvalidator包里面提供的注解就可以生效了。

    (三)估计到了这里又会有人问,如果validator包里面注解不能满足我们的需求,我们是否可以自己定义参数验证的逻辑。答案是肯定的,我们可以利用

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.PARAMETER, ElementType.FIELD})
    @Constraint(validatedBy = {Validator.class})
    public @interface ParamValidator {
    

    String message() default "Parameter error!";

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

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

    }

    public class Validator implements ConstraintValidator<ParamValidator, Object> {
      ...
    }

    组合进行自定义,具体的例子网上其他文章就很多了,这里就不进行详细的例子了,但是最终使用的时候就是

      @RequestMapping(value = "/paramValidator", method = RequestMethod.GET)
      public String paramValidator(
          @ParamValidator(isRequired = true, desc = "年级", range = "int:1~9", message = "年级只能从1-9")
          @RequestParam(name = "grade", required = true)
          int grade,
          @ParamValidator(isRequired = true, desc = "班级", range = "int:1~99", message = "班级只能从1-99")
          @RequestParam(name = "classroom", required = true)
          int classroom) {
        return classroomService.getTeacherName(grade, classroom);
      }

    另外不要忘记方法二里面里面提到的MethodValidationPostProcessor这个bean,如果没有初始化这个bean,自定义的验证方法也不会执行。验证逻辑会失效。

    是不是通过这样写注解的方式来验证进行请求的参数,代码逻辑更佳清晰和优雅?表达的含义也会更佳清楚?并且没有了大量重复的类似的验证代码。

    Ps:这里的代码都是基于spring-mvc框架来试验的,如果有人并没有使用spring-mvc作为rest框架,而是使用jersey来作为rest框架的话,可能一些细节方面需要调整, 但是这三种方案应该都是可以兼容的。

    原文地址:https://www.cnblogs.com/mawang/p/6767906.html?utm_source=itdadao&utm_medium=referral
  • 相关阅读:
    Spring 事务管理
    016 sleep,wait,yield,join区别
    013 GC机制
    011 CountDownLatch,CyclicBarrier和Semaphore
    012 public等关键字可见性
    010 JVM类加载
    009 JVM内存结构以及GC机制
    008 BlockingQueue理解
    python3 正则表达式
    python django
  • 原文地址:https://www.cnblogs.com/jpfss/p/11448058.html
Copyright © 2011-2022 走看看