Spring的@Validation和javax包下的@Valid区别以及自定义校验注解
作者:慕色丶 发布时间:2021-06-20 04:06:35
1.后台参数校验
Spring Validation验证框架对参数的验证机制提供了@Validated(Spring JSR-303规范,是标准JSR-303的一个变种),javax提供了@Valid(标准JSR-303规范),配合BindingResult可以直接提供参数验证结果
spring提供的验证:org.springframework.validation.annotation.Validated;
javax提供的验证:javax.validation.Valid;
在检验Controller的入参是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同:
1.1 分组
@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制,这个网上也有资料,不详述。
@Valid:作为标准JSR-303规范,还没有分组的功能。
1.2 注解地方
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。
1.3 嵌套验证
@Validated:用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
示例代码:
#使用@Validated的分组功能,需要提供接口,原因是
@Target({ElementType.TYPE, ElementType.METHOD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
Class<?>[] value() default {}; #需要定义类型做区分,所以提供个接口做分组区分
}
示例分类接口:
public interface CreateGroup {
}
#在需要验证的字段上添加分组即可
示例代码:
public class WebOrderQo {
/**
* 用户ID
*/
@ApiModelProperty("用户ID")
@NotNull(message = "用户ID不能为空", groups = {UpdateGroup.class, CreateGroup.class, QueryGroup.class})
private Long uid;
}
#在Controller里面的方法上加@Validated注解,启动分组需要在@Validated(CreateGroup.class)填上对应的分组类型,默认没有指定分组的校验注解@NotNull,在分组校验情况@Validated({CreateGroup.class})下不生效,只会在@Validated生效;
示例代码:
@RestController
public class ItemController {
@RequestMapping("/item/add")
public void addItem(@Validated Item item, BindingResult bindingResult) {
doSomething();
}
}
@Valid:用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证
示例代码:
public class Item {
@NotNull(message = "id不能为空")
@Min(value = 1, message = "id必须为正整数")
@ListValue(vals = {0,1}) //自定义注解
private Long id;
@Valid // 嵌套验证必须用@Valid
@NotNull(message = "props不能为空")
@Size(min = 1, message = "props至少要有一个自定义属性") //嵌套验证
private List<Prop> props;
}
2.自定义参数验证注解
当验证框架提供的验证注解无法满足业务需求的时候,可以自定义验证注解实现我们的业务需求
1)、编写一个自定义的校验注解
@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {
String message() default "{pers.store.market.common.valid.ListValue.message}"; //可以在配置文件中配置自定的消息提醒
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int[] vals() default { };
}
注意:可以在resources下面创建ValidationMessages.properties文件,读取自定义的提示消息
pers.store.market.common.valid.ListValue.message=参数提交错误
2)、编写一个自定义的校验器ConstraintValidator
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {
private Set<Integer> set = new HashSet<>();
//初始化方法
@Override
public void initialize(ListValue constraintAnnotation) {
int[] vals = constraintAnnotation.vals();
for (int val : vals) {
set.add(val);
}
}
/**
*
* @param value 需要校验的值
* @param context
* @return
*/
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
return set.contains(value);
}
}
3)、关联自定义的校验器和自定义的校验注解
@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class【可以指定多个不同的校验器适配不同类型的校验】 })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {}
来源:https://blog.csdn.net/qq_42974140/article/details/113183565


猜你喜欢
- 本文实例为大家分享了Java实现简单酒店管理系统的具体代码,供大家参考,具体内容如下为某个酒店编写程序:酒店管理系统,模拟订房、退房和打印所
- 你是否遇到过,出现异常的时候也需要给一个默认值,让程序可以继续运行下去?一般的做法就是 一个达到try catch,然后在finally里面
- 本文实例讲述了Java Spring开发环境搭建及简单入门示例。分享给大家供大家参考,具体如下:前言虽然之前用过Spring,但是今天试着去
- 为什么需要在应用程序中增加渠道信息?Android应用的发布需要面对各种各样的市场,我们称之为渠道。有的时候,我们需要知道应用是从哪个渠道下
- 一、问题重现1.配置文件spring: #DataSource数据源 datasource: &nbs
- 本文实例讲述了Android基于ViewPager+Fragment实现左右滑屏效果的方法。分享给大家供大家参考,具体如下:1.xml布局模
- 什么是mybatisMyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数
- Android的PopupWindow是个很有用的widget,利用它可以实现悬浮窗体的效果,比如实现一个悬浮的菜单,最常见的应用就是在视频
- 布隆过滤器原理很简单:就是把一个字符串哈希成一个整数key,然后选取一个很长的比特序列,开始都是0,在key把此位置的0变为1;下次进来一个
- 本文实例为大家分享了Android获取设备传感器的具体代码,供大家参考,具体内容如下结果示例:xml代码:<?xml version=
- 1、相差秒public double DiffSeconds(DateTime startTime,DateTime endTime){ &
- 自定义View,1. 自定义一个Runnable线程TouchEventCountThread , 用来统计500ms内的点击次
- 这篇文章主要介绍了spring boot 2整合swagger-ui过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的
- CSV(Comma Separated Values)文件是一种纯文本文件,包含用逗号分隔的数据,常用于将数据从一个应用程序导入或导出到另一
- 本文实例讲述了C#使用StopWatch获取程序毫秒级执行时间的方法。分享给大家供大家参考。具体分析如下:这个比时间通过DateTime在程
- 前言一个简单的单机小游戏:flypybird ,用来巩固java基础。涉及主要知识点:JFrame 、 JPanel 、 继承、 键盘/鼠标
- 异步接口的声明我们已经了解到,如果一个方法是异步的,那么这个方法的返回值类型是Task<T>,那么接口中该如何规定异步方法呢?一
- 使用@RequestParam注解获取参数创建Hello控制器类package com.controller;import org.spri
- 前言相信每位Android开发者都用过Toast,都知道是弹出消息的。类似于js里面的alert,C#里面的MesageBox。当然andr
- 1.元组(Tuple)元组(Tuple)在4.0 的时候就有了,但元组也有些缺点,如: 1)Tuple 会影响代码的