Java Bean Validation API

API

默认包:javax.validation

Validator

基础接口:javax.validation.Validator

public interface Validator {/** 验证 object*/<T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);/** 验证属性*/<T> Set<ConstraintViolation<T>> validateProperty(T object,													 String propertyName, Class<?>... groups);/** 验证属性值为指定value*/<T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups);/** 获取指定类的BeanDescriptor*/BeanDescriptor getConstraintsForClass(Class<?> clazz);<T> T unwrap(Class<T> type);ExecutableValidator forExecutables();
}

用于验证的方法

	<T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);<T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups);<T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups);

用于验证方法、构造函数的方法

	ExecutableValidator forExecutables();

返回的是 javax.validation.executable.ExecutableValidator

public interface ExecutableValidator {/** 校验方法的所有参数*/<T> Set<ConstraintViolation<T>> validateParameters(T object,  Method method, Object[] parameterValues,  Class<?>... groups);/** 校验方法的返回值*/<T> Set<ConstraintViolation<T>> validateReturnValue(T object, Method method, Object returnValue, Class<?>... groups);/** 校验构造函数的参数*/<T> Set<ConstraintViolation<T>> validateConstructorParameters(Constructor<? extends T> constructor,  Object[] parameterValues, Class<?>... groups);/** 校验构造函数的返回值*/<T> Set<ConstraintViolation<T>> validateConstructorReturnValue(Constructor<? extends T> constructor,  T createdObject,  Class<?>... groups);
}
//orderService:Object  ,placeOrder:Method
executableValidator.validateParameters(orderService, placeOrder, new Object[] { null, item1, 1 }, Group);
@Interceptor
public class SampleMethodInterceptor {@Injectprivate Validator validator;@AroundInvokepublic Object invoke(MethodInvocation invocation) throws Throwable {// Avoid Validator invocation on FactoryBean.getObjectType/isSingletonif (isFactoryBeanMetadataMethod(invocation.getMethod())) {return invocation.proceed();}Class<?>[] groups = determineValidationGroups(invocation);// Standard Bean Validation 1.1 APIExecutableValidator execVal = this.validator.forExecutables();Method methodToValidate = invocation.getMethod();Set<ConstraintViolation<Object>> result;try {//校验参数result = execVal.validateParameters(invocation.getThis(), methodToValidate, invocation.getArguments(), groups);}catch (IllegalArgumentException ex) {// Probably a generic type mismatch between interface and impl as reported in SPR-12237 / HV-1011// Let's try to find the bridged method on the implementation class...methodToValidate = BridgeMethodResolver.findBridgedMethod(ClassUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()));result = execVal.validateParameters(invocation.getThis(), methodToValidate, invocation.getArguments(), groups);}if (!result.isEmpty()) {throw new ConstraintViolationException(result);}Object returnValue = invocation.proceed();//校验返回值result = execVal.validateReturnValue(invocation.getThis(), methodToValidate, returnValue, groups);if (!result.isEmpty()) {throw new ConstraintViolationException(result);}return returnValue;}
}

groups

group允许在验证过程中限制约束策略的验证。在验证的过程中,group会作为参数传入,仅属于指定Group的约束才会验证。如果不指定,则是Default Group。

当指定多个Group时,验证顺序是不受控制的。

ConstraintViolation

ConstraintViolation用于描述验证失败的信息。

public interface ConstraintViolation<T> {String getMessage();String getMessageTemplate();T getRootBean();Class<T> getRootBeanClass();Object getLeafBean();Object[] getExecutableParameters();Object getExecutableReturnValue();Path getPropertyPath();Object getInvalidValue();ConstraintDescriptor<?> getConstraintDescriptor();<U> U unwrap(Class<U> type);
}
  • getMessage:返回验证失败的本地化的message。
  • getMessageTemplate:返回非解析的message(一般是约束的message属性)。框架使用此值作为错误码key。
  • getRootBean:返回导致验证失败的根对象(例如传给Validator.validate()方法的object 参数)。对于方法验证,返回的是正在执行方法的对象,对于构造函数或Validator.validateValue(),返回null。
  • getRootBeanClassrootBean的Class。对于构造函数返回构造函数所在的类。
  • getLeafBean:返回以下对象:
    • bean约束,则返回约束应用的bean实例
    • 放置在属性上的属性约束或容器元素约束,则返回属性所属的bean实例。
    • 属性约束,调用Validator.validateValue(),返回ConstraintViolation ,则为null。
    • 方法参数、交叉参数、返回值 约束或者方法参数、返回值上放置的容器元素约束,则返回执行方法的对象。
    • 构造函数的参数、交叉参数约束 或者构造函数的参数上放置的容器元素约束,则为null。
    • 构造函数返回值约束,则为构造函数创建的对象实例。
  • getExecutableParameters:返回方法或构造函数调用传入的参数。
  • getExecutableReturnValue:返回方法或构造函数调用的返回值
  • getInvalidValue:返回传给 isValid()的值,即被验证的值。对于交叉验证参数,则返回调用传入的参数数组。
  • getConstraintDescriptor:约束的元数据
  • getPropertyPath:返回从根对象到验证失败的对象的路径。
  • unwrap

Path

public interface Path extends Iterable<Path.Node> {@OverrideString toString();/*** Represents an element of a navigation path.*/interface Node {String getName();boolean isInIterable();Integer getIndex();Object getKey();ElementKind getKind();<T extends Node> T as(Class<T> nodeType);@OverrideString toString();}interface MethodNode extends Node {List<Class<?>> getParameterTypes();}interface ConstructorNode extends Node {List<Class<?>> getParameterTypes();}interface ReturnValueNode extends Node {}interface ParameterNode extends Node {int getParameterIndex();}interface CrossParameterNode extends Node {}interface BeanNode extends Node {/** 获取bean的容器类型*/Class<?> getContainerClass();/** 获取 类型参数的index。*/Integer getTypeArgumentIndex();}/*** Node representing a property.** @since 1.1*/interface PropertyNode extends Node {Class<?> getContainerClass();Integer getTypeArgumentIndex();}/** 容器元素节点*/interface ContainerElementNode extends Node {Class<?> getContainerClass();Integer getTypeArgumentIndex();}
}

PathNode的可迭代集合。

Node

Node提供方法:

  • getName():返回Node的表示。
  • isInIterable():如果node表示一个包含在数组、多值容器(e.g. Iterable,Map)中的元素,则返回true。
  • getIndex():返回元素在容器中的索引,或者 null
  • getKey():返回元素在容器中的key,或者null。
  • getKind():返回node 的类型
  • as(Class<? extends Node>):node 转换为指定子类型。

Node的子类型:

  • BeanNode
  • PropertyNode
  • MethodNode
  • ConstructorNode
  • ParameterNode
  • CrossParameterNode
  • ReturnValueNode
  • ContainerElementNode
元素类型
public enum ElementKind {BEAN,PROPERTY,METHOD,CONSTRUCTOR,PARAMETER,CROSS_PARAMETER,RETURN_VALUE,CONTAINER_ELEMENT
}
Path生成规则
  • 实例类型考虑的是运行时类型(实例的真实类型)而不是静态类型(声明类型)。
  • 如果失败Node是根对象,则BeanNodename为null,KINDElementKind.BEAN
  • 当级联验证时:
    • 级联属性时,添加一个PropertyNode,name为字段名或属性名。Kind为ElementKind.PROPERTY
    • 级联容器时,有index时,添加一个getIndex() 返回不为null 的Node。
    • 级联容器时,有key时,添加一个getKey() 返回不为null 的Node。
    • 级联可枚举容器时,返回isInIterable() 为true 的Node
    • … …
  • 嵌套容器时
  • 属性级别约束,返回 PropertyNode,name为字段或者属性名
  • 类级别约束,返回 BeanNode,name为null。
  • 方法,构造函数约束,
  • 容器元素约束。

示例

Message插值(Message interpolation)

Message插值用于把约束的Message属性解析成可读的,完整的Message。

默认Message插值

每个符合Bean验证的实现都包含一个默认的消息插值,遵守规范的算法来解析消息。

消息插值的前提条件:

  • 每个约束必须通过message属性定义消息
  • 每个约束的message属性必须定义一个默认值。
  • 在声明约束的时候,可以覆盖message属性。
message格式

message是个字符串,支持参数。参数用{}${}定义。特定字符需要使用转义符。\\,\{,\},\$

Value must be between {min} and {max}
Must be greater than ${inclusive == true ? 'or equal to ' : ''}{value}
默认算法
  1. 从message属性中抽取参数,作为key从命名为ValidationMessages(通常使用属性文件/ValidationMessages.properties和它的本地变量)的ResourceBundle查询,使用定义的locale。如果查找到属性,则用属性值替换变量。递归应用此规则直到没有参数

  2. 参数作为key从Bean Validation provider 内置的ResourceBundle查询属性值,使用定义的locale。如果查找到属性,则用属性值替换变量。此规则不能递归应用

  3. 如果步骤2触发一个替换,则应用步骤1,否则执行步骤4

  4. 消息参数如果匹配了约束的属性,则用约束声明中指定的属性值替换。参数插值优先于消息表达式

    //参数
    javax.validation.constraints.Size.message=size must be between {min} and {max}
    //声明的属性
    @Size(min=1, max=50)
    private String title;
    
  5. 消息字符串中的消息表达式是用EL解析。

本地化
interpolate(String,Context, Locale)
//默认使用 Locale.getDefault()
消息表达式

消息表达式使用 ${} 包含起来,引用的变量需要在EL上下文中能够访问。以下属性和bean可以在EL上下文中访问:

  • 约束声明时指定的属性值。
  • 通过validatedValue 引用被验证的值。
  • 用过formatter 引用格式化器。${formatter.format('%1$.2f', validatedValue)}

如果在消息插值期间发生异常,例如由于无效表达式或引用未知属性,则消息表达式保持不变。

自定义消息插值

自定义消息插值,需要实现接口MessageInterpolator

public interface MessageInterpolator {String interpolate(String messageTemplate, Context context);String interpolate(String messageTemplate, Context context,  Locale locale);/*** Information related to the interpolation context.*/interface Context {//返回 导致验证失败的约束的metadataConstraintDescriptor<?> getConstraintDescriptor();//返回正在被验证的值Object getValidatedValue();<T> T unwrap(Class<T> type);}
}

messageTemplate:约束声明时的message属性值或者提供给ConstraintValidatorContext 方法的参数。

消息插值器实现必须是线程安全的。 此实例在ValidatorFactory构造时通过 Configuration.messageInterpolator(MessageInterpolator)设置,并且被由其构造的Validator共用。

触发方法验证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/588990.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为商城秒杀时加密验证 device_data 的算法研究

前言 之前华为商城放出 Mate60 手机时, 想给自己和家人抢购一两台&#xff0c;手动刷了好几天无果后&#xff0c;决定尝试编写程序&#xff0c;直接发送 POST 请求来抢。通过抓包和简单重放发送后&#xff0c;始终不成功。仔细研究&#xff0c;发现 Cookie 中有一个名为 devic…

启动gazebo harmonic

ros2 launch ros_gz_sim gz_sim.launch.py gz_version:8 如果不输入gz_version:8,默认就是6&#xff0c;启动的就是默认版本ign版本 左边那个是8&#xff0c;右边那个是6

基于EPICS modbus模块的单通道电压监测项目

先介绍在本项目中使用到的硬件&#xff1a; 1&#xff09;开发板&#xff1a;为香橙派Zero2&#xff0c;安装系统如下&#xff1a; Distributor ID: Ubuntu Description: Ubuntu 22.04.2 LTS Release: 22.04 Codename: jammy 2&#xff09; USB转485模块&…

深入探索MongoDB集群模式:从高可用复制集

MongoDB复制集概述 MongoDB复制集主要用于实现服务的高可用性&#xff0c;与Redis中的哨兵模式相似。它的核心作用是数据的备份和故障转移。 复制集的主要功能 数据复制&#xff1a;数据写入主节点&#xff08;Primary&#xff09;时&#xff0c;自动复制到一个或多个副本节…

react ant tree节点没有children也会显示展开框 节点有children却不显示展开框

1.背景 最近处理树状结构时遇到了一个诡异问题&#xff0c;后端返回了组织树&#xff0c;组织树里面可能有组织&#xff0c;也可能有用户&#xff0c;很奇怪的是所有用户都会显示展开图标&#xff0c;而组织有些会显示展开图标&#xff0c;有些不会显示 2.分析 一开始找到了用…

【Java 进阶篇】Linux 常用命令使用详解:玩转命令行的魔法世界

在计算机的世界里&#xff0c;Linux是一个强大而富有魅力的操作系统。对于很多小白用户来说&#xff0c;刚接触Linux时可能感觉有些陌生&#xff0c;尤其是在命令行界面下。然而&#xff0c;正是这个看似晦涩的命令行&#xff0c;才是Linux系统最为强大和灵活的地方。本文将围绕…

论文阅读——SG-Former

SG-Former: Self-guided Transformer with Evolving Token Reallocation 1. Introduction 方法的核心是利用显著性图&#xff0c;根据每个区域的显著性重新分配tokens。显著性图是通过混合规模的自我关注来估计的&#xff0c;并在训练过程中自我进化。直观地说&#xff0c;我们…

分布式【雪花算法】

雪花算法 背景&#xff1a;在分布式系统中&#xff0c;需要使用全局唯一ID&#xff0c;期待ID能够按照时间有序生成。 **原理&#xff1a;**雪花算法是 64 位 的二进制&#xff0c;一共包含了四部分&#xff1a; 1位是符号位&#xff0c;也就是最高位&#xff0c;始终是0&am…

【教学类-43-11】 20231231 3*3宫格数独提取单元格坐标数字的通用模板(做成2*2=4套、3*2=6套)

背景需求&#xff1a; 1、以前做单元格填充&#xff0c;都是制作N个分开的单元格 &#xff08;表格8&#xff09; 2、这次做五宫格数独的Word模板&#xff0c;我图方便&#xff0c;就只用了一个大表格&#xff0c;第六行第六列隐藏框线&#xff0c;看上去就是分开的&#xff…

剑指offer题解合集——Week2day6

文章目录 剑指offerWeek2周六&#xff1a;表示数值的字符串AC代码思路&#xff1a; 周六&#xff1a;调整数组顺序使奇数位于偶数前面AC代码思路&#xff1a; 剑指offerWeek2 周六&#xff1a;表示数值的字符串 题目链接&#xff1a;表示数值的字符串 请实现一个函数用来判…

Spring系列:Spring如何解决循环依赖

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

Hololens打包报错【MSB4181】【error C1192】问题解决

Hololens2打包发生错误&#xff0c;errorcode1&#xff0c;主要原因如下&#xff1a; C:\ProgramFiles\MicrosoftVisualStudio\2022\Community\MSBuild\Microsoft\WindowsXaml\v17.0\8.2\Microsoft.Windows.UI.Xaml.Common.targets(415,5): error MSB4181: CompileXaml false […

Python+OpenGL绘制3D模型(六)材质文件载入和贴图映射

系列文章 一、逆向工程 Sketchup 逆向工程&#xff08;一&#xff09;破解.skp文件数据结构 Sketchup 逆向工程&#xff08;二&#xff09;分析三维模型数据结构 Sketchup 逆向工程&#xff08;三&#xff09;软件逆向工程从何处入手 Sketchup 逆向工程&#xff08;四&#xf…

WSL使用VsCode运行cpp文件

文章目录 缘起主要步骤参考 缘起 今天在阅读《C20设计模式-可复用的面向对象设计方法&#xff08;原书第2版&#xff09;》的时候&#xff0c;遇到代码想要运行一下&#xff0c;于是决定使用wsl下的vscode配置cpp的环境。 主要步骤 1.安装gcc和g编译器 打开命令行输入wsl&am…

推荐系统中 排序策略 CTR 预估加权平均法

CTR&#xff08;Click-Through Rate&#xff09;预估加权平均法是一种用于估计广告点击率的方法&#xff0c;其中对不同的CTR预估模型赋予不同的权重&#xff0c;通过加权平均来得到整体的CTR预估。这样的方法可以充分利用多个CTR预估模型的优势&#xff0c;提高整体的预估准确…

docker应用部署(部署MySql,部署Tomcat,部署Nginx,部署Redis)

Docker 应用部署 一、部署MySQL 搜索mysql镜像 docker search mysql拉取mysql镜像 docker pull mysql:5.6创建容器&#xff0c;设置端口映射、目录映射 # 在/root目录下创建mysql目录用于存储mysql数据信息 mkdir ~/mysql cd ~/mysqldocker run -id \ -p 3307:3306 \ --na…

TCP服务器的编写(下)

我们现在开始对我们的客户端开始封装 我们的客户端&#xff0c;创建完套接字&#xff0c;需不需要bind呢&#xff1f;&#xff1f; 当然是不需要的&#xff0c;你本身是一个客户端&#xff0c;其他人写的应用也可能是客户端&#xff0c;如果我们bind&#xff0c;一定意味着我们…

CCNP课程实验-05-Comprehensive_Experiment

目录 实验条件网络拓朴配置实现基础配置实现IGP需求&#xff1a;1. 根据拓扑所示&#xff0c;配置OSPF和EIGRP2. 在R3上增加一个网段&#xff1a;33.33.33.0/24 (用Loopback 1模拟) 宣告进EIGRP&#xff0c;并在R3上将EIGRP重分布进OSPF。要求重分布进OSPF后的路由Tag值设置为6…

算法基础之滑雪

滑雪 核心思想&#xff1a;记忆化搜索 状态表示&#xff1a; f[i][j] 表示所有从(i,j) 开始滑的路径的最大值 状态计算&#xff1a; 分成四个方向 f[i][j] max(f[i][j] , f[i][j1] 1) 且h[a][b] (下一个点) 必须严格小于 h[i][j] 才能滑过去 #include<iostream>#…

LaTeX符号大全:打破排版的边界

LaTeX符号大全&#xff1a;打破排版的边界 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;让我们一起探索一门极富表现力的排版艺术——LaTeX&…