前言
最近,准备查一下Spring中的Interceptor的实现原理,以及运行机制,怎么在Spring中发挥作用。无意间就手动搜索了handler,结果就开始了handler的探究。这也算是一个意外的收获吧!如果,此时你也在了解探究Handler,希望这篇文章可以给你一点帮助哦,我也希望在评论区留下你的见解,一起学习探究!
探究Mapping机制
1. 初识HandlerMapping
在了解Spring的Handler之前,我们先来了解一下Spring MVC的运行原理与机制,学习与使用过Spring的我们,对下图肯定不会感到陌生吧。(网上扣的图)
通过上图,我们可以看到,我们在开发使用Spring开发web项目时,我们的所有客户端请求都会交给DispatcherServlet来处理,接着DispatcherServlet会调用HandlerMapping来解析URL,完成Controller的匹配,接着执行业务操作,最后将数据交给ViewResolver处理视图映射。这个过程上图已经表达的很清楚了。说到这里,我们应该清楚了,Handler的作用很重要,它是连接用户请求与服务端业务的桥梁。让服务器知道用户的请求应该映射到哪个Controller,调用Controller的那个业务Method完成用户的请求。
2. 内置HandlerMapping原理
都知道URL的映射是通过@RequestMapping注解完成的,使用起来 so easy。内部又是如何来解析和处理的呢?我们一起来看看。
- 对于@RequestMapping注解的处理,在Spring(我使用的是5.x版本)的内部是通过RequestMappingHandlerMapping来处理完成的。通过下图,我们继续找父类RequestMappingInfoHandlerMapping。
- 通过观察RequestMappingInfoHandlerMapping类的头部信息,我们发现该类是 AbstractHandlerMethodMapping 的派生类,此处的泛型 “T”具体为 RequestMappingInfo 类型。
- 在RequestMappingInfo类中,通过注释信息,属性信息,可以看出来,这里包装了单个请求的所有信息,例如:请求参数,请求头以及请求方法等信息。
- DispatcherServlet在执行时,首先会初始化内部的一些策略,包括:多媒体解析,主题解析,处理器映射,视图解析等默认的内部执行策略。
- DispatcherServlet是FrameworkServlet的派生类,并且实现了
doService(request,response)
方法来处理客户端请求。说明:这是实现了FramworkServlet的doService方法,FramworkServlet继承自HttpServlet,并且重写了父类中的doGet(),doPost(),doPut(),doDelete 等方法,在这些重写的方法里都调用了 processRquest() 方法做请求处理,进入processRquest()可以看到里面调用了FramworkServlet中定义的doService() 方法。读到这里,是不是突然就明白了,DispatcherServlet通过一个doService()方法巧妙的来处理客户端的多种请求需要完成的业务。简直妙极了~~
实践
首先,我们定义自己的映射器注解(类似于和@RequestMapping的作用),并且实现HandlerMapping。完成客户端所请求路径(URL)和Controller中被该注解标注的方法或者类的匹配工作,然后正确执行相应的Controller方法完成客户端的业务。
- 编写注解类
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MongoRequestMapping { /** * 映射的 URL 地址 * @return */ String value() default ""; }
- 编写HandlerMapping完成注解映射处理,这里我们继承Spring中的RequestMappingHandlerMapping,加上部分日志信息,观察自定义的HandlerMapping是否执行了。(如果你想要完全自己处理映射匹配的逻辑,可以参考Spring源码 RequestMappingHandlerMapping 类的具体实现)
@Component public class MongoRequestHandlerMapping extends RequestMappingHandlerMapping { private