zoukankan      html  css  js  c++  java
  • Spring Validation 实践

    参考文档:https://springboot.io/t/topic/2582

    Java API 规范( JSR303 )定义了 Bean 校验的标准 validation-api ,但没有提供实现。 hibernate validation 是对这个规范的实现,并增加了校验注解如 @Email 、 @Length 等。 Spring Validation 是对 hibernate validation 的二次封装。以 spring-boot 项目为例,介绍 Spring Validation 的使用。

    引入依赖:(如果 spring-boot 版本小于 2.3.x , spring-boot-starter-web 会自动传入 hibernate-validator 依赖。如果 spring-boot 版本大于 2.3.x ,则需要手动引入依赖)

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.1.Final</version>
    </dependency>

    对于 web 服务来说,为防止非法参数对业务造成影响,在 Controller 层一定要做参数校验的!大部分情况下,请求参数分为如下两种形式:

    1. POST 、 PUT 请求,使用 requestBody 传递参数;
    2. GET 请求,使用 requestParam/PathVariable 传递参数。

    requestBody 参数校验

    POST 、 PUT 请求一般会使用 requestBody 传递参数,这种情况下,后端使用 DTO对象(数据传输对象Data Transfer Object) 进行接收。 只要给DTO对象加上 @Validated 注解就能实现自动参数校验 。比如,有一个保存 User 的接口,要求 userName 长度是 2-10 , account 和 password 字段长度是 6-20 。如果校验失败,会抛出 MethodArgumentNotValidException 异常, Spring 默认会将其转为 400(Bad Request) 请求。

    在 DTO 字段上声明约束注解

    @Data
    public class UserDTO {
    
        private Long userId;
    
        @NotNull(message = "名称不能为空")
        @Length(min = 2, max = 10)
        private String userName;
    
        @NotNull(message = "账号不能为空")
        @Length(min = 6, max = 20)
        private String account;
    
        @NotNull
        @Length(min = 6, max = 20)
        private String password;
    }

    在方法参数上声明校验注解

    @PostMapping("/save")
    public Result saveUser(@RequestBody @Validated UserDTO userDTO) {
        // 校验通过,才会执行业务逻辑处理
        return Result.ok();
    }

    注:这种情况下, 使用 @Valid 和 @Validated 都可以 。

    requestParam/PathVariable 参数校验

    GET 请求一般会使用 requestParam/PathVariable 传参。如果参数比较多(比如超过6个),还是推荐使用 DTO 对象接收。否则,推荐将一个个参数平铺到方法入参中。在这种情况下, 必须在 Controller 类上标注 @Validated 注解,并在入参上声明约束注解(如 @Min 等) 。如果校验失败,会抛出 ConstraintViolationException 异常。代码示例如下:

    @RequestMapping("/api/user")
    @RestController
    @Validated
    public class UserController {
        // 路径变量
        @GetMapping("{userId}")
        public Result detail(@PathVariable("userId") @Min(10000000000000000L) Long userId) {
            // 校验通过,才会执行业务逻辑处理
            UserDTO userDTO = new UserDTO();
            userDTO.setUserId(userId);
            userDTO.setAccount("11111111111111111");
            userDTO.setUserName("xixi");
            userDTO.setAccount("11111111111111111");
            return Result.ok(userDTO);
        }
    
        // 查询参数
        @GetMapping("getByAccount")
        public Result getByAccount(@Length(min = 6, max = 20) @NotNull String  account) {
            // 校验通过,才会执行业务逻辑处理
            UserDTO userDTO = new UserDTO();
            userDTO.setUserId(10000000000000003L);
            userDTO.setAccount(account);
            userDTO.setUserName("xixi");
            userDTO.setAccount("11111111111111111");
            return Result.ok(userDTO);
        }
    }

    分组校验。

    分组接口可以写到DTO里面。

    约束注解上声明适用的分组信息 groups

    @Data
    public class UserDTO {
    
        @Min(value = 10000000000000000L, groups = Update.class)
        private Long userId;
    
        @NotNull(groups = {Save.class, Update.class})
        @Length(min = 2, max = 10, groups = {Save.class, Update.class})
        private String userName;
    
        @NotNull(groups = {Save.class, Update.class})
        @Length(min = 6, max = 20, groups = {Save.class, Update.class})
        private String account;
    
        @NotNull(groups = {Save.class, Update.class})
        @Length(min = 6, max = 20, groups = {Save.class, Update.class})
        private String password;
    
        /**
         * 保存的时候校验分组
         */
        public interface Save {
        }
    
        /**
         * 更新的时候校验分组
         */
        public interface Update {
        }
    }

     @Validated 注解上指定校验分组

    @PostMapping("/save")
    public Result saveUser(@RequestBody @Validated(UserDTO.Save.class) UserDTO userDTO) {
        // 校验通过,才会执行业务逻辑处理
        return Result.ok();
    }
    
    @PostMapping("/update")
    public Result updateUser(@RequestBody @Validated(UserDTO.Update.class) UserDTO userDTO) {
        // 校验通过,才会执行业务逻辑处理
        return Result.ok();
    }
    复制代码
  • 相关阅读:
    重学Mybatis从入门到源码之一
    Ribbon的负载均衡策略及使用方法
    SpringCloud之Ribbon的使用及源码解析
    FeignClient spi 调用 短路异常 & 线程池配置
    springboot 中yml配置
    jrebel 启动失败的处理
    使用@Cacheable注解时,Redis连不上,直接调用方法内部的解决方案
    redis scan 命令指南
    正式学习单元测试
    Cannot assign requested address 和 SO_REUSEADDR 参数
  • 原文地址:https://www.cnblogs.com/gzhcsu/p/13705402.html
Copyright © 2011-2022 走看看