一种校验技巧与原理浅析

一、校验场景与技巧

业务逻辑需要通过邮件发送资料,界面提供邮件信息的配置,包含标题、模板、收件人列表等。其中收件人邮件地址均要符合通用的邮件格式。

如何简单有效的在java后端对请求中的收件人邮件地址做校验呢?

我们其实可以利用遵循JSR-303规范定义或衍生的注解来实现,示例代码:

即:

  • 请求体对象中集合类型字段的泛型中增加@Email注解的校验配置
  • 请求方法带@RequestBody注解的参数,增加@Valid注解

二、原理探索

经过探索分析,原理主要涵盖以下知识点,我们将从文档、源码等多角度来做到知其然知其所以然。

1.JSR-303

JSR-303JCP (Java Community Process)发布在其官网的一种Java规范提案,称为Bean Validation规范,为Bean验证定义了元数据模型和API。

2.自动配置与事件机制 

 

由spring-boot-auto-configure包的spring.factories中指定配置的BackgroundPreinitializer来自动承担应用监听器的角色。该对象bean注入spring容器后,监听springboot应用启动事件,监听到则异步触发多个模块的初始化,包括验证模块ValidationInitializer。该验证模块的初始化机制,稍后会详细展开。

3.SPI & Validation API

在面向的对象的设计里,一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。而

SPI (Service Provider Interface) 是Java提供的一套用来被第三方实现或者扩展的API,核心思想就是解耦,与即插即用。

典型案例:JDBC驱动的加载,SLF4J日志接口,dubbo的扩展,sharding-jdbc 数据加密,Flink的Table加载等。

验证相关的SPI机制如下:

 从上图可知,springboot-auto-configure触发调用,validation-api中提供了验证提供器的服务接口定义,hibernate-validator提供了服务接口的实现,由ServiceLoader负责将其加载。

4.ServiceLoader

 JDK 1.6 引入,用于懒加载SPI服务提供者。

从源码可见,ServiceLoader负责搜索Classpath下META-INF/services目录下名称为SPI接口的文件,解析其内容(接口的实现类的路径),并加载实例化。 

5.hibernateValidator

 第2小节提到了ValidationInitializer,此处由Validation类的configure方法通过ServiceLoader加载到hibernateValidator。

思考:对象属性打上的验证注解,每次请求时应用程序是如何根据注解的不同采取不同的验证呢?

还是用源码来揭晓谜底:

 本小节第一张截图中代码 configuration.buildValidatorFactory()即是调用上图箭头所指的方法,在该方法中会进行初始化的工作,包括验证注解及其关系的绑定,如下图,是否恍然大悟:

例如,注解@NotBlank将由NotBlankValidator验证器来检查是否该字段的值符合非空串的校验。 

 

6.触发

让我们通过一张特殊的流程类图,来了解每次请求到达,应用程序是如何完整的完成校验及其它相关处理的。

7.源码技巧赏析

请再次开动脑筋

精髓:一个boolean成员变量 + 字节与表达式 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值