相关依赖

如果开发普通 Java 程序的的话,你需要可能需要像下面这样依赖:

  <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.9.Final</version>
   </dependency>
   <dependency>
             <groupId>javax.el</groupId>
             <artifactId>javax.el-api</artifactId>
             <version>3.0.0</version>
     </dependency>
     <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.6</version>
     </dependency>

实体类

package com.test.valid.entity;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

public class Person {

    @NotNull(message = "id字段不能为空")
    private String id;

    @Size(max = 20)
    @NotNull(message = "name字段不能为空")
    private String name;

    @Pattern(regexp = "((^Man$|^Woman$|^UGM$))",message = "sex字段只能是Man、Woman、UGM")
    @NotNull(message = "sex字段不能为空")
    private String sex;

    @Email(message = "email格式不正确")
    @NotNull(message = "email不能为空")
    private String email;

    public Person() {

    }

    public Person(String id, String name, String sex, String email) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.email = email;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
View Code

JSR提供的校验注解:

  • @Null 被注释的元素必须为 null
  • @NotNull 被注释的元素必须不为 null
  • @AssertTrue 被注释的元素必须为 true
  • @AssertFalse 被注释的元素必须为 false
  • @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
  • @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
  • @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
  • @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
  • @Size(max=, min=) 被注释的元素的大小必须在指定的范围内
  • @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
  • @Past 被注释的元素必须是一个过去的日期
  • @Future 被注释的元素必须是一个将来的日期
  • @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式

Hibernate Validator提供的校验注解:

  • @NotBlank(message =) 验证字符串非null,且长度必须大于0
  • @Email 被注释的元素必须是电子邮箱地址
  • @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
  • @NotEmpty 被注释的字符串的必须非空
  • @Range(min=,max=,message=) 被注释的元素必须在合适的范围内

验证Controller的输入

验证请求体(RequestBody)

我们在需要验证的参数上加上了@Valid注解,如果验证失败,它将抛出MethodArgumentNotValidException。默认情况下,Spring会将此异常转换为HTTP Status 400(错误请求)。

 1 package com.test.valid.controller;
 2
 3 import com.test.valid.entity.Person;
 4 import org.springframework.http.ResponseEntity;
 5 import org.springframework.validation.annotation.Validated;
 6 import org.springframework.web.bind.annotation.*;
 7
 8 import javax.validation.Valid;
 9 import javax.validation.constraints.Max;
10
11 @Validated
12 @RestController
13 @RequestMapping("/valid")
14 public class PersonController {
15
16     @PostMapping("/person")
17     public ResponseEntity<Person> getPerson(@Valid Person person) {
18         return ResponseEntity.ok().body(person);
19     }
20
21     @GetMapping("/person/{id}")
22     public ResponseEntity<Integer> getPersonByID(@Valid @PathVariable("id") @Max(value = 5,message = "超过 id 的范围了") Integer id) {
23         return ResponseEntity.ok().body(id);
24     }
25 }

测试验证:

{
    "timestamp": "2019-10-25T03:05:15.018+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "Email.person.email",
                "Email.email",
                "Email.java.lang.String",
                "Email"
            ],
            "arguments": [
                {
                    "codes": [
                        "person.email",
                        "email"
                    ],
                    "arguments": null,
                    "defaultMessage": "email",
                    "code": "email"
                },
                [],
                {
                    "defaultMessage": ".*",
                    "codes": [
                        ".*"
                    ],
                    "arguments": null
                }
            ],
            "defaultMessage": "email格式不正确",
            "objectName": "person",
            "field": "email",
            "rejectedValue": "123.com",
            "bindingFailure": false,
            "code": "Email"
        }
    ],
    "message": "Validation failed for object='person'. Error count: 1",
    "path": "/valid/person"
}
View Code

验证请求参数(Path Variables 和 Request Parameters)

controller:

一定一定不要忘记在类上加上 Validated 注解了,这个参数可以告诉 Spring 去校验方法参数。

如上面的代码。

验证 Service 中的方法

我们还可以验证任何Spring组件的输入,而不是验证控制器级别的输入,我们可以使用@Validated@Valid注释的组合来实现这一需求。

一定一定不要忘记在类上加上 Validated 注解了,这个参数可以告诉 Spring 去校验方法参数。


自定义 Validator

package com.test.valid;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = RegionValidator.class)
@Documented
public @interface Region {
    String message() default "Region 值不在可选范围内";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}
package com.test.valid;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;

public class RegionValidator implements ConstraintValidator<Region, String> {
   public void initialize(Region constraint) {
   }

   public boolean isValid(String obj, ConstraintValidatorContext context) {
      HashSet<Object> regions = new HashSet<>();
      regions.add("China");
      regions.add("China-Taiwan");
      regions.add("China-HongKong");
      return regions.contains(obj);
   }
}
@Region
private String region;
{
    "timestamp": "2019-10-25T03:20:28.459+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "Region.person.region",
                "Region.region",
                "Region.java.lang.String",
                "Region"
            ],
            "arguments": [
                {
                    "codes": [
                        "person.region",
                        "region"
                    ],
                    "arguments": null,
                    "defaultMessage": "region",
                    "code": "region"
                }
            ],
            "defaultMessage": "Region 值不在可选范围内",
            "objectName": "person",
            "field": "region",
            "rejectedValue": "China-shanghai",
            "bindingFailure": false,
            "code": "Region"
        }
    ],
    "message": "Validation failed for object='person'. Error count: 1",
    "path": "/valid/person"
}
12-27 20:56