Spring MVC 核心调用流程( 三 )

::: warning 知识点
addMatchingMappings方法 , 主要一个匹配过程 , 匹配 @RequestMapping注解中的属性值是否满足
/** consumes:指定处理请求的提交内容类型(Content-Type) , *例如application/json, text/html;* produces: 指定返回的内容类型 , 仅当request请求头中的(Accept)类型中包含该指定类型才返回;* params:指定request中必须包含某些参数值是 , 才让该方法处理 。* headers:指定request中必须包含某些指定的header值 , 才能让该方法处理请求 。* */@RequestMapping(value = https://www.isolves.com/it/cxkf/kj/2020-10-10/"/getUser",method = RequestMethod.GET,params = "username=jack",consumes = "application/json",produces = "application/json",headers = "Referer=http://www.xx.com/"):::

返回 getHandler , 进入 getHandlerExecutionChain方法
所在类:org.springframework.web.servlet.handler. AbstractHandlerMapping
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {// 如果没有获得则创建一个 HandlerExecutionChainHandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));// 获取当前的请求地址:/user/xxxString lookupPath = this.urlPathHelper.getLookupPathForRequest(request);// 在 HandlerExecutionChain 中添加拦截器// 遍历 SpringMVC 容器的所有拦截器for (HandlerInterceptor interceptor : this.adaptedInterceptors) {// 判断拦截器类型 , 如果是 MappedInterceptor 类型if (interceptor instanceof MappedInterceptor) {MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;// 则先匹配路径后再添加到执行链if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {chain.addInterceptor(mappedInterceptor.getInterceptor());}}else {// 否则直接添加到执行链chain.addInterceptor(interceptor);}}return chain;}::: warning 知识点
getHandlerExecutionChain中的 HandlerInterceptor拦截器是 SpringMVC中的 ,  SpringAOP中的拦截器是 MethodInterceptor 。:::
拿到当前请求对应的 handler后 , 
返回主流程 , 进入 getHandlerAdapter方法
所在类:org.springframework.web.servlet. DispatcherServlet
/** * TODO : 根据 handlerMethod对象 , 找到合适的 HandlerAdapter对象 , 这里用到了策略模式 */protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {if (this.handlerAdapters != null) {for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(handler)) {// 返回一个可以支持的HandlerAdapter 处理程序实例return adapter;}}}throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");}::: warning 知识点
HandlerAdapter 是什么HandlerAdapter是一个接口 , 充当自身与处理程序对象之间的桥梁 , 从而导致松散耦合设计 。HandlerAdapter主要处理方法参数、相关注解、数据绑定、消息转换、返回值、调用视图解析器等 。
RequestMappingHandlerMapping为当前的请求找到合适的处理程序方法 。
RequestMappingHandlerAdapter执行这个处理程序方法 , 并为它提供反射调用所需要的参数 。
 
HandlerAdapter UML 图
HandlerAdapter的4个实现类:
SimpleServletHandlerAdapter: 适配实现 Servlet 接口的 Handler, 默认调用其 service方法
SimpleControllerHandlerAdapter: 适配实现 Controller 接口的 Handler, 默认调用其 handleRequest 方法
HttpRequestHandlerAdapter: 适配实现 HttpRequestHandler 接口的 Handler, 默认调用其 handleRequest 方法
RequestMappingHandlerAdapter: 适配被 @RequestMapping注释的方式, 一般都是解析一个一个参数, 并且通过反射进行激活
HandlerAdapter 总结HandlerAdapter 是 SpringMVC中扩展机制的非常好的一个体现, , 通过 HandlerAdapter这种设计模式 ,  DispatcherServlet 就可以支持任何格式的 Handler(这里的可以支持指在不改变 DispatcherServlet 的情况下) , 第二是 HandlerAdapter 基于不同 Handler实现不同实现类(策略模式) , 最后也是最重要的就是参数的解析与返回值的解析 。
:::
::: danger 为什么要用HandlerAdapter适配器模式? 首先 ,  Controller的定义有多种  , 一种是带 @Controller注解的 ,  还可以写一个 servlet 当做 controller, 所以用适配器做适配 , 不同子类实现 HandlerAdapter接口 , 定义自己的业务逻辑 , 每个子类都是适配某一种类型的控制器 , 有了 HandlerAdapter , 你只需要调用自己实现的 handle方法 , 屏蔽了不一致的细节 , 对用户来说直接找到对应的处理方法 , 无须关系哪个实现方法 , 否则只能在 DispatcherServlet里面通过 if、 else来处理了 。:::


推荐阅读