zoukankan      html  css  js  c++  java
  • 接口参数校验之@Valid与BindingResult

    接口方法往往需要对入参做一些校验,从而判断入参是否合格,而javax.validation包为我们提供了一些常用的参数校验注解,使用起来很方便。

    下面这个示例是检验入参对象中的password是否为空

    1. 创建一个User.java

    import javax.validation.constraints.NotBlank;
    
    public class User {
        private String username;
        @NotBlank
        private String password;
        private Integer age;
    }

    2. 接口方法

        @PostMapping("/user")
        public User createUser(@Valid  @RequestBody User user) {
            System.out.println(user);
            user.setAge(100);
            return user;
        }

    3. 测试代码 

     @Test
        public void testCreateUser() throws Exception {
            String jsonUser = "{"username":"admin","password":null}";
            mockMvc.perform(MockMvcRequestBuilders.post("/user")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(jsonUser))
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andExpect(MockMvcResultMatchers.jsonPath("$.age").value("100"));
        }

    4. 测试结果

    在测试代码中, 我们的password=null, 所以检验不通过,报400。而password不为null ,测试通过,如下

    5. BindingResult

    在以上的参数校验中,如果参数校验不通过,都不通进入接口方法,我们也不好收集错误信息.。 不过,spring为我们提供了一个java类BindingResult.java, 借助它即可!

    注意: @Valid与BindingResult要配套使用

    5.1 接口代码 

      @PostMapping("/user")
        public User createUser(@Valid  @RequestBody User user, BindingResult errors) {
            if (errors.hasErrors()) {
                errors.getAllErrors().stream().forEach(x-> System.out.println(x.getDefaultMessage()));
            }
            System.out.println(user);
            user.setAge(100);
            return user;
        }

    5.2 测试代码及打印结果

    5.3 自定义错误信息

    public class User {
        private String username;
        @NotBlank(message = "密码不能为空")
        private String password;
        private Integer age;
    }

    6. 自定义注解

    javax.validation默认提供了不少的注解,但是有时候,我们需要按照自己的逻辑去自定义注解。

    下面举个例子,在创建User对象时,先校验一下数据库是否存在相同的用户名username, 代码如下:

    6.1  查询逻辑

    @Service
    public class UserService {
    
        /**
         * 模拟查询,检验admin用户名是否存在
         * @param username
         * @return
         */
        public boolean findUserByUsername(String username) {
            if (StringUtils.equals(username, "admin")) {
                return false;
            }
            return true;
    
        }
    }

    6.2  自定义注解及实现

    import javax.validation.Constraint;
    import javax.validation.Payload;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.METHOD, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    // 该注解的具体实例逻辑类
    @Constraint(validatedBy = MyValidatorImpl.class)
    public @interface MyValidator {
        String message() default "admin用户已存在";
    
        Class<?>[] groups() default { };
    
        Class<? extends Payload>[] payload() default { };
    }
    import org.springframework.beans.factory.annotation.Autowired;
    import qinfeng.zheng.mockmvcdemo.service.UserService;
    
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    
    /**
     * 实现 ConstraintValidator接口的类,spring会将其弄成一个bean
     */
    public class MyValidatorImpl implements ConstraintValidator<MyValidator, String> {
        @Autowired
        private UserService userService;
    
        @Override
        public void initialize(MyValidator anno) {
            System.out.println("初始化。。。。");
        }
    
        /**
         * @param value   需要校验的参数值
         * @param constraintValidatorContext
         * @return  false : 校验不通过
         *          true : 校验通过
         */
        @Override
        public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
            return userService.findUserByUsername(value);
        }
    }

    6.3 实体类上注解的使用

    public class User {
        @MyValidator
        private String username;
        @NotBlank(message = "密码不能为空")
        private String password;
        private Integer age;
    }

    6.4 校验接口

      @PostMapping("/user")
        public User createUser(@Valid  @RequestBody User user, BindingResult errors) {
            if (errors.hasErrors()) {
                errors.getAllErrors().stream().forEach(x-> System.out.println(x.getDefaultMessage()));
            }
            System.out.println(user);
            user.setAge(100);
            return user;
        }

    6.5 测试代码

  • 相关阅读:
    asp.net mvc中ViewData、ViewBag和TempData的详解
    在asp.net WebForms中使用路由Route
    Sql Server批量删除指定表
    MongoDB安装并设置为windows服务以使其开机自启
    NPOI操作excel之写入数据到excel表
    NPOI操作excel之读取excel数据
    SQL Server 定时自动备份数据库
    如何用按钮的click事件去触发a标签的click事件
    C# Asp.net Quartz.NET作业调度之创建、安装、卸载、调试windows服务的简单事例
    c#中浅拷贝和深拷贝的理解
  • 原文地址:https://www.cnblogs.com/z-qinfeng/p/11746260.html
Copyright © 2011-2022 走看看