接口参数校验之@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 测试代码

原文地址:https://www.cnblogs.com/z-qinfeng/p/11746260.html

时间: 2024-08-30 03:15:15

接口参数校验之@Valid与BindingResult的相关文章

SpringBoot实现通用的接口参数校验

本文介绍基于Spring Boot和JDK8编写一个AOP,结合自定义注解实现通用的接口参数校验. 缘由 目前参数校验常用的方法是在实体类上添加注解,但对于不同的方法,所应用的校验规则也是不一样的,例如有一个AccountVO实体: publicclassAccountVO{privateStringname;//姓名privateIntegerage;//年龄} 假设存在这样一个业务:用户注册时需要填写姓名和年龄,用户登陆时只需要填写姓名就可以了.那么把校验规则加在实体类上显然就不合适了. 所

web接口参数校验神器-json schema 快速入门

Json Schema 快速入门 JSON 模式是一种基于 JSON 格式定义 JSON 数据结构的规范.它被写在 IETF 草案下并于 2011 年到期.JSON 模式: 描述现有数据格式. 干净的人类和机器可读的文档. 完整的结构验证,有利于自动化测试. 完整的结构验证,可用于验证客户端提交的数据. Json schema 格式 Json schema 本身遵循Json规范,本身就是一个Json字符串,先来看一个例子 { "$schema": "http://json-s

Spring Boot 参数校验

1.背景介绍 开发过程中,后台的参数校验是必不可少的,所以经常会看到类似下面这样的代码 这样写并没有什么错,还挺工整的,只是看起来不是很优雅而已. 接下来,用Validation来改写这段 2.Spring Boot文档中的Validation 在Spring Boot的官网中,关于Validation只是简单的提了一句,如下 其实,Spring Validator和Hibernate Validator是两套Validator,可以混着用,这里我们用Hibernate Validator 3.

【Java】使用@Valid+BindingResult进行controller参数校验

@Valid @Valid注解用于校验,所属的包: javax.validation.Valid. 你可以定义实体,在实体的属性上添加校验规则,在API接收数据时添加@Valid注解,这时你的实体将会开启一个校验的功能. ## 空检查 @NotEmpty:用在集合类上面:不能为null,而且长度必须大于0  @NotBlank: 用在String上面:只能作用在String上,不能为null,而且调用trim()后,长度必须大于0  @NotNull:用在基本类型上:不能为null,但可以为em

SpringBoot 参数校验的方法

Introduction 有参数传递的地方都少不了参数校验.在web开发中,前端的参数校验是为了用户体验,后端的参数校验是为了安全.试想一下,如果在controller层中没有经过任何校验的参数通过service层.dao层一路来到了数据库就可能导致严重的后果,最好的结果是查不出数据,严重一点就是报错,如果这些没有被校验的参数中包含了恶意代码,那就可能导致更严重的后果. 这里我们主要介绍在springboot中的几种参数校验方式.常用的用于参数校验的注解如下: @AssertFalse 所注解的

实用———springmvc接收参数校验

https://www.cnblogs.com/funyoung/p/8670550.html https://www.cnblogs.com/monkeydai/p/10068547.html [email protected] 两粒种子,一片森林. 首页 新随笔 联系 订阅 管理 随笔 - 21  文章 - 0  评论 - 8 两粒种子,一片森林. 首页 新随笔 联系 订阅 管理 随笔 - 21  文章 - 0  评论 - 8 SpringMVC参数校验 使用SpringMVC时配合hibe

springmvc参数校验+统一异常处理

一.PathVariable 校验 在定义 Restful 风格的接口时,通常会采用 PathVariable 指定关键业务参数,如下: @GetMapping("/path/{group:[a-zA-Z0-9_]+}/{userid}") @ResponseBody public String path(@PathVariable("group") String group, @PathVariable("userid") Integer us

为List&lt;T&gt;中的T进行参数校验

1.现在前端发送了一个POST请求,他的Data是一个数组,而不是对象(jsonObj的值两侧是中括号). var jsonObj = [{'id':11, 'name':'叵'}, {'id':12, 'name':'卜'}]; $.ajax({ type : "post", // 省略 data : JSON.stringify(jsonObj), // 省略 }); 2.后端的请求方法应该让一个Input的数组对象,或是Input泛型的List对象入参,来进行数据绑定 @Requ

jsr-303 参数校验-学习(转)

1.是什么? JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,比如: ------------------------------------------------- @NotNull(message="名字不能为空") private String userName; @Max(value=90,message="年龄不能超过90岁") private int age; @Email(message="邮箱格式错误&