前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaBean基于注解实现校验

JavaBean基于注解实现校验

作者头像
胖虎
发布2019-06-26 15:55:50
1K0
发布2019-06-26 15:55:50
举报
文章被收录于专栏:晏霖晏霖

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

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

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

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

代码语言:javascript
复制
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<String> stringList;
    @AssertTrue(message = "bool必须为true")
    private Boolean bool;
    @NotNull(message = "对象不能为空")
    private Student student;
    //省略getter setter

这是一个用来测试的 controller,

代码语言:javascript
复制
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发送五次请求,每一次我都更改了部分参数以便触发校验注解,下面是我操作的过程

1

2

3

4

5

图片

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

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

代码语言:javascript
复制
@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.
     * <p>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}.
     * <p>Other {@link org.springframework.validation.SmartValidator} implementations may
     * support class arguments in other ways as well.
     */
    Class<?>[] value() default {};

}
-----------------------------
代码语言:javascript
复制
@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface Valid {
}

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

代码语言:javascript
复制
/**
 * @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=)

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

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-01-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 晏霖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档