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();
    }
    复制代码
  • 相关阅读:
    跳出iframe
    leetcode 225. Implement Stack using Queues
    leetcode 206. Reverse Linked List
    leetcode 205. Isomorphic Strings
    leetcode 203. Remove Linked List Elements
    leetcode 198. House Robber
    leetcode 190. Reverse Bits
    leetcode leetcode 783. Minimum Distance Between BST Nodes
    leetcode 202. Happy Number
    leetcode 389. Find the Difference
  • 原文地址:https://www.cnblogs.com/gzhcsu/p/13705402.html
Copyright © 2011-2022 走看看