Springmvc参数校验

[toc]

springMVC 的基本参数校验

使用@RequestParam 注解控制请求参数

  1. 在写控制层的接口时,我们需要对前端或者接口访问者进行访问参数的校验,如果将参数的校验逻辑写到控制层的代码里,会造成代码重复,资源浪费,不美观。

  2. 对于控制层接口的基本类型方法参数,我们可以用注解控制,一般都是GET方法居多

  3. 相配合的还需要一个自定义的全局错误返回处理,这样就可以完全的自定义了

例如:

    @GetMapping("/hello")
    public Response sayHello(@RequestParam String hello,long start) {
        return Response.success(hello);
    }
   @ExceptionHandler
    public Response exceptionMatchHandle(Exception e){
            //参数绑定异常 SpringMVC异常
            if (e instanceof ServletRequestBindingException){
                log.error("发生了SpringMVC异常:{}",e.getMessage());
                if (e instanceof MissingRequestHeaderException){
                    return Response.failure(ErrorCode.ERROR_PARMS_NO_HEADER);
                }
                return Response.failure(ErrorCode.ERROR_PARMS_NO_PARM);
            }
    }

如上所示,在接口声明中可以将请求参数加上@RequestParam 注解,当访问接口没有传该参数的时候,springmvc会报异常然后可以使用自定义的异常处理统一捕获处理即可,

--- 在请求参数的声明中,尽量不要声明基本类型上图的start,因为如果声明了基本类型就相当于,该参数是必传的,如果没有就会报错,如果你希望start是非必须的,可以声明成引用类型Long。

@RequestParam的使用

  1. @RequestParam的可用属性

    • 以上是@RequestParam注解的声明,可以看到由四个属性组成,name和value相当于同一个,也就是可用的有三个

    • name(value):标识该参数的名称,也就是访问接口时需要传的参数名称,默认是接口定义时的参数名,对应上述的hello,但可以通过该属性覆盖重写参数名 @RequestParam(name="hi") String hello此时访问接口传参名得是hi

    • required:标识该参数是不是必须参数,默认是true就是必传,如果没有该参数就会报错,如果改为false,则该参数不是必须,可以不传

    • defaultValue() : 当访问接口时,该参数没有传的话,就给与一个默认的值

    • defaultValue 与required的值无关,当required为true时,配置了defaultValue,即便不传hello的值,依然可以访问成功,返回值为 asasasasa

使用JSR-303验证框架

spring boot 支持JSR-303、Bean验证框架,默认实现用的是 Hibernate validator。在Spring MVC中,只需要使用@Valid注解标注在方法参数商,Spring Boot即可对参数对象进行校验,校验结果会放在BindingResult对象中。

如何使用验证框架

相关注解

JSR-303定义了一系列的注解用来验证Bean的属性,常用的有以下几种,用于标注在被校验对象的类字段之上。全部注解可以参考JSR 303 – Bean Validation

  • 对于空的检查

    • @Null:验证对象是否为空;

    • @NotNull:验证对象不为空;

    • @NotBlank:验证字符串不为空或者不是空字符串,比如""和“ ”都会验证失败;

    • @NotEmpty:验证对象部位null,或者集合不为空。

  • 长度的检查:

    • @Size(min= ,max=):验证对象长度,可支持字符串、集合;

    • @Length:字符串的大小。

  • 数值检测:

    • @Min:验证数字是否大于等于指定的值;

    • @Max:验证数字是否小于等于指定的值;

    • @Digits:验证数字是否符合指定格式,如@Digits(integer=9,fraction=2)表示,数字要求必须是小数点前有9位,小数点后有2位;

    • @Range:验证数字是否在指定范围内,如@Range(min=1,max=1000)。

  • 其他:

    • @Email:验证是否为邮件格式,为null则不做校验;

    • @Pattern:验证String对象是否符合正则表达式的规则。

  • 注解依赖的包:

如何使用

  1. 首先在需要校验的类中字段上标注需要的注解

    ```java /**

    • @author 飞客不去

      */

      @Data

      public class Drink {

}

  1. 如上所述,在drink类中需要校验的字段上标注对应的控制注解,之后在请求参数处标注注解@Valid 声明该参数需要校验即可

  2. 在需要校验的接口中增加参数,BindingResult result,框架会将校验的结果放在该对象中, 1. 该对象包含了所有验证结果 2. 可以使用提供的两个方法查看 1. hasErrors,判断验证是否通过; 2. getAllErrors,得到所有错误信息,通常返回FieldError列表 3. 如果在需要校验的接口参数处没有声明BindingResult result参数,则SpringMVC会抛出异常,可以使用全局异常处理。 4. 对于验证的结果一般都会让框架抛异常出去,但是如果想要自己查看并解决校验结果,可以增加BindingResult result对象

  3. 对校验规则的分组

    1. 在使用场景中,可能会遇到这样的情况:当你添加的时候ID可以为空,但是在修改的时候ID又不可以为空,通常不同的业务逻辑,会有不同的验证逻辑,这个应该怎么解决呢

    2. JSR-303提供了group概念,规定每个校验注解都必须支持,腰间注解用在字段上的时候,可以指明使用的组

    ```java

    @Data public class AppMonitor {

    public interface Add{}

    @NotNull(groups = Add.class) private Long id; private String name;

}

框架的高级用法

  1. 当我们接口的参数内部还引用其他对象时,需要对内部的对象也做校验应该如何?

    只需要在参数对象内部的对象引用字段上加上@Valid注解即可,此时框架就会对Food 内部的Drink类也会做校验了,不加则不会做校验,即便Drink内部也有校验注解。

  2. 对于同一个Drink类,可能不同的接口需要做的校验类型不同,那么总不能一个接口可以用,另一个接口就不能在用了吧。

    1. 对于这个情况,一般都会有解决方法,不会说只试用单个,那么就没什么扩展的意义。

    2. 这个情况可以类似于我们之前说的@Jsonview,这是可以分组的,不过要加上一个注解@Validate

    3. 具体实施如下

      1. 在参数类的内部新建接口用于分组,

      2. 在每个校验注解内部配置所属的组

      3. 在接口定义的地方使用@Validate注解并定义好校验需要的接口分组

      代码实现如下:

      1. 实体类(参数类)

      ```java @Data public class Drink { public interface Update{} public interface Add{}

框架的扩展

  1. 框架给出的注解是有限的,但是大部分情况下我们已经够用了,

  2. 我们有时候自己的业务比较复杂,对校验也可能比较复杂。

  3. 此时我们可以自己定义一个我们自己的注解,校验框架也是允许自定义注解的 。

自定义校验

  1. 举例说明自定义注解的实现:我们需要一个自定义注解来校验货物的库存

  1. 自定义注解如下格式

  • 自定义注解Stock跟其他注解差不多,作用就是如果属性值小于min的话,就会报错。

  • 需要提供一个@Constraint来说明需要什么类来验证注解

  • 验证注解必须要包含以下几个属性

    • message,用于创建错误细腻些,支持表达式,如库存不能低于{min}个

    • groups,验证规则分组

    • payload,定义了验证的有效负荷

    • 后两个可以自行琢磨怎么使用,也可以不使用

  • 新建一个StockValidator类来验证注解

  • StockValidator类必须实现ConstraintValidator接口initialize方法以及验证方法isValid

  • 具体的校验逻辑在isValid方法中做校验

  • 其他参数可以自行琢磨,不在本篇的介绍中,这个程度至少自己就够用了

结语

写博客是为了记录自己的学习,也是分享给大家自己的问题解决,如果能帮上看到这个博客的人时最好的了,且写且珍惜。

最后更新于

这有帮助吗?