SpringMVC学习之HandlerMapping
文章目录
起因
新服务在处理不存在的url请求时,上报日志报错,具体错误信息:
根据报错信息找到相关代码
代码处做了对参数hanler的强制转换,但是真正传入的参数类型为 ResourceHttpRequestHandler 导致转换失败而报错,梳理一下,handler是在 自定义的日志Interceptor 的afterCompletion方法中由框架传入的
ResourceHttpRequestHandler 是什么?
查阅类文档,ResourceHttpRequestHandler是SpringMVC提供的处理静态资源的Handler,比如常见的js或者css文件。在当前前后端分离的分工下,对于REST服务开发,不会再使用这种方式提供对静态资源的访问,为什么请求了一个不存在的url,会使用静态资源的Hanlder来处理?
SpringMVC提供了哪些HandlerMapping?
SpringMVC提供的HanlderMapping位于 org.springframework.web.servlet.handler 包下,主要包含
Mapping | Desc |
---|---|
RequestMappingHandlerMapping | 处理@RequestMapping 注解映射关系 |
SimpleUrlHandlerMapping | 使用URL模式匹配映射关系 |
BeanNameUrlHandlerMapping | 基于Bean名匹配映射关系 |

SpringMVC 路径映射流程回顾
回顾一下SpringMVC的路径映射流程,通常的url请求的编码方式为:
|
|
标识了 @RequestMapping 注解的方法会被 SpringMVC 框架的 RequestMappingHandlerMapping 类在启动时进行扫描并根据映射信息来创建 RequestMappingInfo(RequestMappingInfo 类维护请求的映射信息),扫描后的所有Mapping信息在 MappingRegistry(AbstractHandlerMethodMapping内部类) 类进行维护

SpringMVC如何处理request与HandlerMethod的映射关系
AbstractHandlerMethodMapping的getHandler 方法用来通过给定的request来找到一个合适的handler进行处理
getHandler会先调用抽象方法 getHandlerInternal 由子类实现查找逻辑,如果找不到,则查找默认配置的Hanlder,默认Hanlder找不到则返回null
SpringMVC默认使用了哪些HandlerMapping
如何查询Handler是在 DispacherServlet的getHandler方法操作的,它会在所有的handlerMappings(有序handlerMapping)中查找出一个可用的handler进行request的处理

如图可知会在7个handlerMapping中依次进行查询,这些handlerMapping是在 DispatcherServlet#initHandlerMappings()
设置的
定位到问题原因
跟踪请求代码发现对于不存在的url会在 SimpleUrlHanlderMapping中找到可用的handler,因为最终请求url匹配上了 /**,而 /** 模式对应的handler就是 ResourceHttpRequestHandler,此时getHandler的结果就是ResourceHttpRequestHandler 了,但是在上报时使用的是 HandlerMethod,执行到此时报了转换异常


WebMvcAutoConfiguration中的SourceHandler在哪注册的?
在启用MVC功能时,会增加注解 @EnableWebMvc,而对应的MVC配置类为 WebMvcConfigurationSupport,在这个类中进行SourceHandler的注册。跟踪代码发现两个ResourceHandler是在 WebMvcAutoConfigurationAdapter中添加的
