JavaBean基于注解实现校验

前言

上一文我通过传递不合法参数触发异常,进行了统一拦截,那么这篇文章主要介绍JSR303,Hibernate Validator详细讲解及如何优雅的对参数进行校验,使用和技巧。

正文

JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了,笔者还是基于springboot(1.5.8.RELEASE)。

直接上干货,带你们一起实验是使用org.hibernate.validator.constraints包下的注解。

首先定义一个实体类,属性分别用了校验注解,分别进行触发。

import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;

import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.List;

/**
 * @author yanlin
 * @version v1.3
 * @date 2018-10-18 下午3:16
 * @since v8.0
 **/
public class Student implements Serializable {
    private static final long serialVersionUID = 7003907324788760110L;
    @NotBlank(message = "姓名不能为空")
    private String name;
    @Min(value = 2, message = "不能小于2")
    @Max(value = 5, message = "不能大于5")
    private Integer age;
    @NotEmpty(message = "集合不能为空")
    private List stringList;
    @AssertTrue(message = "bool必须为true")
    private Boolean bool;
    @NotNull(message = "对象不能为空")
    private Student student;
    //省略getter setter

这是一个controller,

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.hibernate.validator.constraints.NotBlank;
import javax.validation.Valid;


/**
 * @author yanlin
 * @version v1.2
 * @date 2018-08-16 下午2:21
 * @since v8.0
 **/
@SpringBootApplication
@EnableDiscoveryClient
@RestController
//@Validated
public class EurekaClientApp {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApp.class, args);
    }


    @RequestMapping(value = "/ClientService/body", method = RequestMethod.POST)
    public void testBodyE(@Valid @RequestBody Student student) {
        System.out.println(student.toString());

    }

我利用postman发送五次请求,每一次我都更改了部分参数以便触发校验注解,下面是我操作的过程

JavaBean基于注解实现校验_第1张图片

 

JavaBean基于注解实现校验_第2张图片

JavaBean基于注解实现校验_第3张图片

 JavaBean基于注解实现校验_第4张图片

 JavaBean基于注解实现校验_第5张图片

从上面的操作过程可以发现,其实不同类型的注解校验是有顺序的,并不是实体类里属性自上而下的顺序,最后一张图可以发现,我名字是空,但是断言bool是true时,他优先触发了断言,所以小伙伴们在使用的时候要主意哦,同类型的注解是有顺序的,切记,不同类型的不是越靠前越先触发哦! 

下面介绍一下直接校验方法参数体中的基本数据类型,这是笔者在做这个实验前由于好奇心无意发现的,先贴两个注解的代码,你们会发现我上面写的代码,如果是JavaBean校验,我都会在参数前加@Valid,当然加@Validated效果也是一样的(这两个注解往下看我会有介绍),但是他俩最重要的区别是@Validated可以注释在类上,这个我当时很好奇,所以我实验了一下,结论是:当@Validated使用在类上时,会触发当前类所有写在方法参数上的参数校验注解的生效。

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {

	/**
	 * Specify one or more validation groups to apply to the validation step
	 * kicked off by this annotation.
	 * 

JSR-303 defines validation groups as custom annotations which an application declares * for the sole purpose of using them as type-safe group arguments, as implemented in * {@link org.springframework.validation.beanvalidation.SpringValidatorAdapter}. *

Other {@link org.springframework.validation.SmartValidator} implementations may * support class arguments in other ways as well. */ Class[] value() default {}; }

@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface Valid {
}

 例如:test方法的name参数前加参数校验注解(@NotBlank),但是类上必须加@Validated,否则你在基本数据类型前加的参数校验注解是不生效的,这点笔者已经实验了,大家直接当结论就可以。

/**
 * @author yanlin
 * @version v1.2
 * @date 2018-08-16 下午2:21
 * @since v8.0
 **/
@SpringBootApplication
@EnableDiscoveryClient
@Validated
public class EurekaClientApp {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApp.class, args);
    }


    @RequestMapping(value = "/ClientService/body", method = RequestMethod.POST)
    public void testBodyE(@Valid @RequestBody Student student) {
        System.out.println(student.toString());

    }

    @GetMapping("/ClientService/name")
    public String test(@NotBlank(message = "name 不能为空") @RequestParam("name") String name) {
        if (name.equals("1")) {
            throw new ParameterServiceException("这里填写错误代码,规范应是一个枚举", "描述当前错误原因");
        }
        return name;
    }

下面我总结一下@Validated&@Valid区别

1.该注解表示对该对象进行验证需要在实体类内配合其他注解使用

2.使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同

3.@Validated是@Valid 的一次封装,是Spring提供的校验机制使用。@Valid不提供分组功能

4.@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

5.@Validated不能用在成员属性(字段)上,但是@Valid能加在成员属性(字段)上,而且@Valid类注解上也说明了它支持嵌套验证功能

6.如果一个bean中包含第二个bean,这时要检验第二个bean中某个字段,即嵌套校验,必须要在第一个bean对象中使用@Valid标注到表示第二个bean对象的字段上,然后再第二个bean对象里面的字段上加上校验类型.

7.@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

8.@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上

下面是我总结的所有参数校验注解的使用规则方法

空检查

@Null 验证对象是否为null

@NotNull 验证对象是否不为null, 无法查检长度为0的字符串

@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.

@NotEmpty 检查约束元素是否为NULL或者是EMPTY.

Booelan检查

@AssertTrue 验证 Boolean 对象是否为 true

@AssertFalse 验证 Boolean 对象是否为 false

长度检查

@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内

@Length(min=, max=) Validates that the annotated string is between min and max included.

日期检查

@Past 验证 Date 和 Calendar 对象是否在当前时间之前

@Future 验证 Date 和 Calendar 对象是否在当前时间之后

@Pattern 验证 String 对象是否符合正则表达式的规则

数值检查

建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null

@Min 验证 Number 和 String 对象是否大等于指定的值

@Max 验证 Number 和 String 对象是否小等于指定的值

@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度

@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度

@Digits 验证 Number 和 String 的构成是否合法

@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。 @Range(min=, max=) Checks whether the annotated value lies between (inclusive) the specified minimum and maximum. @Range(min=10000,max=50000,message="range.bean.wage") private BigDecimal wage;

@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)

@CreditCardNumber信用卡验证

@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。

@ScriptAssert(lang= ,script=, alias=)

@URL(protocol=,host=, port=,regexp=, flags=)

本篇依赖了我上篇文章的异常拦截处理,类图如下

JavaBean基于注解实现校验_第6张图片

类的代码在上篇文章已经贴出来了,大家自行拷贝。

注:对本文有异议或不明白的地方微信探讨,wx:15524579896

 

 

 

你可能感兴趣的:(springBoot,java)