依赖

pom.xml

<parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>2.4.0</version></parent>...<!-- ^api validation --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-validation</artifactId></dependency><dependency>    <groupId>javax.validation</groupId>    <artifactId>validation-api</artifactId>    <version>2.0.1.Final</version></dependency><dependency>    <groupId>org.hibernate</groupId>    <artifactId>hibernate-validator</artifactId>    <version>6.1.6.Final</version></dependency><!-- api validation$ -->

Spring配置

ValidationConfig.class:

import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;import javax.validation.Validator;import java.util.HashMap;import java.util.Locale;import java.util.Map;/** * 主动解决参数校验的扩大信息 */@Configurationpublic class ValidationConfig {    @Bean    public Validator validator() {        LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();        localValidatorFactoryBean.setMessageInterpolator(new MessageInterpolator());        return localValidatorFactoryBean;    }    private class MessageInterpolator extends ResourceBundleMessageInterpolator {        @Override        public String interpolate(String message, Context context, Locale locale) {            // 获取注解类型            String annotationTypeName = context.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();            // 依据注解类型获取自定义的音讯Code            String annotationDefaultMessageCode = VALIDATION_ANNATATION_DEFAULT_MESSAGES.get(annotationTypeName);            if (null != annotationDefaultMessageCode && !message.startsWith("javax.validation")                    && !message.startsWith("org.hibernate.validator.constraints")) {                // 如果注解上指定的message不是默认的javax.validation或者org.hibernate.validator等结尾的状况,                // 则须要将自定义的音讯Code拼装到原message的前面;                message += "{" + annotationDefaultMessageCode + "}";            }            return super.interpolate(message, context, locale);        }    }    private static final Map<String, String> VALIDATION_ANNATATION_DEFAULT_MESSAGES =            new HashMap<String, String>(20) {{                put("Min", "validation.message.min");                put("Max", "validation.message.max");                put("NotNull", "validation.message.notNull");                put("NotBlank", "validation.message.notBlank");                put("Size", "validation.message.size");            }};}

Notes:

  • 留神 Validator 的包门路是 javax.validation.Validator

编辑器对于properties编码转换

在IDEA的Setting -> Editor -> File Encodings,勾选Transarent native-to-asiic conversion
最好编码全副转为UTF-8

国际化资源文件

文件:

  • 默认:resources/ValidationMessages.properties
  • 英文:resources/ValidationMessages_en.properties
  • 内容:

    validation.message.min=不能小于{value}validation.message.max=不能大于{value}validation.message.notNull=不能为空validation.message.notBlank=不能为空validation.message.size=长度必须在{min}和{max}之间age=年龄mail=邮箱

接口注解

ValidatorMvc.class:

import lombok.Data;import lombok.ToString;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.*;import javax.validation.Valid;import javax.validation.constraints.Max;import javax.validation.constraints.Min;import javax.validation.constraints.NotBlank;import javax.validation.constraints.Size;/** * @author chad * @date 2021/10/26 18:13 * @since */@RestController@RequestMapping("validation")@Validatedpublic class ValidatorMvc {    @Validated    @Valid    @PostMapping("/hello")    public String hello(            @Min(value = 18, message = "{age}") @Max(value = 60, message = "{age}") @RequestParam Integer age            , @RequestBody @Valid User user    ) {        System.out.println("user ==> " + user.toString() + ", age ==> " + age);        return "Hello " + user.name;    }    @Data    @ToString    public static class User {        /**         * 姓名         */        @Size(min = 2, max = 10, message = "{name}")        private String name;        @NotBlank(message = "{mail}")        private String mail;    }}

Notes:

  • 类上的@Validated注解肯定要加,这样参数age能力被校验
  • @RequestBody肯定要带@Valid注解,这样外面的namemail能力被校验
  • 所有反对的参数校验注解在javax.validation.constraints包下

测试REST

  • 配置环境变量
    src/test/rest/http-client.env.json:

    ### 测试 age 小于18###### res ==> age must great or equals 18POST {{host}}/validation/hello?age=17content-type: application/json{"name": "zhangsan","mail": "test@mail.com"}### 测试 age 大于 60###### res ==> age must less or equals 60POST {{host}}/validation/hello?age=61content-type: application/json{"name": "zhangsan","mail": "test@mail.com"}### 测试 mail 为空-空字符串###### res ==> mail cannot emptyPOST {{host}}/validation/hello?age=18content-type: application/json{"name": "zhangsan","mail": ""}### 测试 mail 为空-null###### res ==> mail cannot emptyPOST {{host}}/validation/hello?age=18content-type: application/json{"name": "zhangsan","mail": null}### 测试 name 小于2位###### res ==> name length must between 2 and 10POST {{host}}/validation/hello?age=18content-type: application/json{"name": "0","mail": "test@mail.com"}### 测试 name 大于10位###### res ==> name length must between 2 and 10POST {{host}}/validation/hello?age=18content-type: application/json{"name": "01234567890","mail": "test@mail.com"}### 胜利###### res ==> Hello ZhangSanPOST {{host}}/validation/hello?age=18content-type: application/json{"name": "ZhangSan","mail": "test@mail.com"}

源码

  • Gitee