前两天跟我们架构师大佬学习了一波Spring Validation的用法,最后总结写出一篇有关Validation的技术总结程序员写接口参数校验,总是太多if else?一招让你避免体力活,好巧不巧在我写文章的时候正好被我们的研发经理看到,他凑过来一看我正在写@Valid注解,他本是个技术狂人,看到我这么上进,眼珠子一转,突然坏笑着对我说,给你出道题:1天内自定义一个注解,要实现跟@Valid注解一样的效果,说完一个转身,只留给我一个潇洒的背影……
这下我可没心思在写文章了,就连看到有人给我文章点赞的消息也突然觉得不香了,这要是在以前我可是开心的要起飞……
那么多源码,1天能做到吗?
这想想怎么可能做到嘛,Spring Validation我才刚学会怎么使用,里边怎么校验的还没整明白呢,那么多源码,要我自己实现一个,这不诚心为难我胖虎吗?
不行,还是得找我的架构师老大,他说不定有办法。我把情况跟他一说,只见他眉头一皱,轻声骂道:好你个经理,给我小弟出难题,那我就给你来个野路子1分钟搞定。
1分钟搞定
只见老大打开IDE,直接照着@Valid注解的源码复制新建了一个注解类ValidXXX:
然后告诉我好了。此时我看着老大的表情,大概就像是那个黑人问好脸的表情,这就行了?
老大狡黠的一笑、不置可否,接着把Controller方法里的@Valid注解换成了他刚写的@ValidXXX注解:
然后当我面运行了一把代码,嘿,还真行!
怎么实现的?
老大告诉我,实际上只要是以“Valid”开头的注解都可以实现这个功能。
还有这种操作?也太秀了吧?本着刨根问底的精神,我在源码中一路搜寻,终于被我找到一点儿蛛丝马迹,下面我们就一起来看看到底是怎么回事吧。
源码浅析
首先我们先来了解一下SpringMVC框架在接收到前端HTTP请求后的大致处理流程,我简要的画了张流程图,省去了一些细节只保留了主要流程:
HTTP请求到达SpringMVC后首先会到达DispatcherServlet,由它来从一系列的解析器中选取合适的处理器来解析参数并绑定到Controller,Controller处理完业务逻辑后返回ModelAndView到DispatcherServlet,再次由DispatcherServlet选择合适的视图解析器来渲染视图。今天我们主要任务就是搞定上图中绿色的解析参数部分。
@RequestBody参数解析器
因为我们的接口是用@RequestBody注解来修饰参数的,所以SpringMVC最终会寻找到一个叫作RequestResponseBodyMethodProcessor的参数解析器来处理参数的解析绑定工作。
- 首先我们进去看一下源码:
看下关键点:
- supportsParameter方法申明了该处理器支持处理有@RequestBody注解修饰的参数
- resolveArgument方法则是用来处理具体解析流程,里面我发现一个可能与参数验证有关的地方validateIfApplicable方法
接下来我们进到validateIfApplicable方法看看:
这个方法看起来比较好理解,主要步骤:
- 获取参数上的所有注解,返回一个注解数组
- 循环数组,判断当前注解是不是Validated注解、或者是不是以“Valid”开头,如果是,则执行参数验证逻辑
看到这里,我才终于明白了为什么我们老大随便写了个@ValidXXX的注解也能实现与@Valid注解一样的效果,姜还是老的辣啊!
我是一名正儿八经的程序员,喜欢我的文章欢迎 转发 及 关注,我也会经常与大家分享工作当中的代码那些事儿。