深入了解数据校验(Bean Validation):ValidatorFactory和Validator等核心API【享学Java】(下)

简介: 深入了解数据校验(Bean Validation):ValidatorFactory和Validator等核心API【享学Java】(下)

ValidatorImpl


它是Hibernate Validator提供的唯一校验器实现(思想准备:非常复杂)



public class ValidatorImpl implements Validator, ExecutableValidator {
  private static final Collection<Class<?>> DEFAULT_GROUPS = Collections.<Class<?>>singletonList( Default.class );
  // 分组Group校验的顺序问题
  // 若依赖于校验顺序,可用使用@GroupSequence注解来控制Group顺序
  private final transient ValidationOrderGenerator validationOrderGenerator;
  private final ConstraintValidatorFactory constraintValidatorFactory;
  ...
  // 唯一构造函数~
  public ValidatorImpl(ConstraintValidatorFactory constraintValidatorFactory, BeanMetaDataManager beanMetaDataManager,
      ValueExtractorManager valueExtractorManager, ConstraintValidatorManager constraintValidatorManager,
      ValidationOrderGenerator validationOrderGenerator, ValidatorFactoryScopedContext validatorFactoryScopedContext) {
    this.constraintValidatorFactory = constraintValidatorFactory;
    this.beanMetaDataManager = beanMetaDataManager;
    this.valueExtractorManager = valueExtractorManager;
    this.constraintValidatorManager = constraintValidatorManager;
    this.validationOrderGenerator = validationOrderGenerator;
    this.validatorScopedContext = new ValidatorScopedContext( validatorFactoryScopedContext );
    this.traversableResolver = validatorFactoryScopedContext.getTraversableResolver();
    this.constraintValidatorInitializationContext = validatorFactoryScopedContext.getConstraintValidatorInitializationContext();
  }
  @Override
  public final <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
    sanityCheckGroups( groups ); // groups里面的内容不能有null
    @SuppressWarnings("unchecked")
    Class<T> rootBeanClass = (Class<T>) object.getClass();
    BeanMetaData<T> rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass );
    // 若没有约束存在,直接返回~
    if ( !rootBeanMetaData.hasConstraints() ) {
      return Collections.emptySet();
    }
    // ValidationContext这个实体类里面的属性极其多~  持有各种组件的引用
    ValidationContext<T> validationContext = getValidationContextBuilder().forValidate( rootBeanMetaData, object );
    // 找到这个分组们的(带有顺序)
    ValidationOrder validationOrder = determineGroupValidationOrder( groups );
    // ValueContext一个实例用于收集所有相关信息,以验证单个类、属性或方法调用。
    ValueContext<?, Object> valueContext = ValueContext.getLocalExecutionContext(validatorScopedContext.getParameterNameProvider(), object,
        validationContext.getRootBeanMetaData(), PathImpl.createRootPath()
    );
    // 此方法传入的信息量非常大~~ 验证上下文、值上下文,验证器
    // 返回的是失败的消息对象:ConstraintViolation  它是被存储在ValidationContext里的~~~~
    return validateInContext( validationContext, valueContext, validationOrder );
  }
  ... // 省略validateProperty和validateValue
  // 下面实现`ExecutableValidator`的相关方法  它的四个接口方法无非就是两个方法:validateParameters和validateReturnValue 略
  //  beanMetaDataManager.getBeanMetaData( clazz )还是相对比较重要的
  @Override
  public final BeanDescriptor getConstraintsForClass(Class<?> clazz) {
    return beanMetaDataManager.getBeanMetaData( clazz ).getBeanDescriptor();
  }
  @Override
  public final <T> T unwrap(Class<T> type) {
    if ( type.isAssignableFrom( Validator.class ) ) {
      return type.cast( this );
    }
    throw LOG.getTypeNotSupportedForUnwrappingException( type );
  }
  // 返回自己即可。因为它是可以校验方法入参、返回值等等的
  @Override
  public ExecutableValidator forExecutables() {
    return this;
  }
  ... // 省略所有的私有方法们~
}


同样的hibernate实现这套ValidatorImpl校验逻辑不可为不复杂。幸好的是:对于我们web程序员来说,我个人建议只需要掌握到几大主流的组件的使用,就完全够用了(毕竟它有很多能力是给javaFx提供的)。再若不需要关心实现细节,完全面向接口编程我认为也是ok的~~


执行validator.validate(person)方法后,最终拿到的是多个ConstraintViolation,它代表着校验失败的那些讯息,若是Spring框架集成,拿出来做出友好的提示便可达到我们的校验效果~


总结


本文总体还是还是依托实例,再着眼于原理层面的分析,介绍了ValidatorFactory和Validator核心。和上文不一样的是,这两个API应该是我们使用者最应该关注的,所以他们提供的接口方法,希望小伙伴可以稍微留点心,记点忆。


上面也说了,hibernate validation它对数据校验的实现非常非常的复杂,毕竟它提供的能力也是非常强大的(当然弱弱说一句:作者打代码能力也是有待讨论的)。

但是我个人认为,如文章所述掌握到这种程度至少对于web开发者来说是够用了的,甚至我相信大多数小伙伴都感觉内容已经溢出了,所以那就各自领会吧~


Bean Validation核心原理部分到此就先告一段落,像什么扩展它的SPI如:ConstraintMappingContributor、ResourceBundleLocator、DefaultGroupSequenceProvider等虽然功能强大可扩展,但本系列就不再讨论了~~~


接下来开始面向小伙伴最为关心的:使用、集成、高级定制等,当然还包括在Spring环境下的高度整合和扩展使用,请持续关注~


相关阅读


深入了解数据校验:Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validation 6.x使用案例【享学Java】

深入了解数据校验(Bean Validation):基础类打点(ValidationProvider、ConstraintDescriptor、ConstraintValidator)【享学Java】

相关文章
|
6月前
|
JSON Java API
【干货满满】分享京东API接口到手价,用Java语言实现
本示例使用 Java 调用京东开放平台商品价格及优惠信息 API,通过商品详情和促销接口获取到手价(含优惠券、满减等),包含签名生成、HTTP 请求及响应解析逻辑,适用于比价工具、电商系统集成等场景。
|
11月前
|
缓存 监控 负载均衡
如何提升 API 性能:来自 Java 和测试开发者的优化建议
本文探讨了如何优化API响应时间,提升用户体验。通过缓存(如Redis/Memcached)、减少数据负载(REST过滤字段或GraphQL精确请求)、负载均衡(Nginx/AWS等工具)、数据压缩(Gzip/Brotli)、限流节流、监控性能(Apipost/New Relic等工具)、升级基础设施、减少第三方依赖、优化数据库查询及采用异步处理等方式,可显著提高API速度。快速响应的API不仅让用户满意,还能增强应用整体性能。
|
6月前
|
JSON Java API
【干货满满】分享拼多多API接口到手价,用Java语言实现
本方案基于 Java 实现调用拼多多开放平台商品详情 API,通过联盟接口获取商品到手价(含拼团折扣与优惠券),包含签名生成、HTTP 请求及响应解析逻辑,适用于电商比价、导购系统集成。
|
6月前
|
JSON Java API
【干货满满】分享淘宝API接口到手价,用Java语言实现
本文介绍了如何使用 Java 调用淘宝开放平台 API 获取商品到手价,涵盖依赖配置、签名生成、HTTP 请求与响应解析等核心实现步骤。
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
453 2
|
7月前
|
JSON JavaScript 前端开发
Python+JAVA+PHP语言,苏宁商品详情API
调用苏宁商品详情API,可通过HTTP/HTTPS发送请求并解析响应数据,支持多种编程语言,如JavaScript、Java、PHP、C#、Ruby等。核心步骤包括构造请求URL、发送GET/POST请求及解析JSON/XML响应。不同语言示例展示了如何获取商品名称与价格等信息,实际使用时请参考苏宁开放平台最新文档以确保兼容性。
|
11月前
|
前端开发 Cloud Native Java
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
|
11月前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
319 11
|
数据采集 存储 Java
Java爬虫获取微店店铺所有商品API接口设计与实现
本文介绍如何使用Java设计并实现一个爬虫程序,以获取微店店铺的所有商品信息。通过HttpClient发送HTTP请求,Jsoup解析HTML页面,提取商品名称、价格、图片链接等数据,并将其存储到本地文件或数据库中。文中详细描述了爬虫的设计思路、代码实现及注意事项,包括反爬虫机制、数据合法性和性能优化。此方法可帮助商家了解竞争对手,为消费者提供更全面的商品比较。
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
3059 5