validation参数检验 - 注解介绍

news/2024/7/24 10:57:14 标签: validation

文章目录

  • Maven 依赖
  • 注解介绍
    • javax.validation 中的注解(22个)
      • Null、NotNull
      • NotBlank
      • NotEmpty
      • Size
      • AssertFalse、AssertTrue
      • DecimalMax、DecimalMin、Max、Min
      • Digits
      • Positive、PositiveOrZero、Negative、NegativeOrZero
      • Future、FutureOrPresent、Past、PastOrPresent
      • Email、Pattern
    • hibernate.validator 中的注解
      • DurationMax、DurationMax
      • Length
      • Range
      • UniqueElements
  • 使用技巧
    • 自定义 message、读取配置文件
  • 问题
    • 为什么同是基本类型,boolean、int 对 null 的处理不同?

Maven 依赖

项目为 springboot 项目,主要依赖有以下三个,其中spring-boot-starter-validation包含了 jakarta.validation-api(包含了 javax.validation)、hibernate-validator

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-validation</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>

	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<optional>true</optional>
	</dependency>

注解介绍

validation_22_21">javax.validation 中的注解(22个)

javax.<a class=validation 中的注解" />

注解验证的数据类型说明
Null所有类型验证元素值必须为 null
NotNull所有类型验证元素值必须不为 null
NotBlankCharSequence验证元素值不能为 null,并且至少包含一个非空白字符。
NotEmptyCharSequence、Collection、Map、Array验证元素值不能为 null,且不能为空
Size(min = min, max = max)同 NotEmpty验证元素的 size 必须在 min 和 max 之间(包含边界),认为 null 是有效的
AssertFalseboolean、Boolean验证元素值必须为 false,认为 null 是有效的
AssertTrue同 AssertFalse验证元素值必须为 true,认为 null 是有效的
DecimalMax(value=, inclusive=)BigDecimal、BigInteger、CharSequence,byte、 short、int、long 及其包装类型,由于舍入错误,不支持double和float验证元素值必须小于等于指定的 value 值,认为 null 是有效的
DecimalMin同 DecimalMax验证元素值必须大于等于指定的 value 值,认为 null 是有效的
Max同 DecimalMax,不支持CharSequence验证元素值必须小于等于指定的 value 值,认为 null 是有效的
Min同 DecimalMax,不支持CharSequence验证元素值必须大于等于指定的 value 值,认为 null 是有效的
Digits(integer =, fraction =)同 DecimalMax验证元素整数位数的上限 integer 与小数位数的上限 fraction,认为 null 是有效的
PositiveBigDecimal、BigInteger,byte、short、int、long、float、double 及其包装类型验证元素必须为正数,认为 null 是有效的
PositiveOrZero同Positive验证元素必须为正数或 0,认为 null 是有效的
Negative同Positive验证元素必须为负数,认为 null 是有效的
NegativeOrZero同Positive验证元素必须为负数或 0,认为 null 是有效的
FutureDate、Calendar、Instant、LocalDate、LocalDateTime、LocalTime、MonthDay、OffsetDateTime、OffsetTime、Year、YearMonth、ZonedDateTime、HijrahDate、JapaneseDate、MinguoDate、ThaiBuddhistDate验证元素值必须是一个将来的时间,认为 null 是有效的
FutureOrPresent同 Future验证元素值必须是当前时间或一个将来的时间,认为 null 是有效的
Past同 Future验证元素值必须是一个过去的时间,认为 null 是有效的
PastOrPresent同 Future验证元素值必须是当前时间或一个过去的时间,认为 null 是有效的
Email(regexp = 正则表达式,flag = 标志的模式)CharSequence验证注解的元素值是Email,可以通过 regexp 和 flag 指定自定义的 email 格式,认为 null 是有效的
Pattern同 Email验证元素值符合正则表达式,认为 null 是有效的

Null、NotNull

验证元素值必须为 null (Null),必须不为 null(NotNull),支持所有类型。

    @GetMapping("null")
    public String isNull(@Null Integer b) {
        return "pass: " + b;
    }

    @GetMapping("notNull")
    public String notNull(@NotNull Integer b) {
        return "pass: " + b;
    }

Null_NotNull

NotBlank

验证元素值不能为null,并且至少包含一个非空白字符。支持的类型:CharSequence

    @GetMapping("notBlank")
    public String notBlank(@NotBlank String b) {
        return "pass: " + b;
    }

notBlank

NotEmpty

验证元素值不能为null,且不能为空。支持的类型:

  • CharSequence (length of character sequence is evaluated)
  • Collection (collection size is evaluated)
  • Map (map size is evaluated)
  • Array (array length is evaluated)
    @GetMapping("notEmpty")
    public String notEmpty(@NotEmpty @RequestParam(name = "list", required = false) ArrayList<String> list) {
        return "pass: " + list;
    }

notEmpty

Size

验证元素的size必须在 min 和 max 之间(包含边界),认为 null 是有效的。支持的类型:

  • CharSequence (length of character sequence is evaluated)
  • Collection (collection size is evaluated)
  • Map (map size is evaluated)
  • Array (array length is evaluated)

Size
min()
size 的最小值,默认为 0

max()
size 的最大值,默认为 Integer.MAX_VALUE

    @GetMapping("size")
    public String size(@Size(min = 2, max = 3) @RequestParam(name = "list", required = false) ArrayList<String> list ) {
        return "pass: " + list;
    }

size

AssertFalse、AssertTrue

验证元素值必须为false/true,认为 null 是有效的(见测试结果),支持booleanBoolean

    @GetMapping("wrapperAssertFalse")
    public String wrapperAssertFalse(@AssertFalse Boolean b) {
        return "pass: " + b;
    }

    @GetMapping("wrapperAssertTrue")
    public String wrapperAssertTrue(@AssertTrue Boolean b) {
        return "pass: " + b;
    }

    @GetMapping("primitiveAssertFalse")
    public String primitiveAssertFalse(@AssertFalse boolean b) {
        return "pass: " + b;
    }

    @GetMapping("primitiveAssertTrue")
    public String primitiveAssertTrue(@AssertTrue boolean b) {
        return "pass: " + b;
    }

测试结果

primitiveAssertTrue

wrapperAssertTrue

primitiveAssertFalse

wrapperAssertFalse

注解数据类型truefalsenull
@AssertTrue基本类型××
@AssertTrue包装类型×
@AssertFalse基本类型×
@AssertFalse包装类型×

关于 null 的特除处理
  在AssertTrueAssertFalse的 javadoc 中都有一句 null elements are considered valid,意思就是 null 被认为是有效的。那为什么 AssertTrue 对基本类型 boolean 会验证失败呢?我觉得是因为基本类型的默认值导致的,当前端传值为 null 时,Boolean会使用直接使用 null,但是基本类型不能为 null,所以boolean使用的是默认值 false,false != true,所以验证失败。

DecimalMax、DecimalMin、Max、Min

验证元素值必须小于等于 / 大于等于指定的 value 值,认为 null 是有效的。

  • BigDecimal
  • BigInteger
  • CharSequence,Max、Min 不支持
  • byte、short、int、long 及其包装类型
  • 由于舍入错误,不支持double和float

Max

DecimalMax
value() 方法
指定的最大、最小值

inclusive() 方法
验证时是否可以包含边界值(value()方法指定的值),默认为 true
Max、Min 不支持。

    @GetMapping("decimalMinInteger")
    public String decimalMinInteger(@DecimalMin(value = "10") Integer b) {
        return "pass: " + b;
    }

    @GetMapping("decimalMinInt")
    public String decimalMinInt(@DecimalMin(value = "10") int b) {
        return "pass: " + b;
    }
	
    @GetMapping("decimalMinIntegerExclusive")
    public String decimalMinIntegerExclusive(@DecimalMin(value = "10", inclusive = false) Integer b) {
        return "pass: " + b;
    }

decimalMinInteger
上图中使用的是包装类型 Integer, 有两个特殊情况:

  1. 当无法将字符串转换为对应数值类型时,会抛出异常,但此异常并不是验证失败,因为还没有走到验证那一步就报错了
  2. 当值为 null时,通过了验证

decimalMinInt
上图中使用的是基本类型 int,与图 decimalMinInteger 相比, 可以看出与 Integer 的区别,在于对 null 的处理,int 是直接抛出了异常,而 Integer 是通过了验证

decimalMinIntegerExclusive
上图中 inclusive = false,与图 decimalMinInteger 的第二个小图相比,图 decimalMinIntegerExclusive 没有通过验证。

Digits

验证元素整数位数的上限 integer 小数位数的上限 fraction,认为 null 是有效的。支持 BigDecimal、BigInteger、CharSequence,byte、 short、int、long 及其包装类型,由于舍入错误,不支持double和float

enter description here
integer()
整数位数的最大值

fraction()
小数位数的最大值

    @GetMapping("digits")
    public String digits(@Digits(integer = 2, fraction = 1) BigDecimal b) {
        return "pass: " + b;
    }

digits

Positive、PositiveOrZero、Negative、NegativeOrZero

验证元素必须为正数(Positive)、正数或 0 (PositiveOrZero)、负数(Negative)、负数或 0 (NegativeOrZero),认为 null 是有效的 ,支持的类型:

  • BigDecimal
  • BigInteger
  • byte、short、int、long、float、double 及其包装类型
    @GetMapping("positive")
    public String positive(@Positive Integer t) {
        return "pass: " + t;
    }

    @GetMapping("positiveOrZero")
    public String positiveOrZero(@PositiveOrZero Integer t) {
        return "pass: " + t;
    }

positive

positiveOrZero

Future、FutureOrPresent、Past、PastOrPresent

验证元素值必须是一个将来的时间(Future)、将来的时间或当前时间(FutureOrPresent)、过去的时间(Past)、过去的时间或当前时间(PastOrPresent),认为 null 是有效的 。此处 present 的概念是相对于使用约束的类型定义的。例如,如果约束条件是一年,那么当前时间就意味着整个当年。支持的类型:

  • java.util.Date
  • java.util.Calendar
  • java.time.Instant
  • java.time.LocalDate
  • java.time.LocalDateTime
  • java.time.LocalTime
  • java.time.MonthDay
  • java.time.OffsetDateTime
  • java.time.OffsetTime
  • java.time.Year
  • java.time.YearMonth
  • java.time.ZonedDateTime
  • java.time.chrono.HijrahDate
  • java.time.chrono.JapaneseDate
  • java.time.chrono.MinguoDate
  • java.time.chrono.ThaiBuddhistDate
    @GetMapping("future")
   public String future(@Future LocalDate t) {
       return "pass: " + t;
   }

   @GetMapping("futureOrPresent")
   public String futureOrPresent(@FutureOrPresent LocalDate t) {
       return "pass: " + t;
   }

测试时间为 2020-04-30

future

futureOrPresent
测试时间为 2020-04-30,可以看到图 future、图 futureOrPresent 的第二张小图,一个验证失败,一个验证通过。

Email、Pattern

验证注解的元素值是Email(Email)、符合正则表达式(Pattern),可以通过 regexp 和 flag 指定自定义的 email、正则格式,认为 null 是有效的 ,支持的类型:CharSequence。

Email
regexp()
正则表达式,Email 默认为 .* 任意字符,Pattern无默认值。
flags()
指定正则的匹配模式,不会用(手动狗头)。

    @GetMapping("email")
    public String email(@Email(regexp = ".+@.+") String email) {
        return "pass: " + email;
    }

email

hibernate.validator 中的注解

hibernate.validator

注解数据类型说明
CreditCardNumber(ignoreNonDigitCharacters=)CharSequence检查字符序列是否通过Luhn校验和测试。请注意,此验证旨在检查用户错误,而不是信用卡有效性!ignoreNonDigitCharacters允许忽略非数字字符,默认值为false。
Currencyjavax.money.MonetaryAmount 子类型检查注解的货币单位 javax.money.MonetaryAmount 是否为指定货币单位的一部分
DurationMaxDuration注解的 Duration 必须小于等于 DurationMax 指定的值,默认包含边界
DurationMinDuration注解的 Duration 必须大于等于 DurationMax 指定的值,默认包含边界
EANCharSequence是否是有效的国际商品编号,null 是有效的
ISBNCharSequence是否是有效的国际标准书号,null 是有效的
LengthCharSequence长度必须在 min 和 max之间,包含边界
RangeBigDecimal、BigInteger、CharSequence,byte、 short、int、long 及其包装类型数字大小必须在 min 和 max 之间,包含边界
UniqueElementsCollection检测集合中的值都是唯一的(集合不能包含相同的元素,null 是有效的)
UrlCharSequence根据RFC2396检查字符序列是否为有效URL
LuhnCheckCharSequence检查字符序列中的数字是否通过Luhn校验和算法
Mod10CheckCharSequence检查字符序列中的数字是否通过通用mod 10校验和算法。
Mod11CheckCharSequence检查字符序列中的数字是否通过通用mod 11校验和算法。
ScriptAssert任意类型
CodePointLengthCharSequence
CNPJCharSequence验证巴西公司纳税人注册编号
CPFCharSequence验证巴西个人纳税人注册号
TituloEleitoralCharSequence验证巴西选民身份证号
NIPCharSequence验证波兰增值税标识号
PESELCharSequence验证波兰的国家标识号
REGONCharSequence验证波兰纳税人识别码

DurationMax、DurationMax

注解的 Duration 必须小于等于(DurationMax)、大于等于(DurationMin) 指定的值,默认包含边界。支持的类型 java.time.Duration

DurationMax

@RestController
public class HibernateController {

    private final HibernateService hibernateService;

    public HibernateController(HibernateService hibernateService) {
        this.hibernateService = hibernateService;
    }

    @GetMapping("durationMax")
    public String durationMax(long minutes) {
        Duration duration = Duration.ofMinutes(minutes);
        return "pass: " + hibernateService.durationMax(duration);
    }
}

@Validated
@Service
public class HibernateService {

    public long durationMax(@DurationMax(minutes = 2) Duration d) {
        return d.toMinutes();
    }
}

durationMax

Length

字符长度必须在 min 和 max之间,包含边界。支持的类型:CharSequence

Length

    @GetMapping("length")
    public String length(@Length(min = 2, max = 3) StringBuilder s) {
        return "pass: " + s.toString();
    }

length

Range

数字大小必须在 min 和 max 之间,包含边界。支持的类型:

  • BigDecimal
  • BigInteger
  • CharSequence
  • byte、 short、int、long 及其包装类型

Range

    @GetMapping("range")
    public String range(@Range(min = 3, max = 10) Integer s) {
        return "pass: " + s.toString();
    }

range

UniqueElements

检测集合中的值都是唯一的(集合不能包含相同的元素),null 是有效的。支持的类型:Collection

    @GetMapping("uniqueElements")
    public String uniqueElements(@UniqueElements @RequestParam("list") List<String> list) {
        return "pass: " + list;
    }

uniqueElements

使用技巧

自定义 message、读取配置文件

问题

为什么同是基本类型,boolean、int 对 null 的处理不同?

如下代码可以看出,在值为 null 时,spring 对 Boolean 进行的特殊处理,直接返回了 false,而对其他基本类型抛出了异常。

	// org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver
	
	@Nullable
	private Object handleNullValue(String name, @Nullable Object value, Class<?> paramType) {
		if (value == null) {
			if (Boolean.TYPE.equals(paramType)) {
				return Boolean.FALSE;
			}
			else if (paramType.isPrimitive()) {
				throw new IllegalStateException("Optional " + paramType.getSimpleName() + " parameter '" + name +
						"' is present but cannot be translated into a null value due to being declared as a " +
						"primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
			}
		}
		return value;
	}

http://www.niftyadmin.cn/n/1688149.html

相关文章

validation参数检验 - 如何使用

文章目录Maven 依赖Spring MVC Controller 的输入验证 Path Variables、 Request Parameters、Request Header验证 RequestBody非 Controller 组件的方法自定义 Validator自定义一个验证需要的注解自定义 Constraint 注解注意点自定义一个 Validator定义一个 POJO 进行验证以纯…

Mysql DELETE语法

文章目录Mysql DELETE语法多表 DELETE语法DELETE LIMIT参考Mysql DELETE语法 多表 DELETE语法 DELETE [LOW_PRIORITY] [QUICK] [IGNORE]tbl_name[.*] [, tbl_name[.*] ...]FROM table_references[WHERE where_definition]DELETE [LOW_PRIORITY] [QUICK] [IGNORE]FROM tbl_na…

ArrayList 源码详解 (JDK8)

文章目录类图声明RandomAccess 接口Cloneable 接口Serializable 接口List 接口AbstractList 抽象类属性DEFAULT_CAPACITYEMPTY_ELEMENTDATADEFAULTCAPACITY_EMPTY_ELEMENTDATAelementDatasize构造方法方法trimToSize()容量计算、扩容size()、isEmpty() 、 contains(Object o) 、…

实例变量、构造代码块、构造方法的执行顺序

实例变量、构造代码块、构造方法的执行顺序单个类的执行顺序父子类的执行顺序本文内容不涉及类加载、静态变量、静态代码块的知识。单个类的执行顺序 测试代码 public class InitTestFather {private P p1 new P("父 - 变量1");{System.out.println("父 - 代…

类、字段、代码块、构造方法的执行顺序

类、字段、代码块、构造方法的执行顺序测试代码执行结果参考测试代码 有两个类 Father、Son&#xff0c;其中有实例变量、类变量、构造代码块、静态代码块、构造方法 class Father {public Integer test 100;public int i test();private static int j method();static {S…

Elasticsearch 修改IK分词器源码实现基于MySql的词库热更新

Elasticsearch 修改IK分词器源码实现基于MySql的词库热更新官方提供的热更新方式自己实现基于MySQL的词库热更新数据库JDBC 配置pomsrc/main/assemblies/plugin.xmlsrc/main/resources/plugin-security.policy修改 DictionaryMySQL 热更新的实现类 DatabaseMonitor打包测试参考…

robotac属于a类还是b类_为什么知产顾问推荐你注册35类商标?

35商标被称作是万能商标&#xff0c;好像所有行业都能够跟它扯上关系&#xff0c;然而&#xff0c;事情真的是酱紫吗&#xff1f;今天&#xff0c;小知就来讲讲哪些行业需要注册第35类商标。 广告、电商、服务行业全都逃不开第35类商标属于服务商标&#xff0c;包括由个人或组织…

can通道采样频率_CAN总线哪个节点在通讯?发送了什么信息?(一)

作者&#xff1a;Steve Smith最近关于CAN 总线哪个模块在通讯以及传输了什么信息的讨论非常多&#xff0c;因此我想和大家分享用PicoScope 6 Automotive软件处理这个问题的一些方法。众所周知&#xff0c;要想将CAN总线信号正确有效地译码并不容易。虹科Pico汽车示波器4425A的优…