springmvc源码笔记-RequestMappingHandlerMapping
下图是springmvc的执行流程

图片来源:https://www.jianshu.com/p/8a20c547e245
DispatcherServlet根据url定位到Controller和方法,依赖的是HandlerMapping接口的各个实现类,其中,RequestMappingHandlerMapping是专门用来处理注解方式的Controller的
下面,我们分RequestMappingHandlerMapping的加载以及RequestMappingHandlerMapping如何根据url定位Controller两部分来讲
RequestMappingHandlerMapping加载过程
RMHP在系统启动时会被注册成bean,见《springmvc源码笔记-HandlerMapping注入》
因为RMHP实现了InitializingBean接口,在bean加载完成后会自动调用afterPropertiesSet方法,在此方法中调用了AbstractHandlerMethodMapping#initHandlerMethods()来实现初始化
protected void initHandlerMethods() {
// 遍历所有的bean
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
} protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
beanType = obtainApplicationContext().getType(beanName);
}
......
// isHandler判断类是否有Controller或者RequestMapping注解
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
} protected void detectHandlerMethods(Object handler) {
......
if (handlerType != null) {
Class<?> userType = ClassUtils.getUserClass(handlerType);
// 遍历类的所有方法
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
// 获取方法上的映射(会读取方法上的RequestMapping注解获取url)
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
......
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// 将映射关系放入AbstractHandlerMethodMapping.mappingRegistry中
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
RequestMappingHandlerMapping解析过程
DispatcherServlet继承HttpServlet,所以执行链是FrameworkServlet#doGet→DispatcherServlet#doService→DispatcherServlet#doDispatch→DispatcherServlet#getHandler
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
// handlerMappings已在onRefresh方法中初始化
for (HandlerMapping mapping : this.handlerMappings) {
// 第一个mapping就是RequestMappingHandlerMapping
// 获取处理程序,也就是url对应的controller和method
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
} // AbstractHandlerMapping#getHandler->RequestMappingHandlerMapping#getHandlerInternal->AbstractHandlerMapping#lookupHandlerMethod
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
// lookupPath就是请求路径
List<Match> matches = new ArrayList<>();
// 获取url路径匹配项
List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
if (directPathMatches != null) {
// 添加映射匹配集合
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
}
if (!matches.isEmpty()) {
......
// 至此,根据url获取到controller和method
return bestMatch.getHandlerMethod();
} else {
return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
}
} private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
T match = getMatchingMapping(mapping, request);
if (match != null) {
// this.mappingRegistry.getRegistrations().get(mapping)就是获取HandlerMethodMapping
// HandlerMethodMapping保存controller和method信息的类
matches.add(new Match(match, this.mappingRegistry.getRegistrations().get(mapping)));
}
}
}
springmvc源码笔记-RequestMappingHandlerMapping的更多相关文章
- springmvc源码笔记-HandlerMapping注入
在springmvc中,如何根据url找到controller以及对应方法,依赖的是HandlerMapping接口的getHandler方法 在spring容器中默认注册的HandlerMappin ...
- springMVC源码笔记
springMVC 设计总览 下图来源:https://www.cnblogs.com/fangjian0423/p/springMVC-directory-summary.html 下图来源:htt ...
- springmvc源码笔记-HandlerMethodReturnValueHandler
返回值解析器 用于对controller的返回值进行二次处理 结构 // 返回值解析器 public interface HandlerMethodReturnValueHandler { // 判断 ...
- SpringMVC源码情操陶冶-AnnotationDrivenBeanDefinitionParser注解解析器
mvc:annotation-driven节点的解析器,是springmvc的核心解析器 官方注释 Open Declaration org.springframework.web.servlet.c ...
- SpringMVC源码情操陶冶-DispatcherServlet简析(二)
承接前文SpringMVC源码情操陶冶-DispatcherServlet类简析(一),主要讲述初始化的操作,本文将简单介绍springmvc如何处理请求 DispatcherServlet#doDi ...
- SpringMVC源码情操陶冶-AbstractHandlerMethodMapping
承接前文SpringMVC源码情操陶冶-AbstractHandlerMapping,本文将介绍如何注册HandlerMethod对象作为handler 类结构瞧一瞧 public abstract ...
- SpringMVC源码情操陶冶-RequestMappingHandlerAdapter适配器
承接前文SpringMVC源码情操陶冶-HandlerAdapter适配器简析.RequestMappingHandlerAdapter适配器组件是专门处理RequestMappingHandlerM ...
- springMVC源码分析--AbstractHandlerMethodMapping注册url和HandlerMethod对应关系(十一)
在上一篇博客springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)中我们简单地介绍了获取url和HandlerMet ...
- SpringMVC源码阅读:拦截器
1.前言 SpringMVC是目前J2EE平台的主流Web框架,不熟悉的园友可以看SpringMVC源码阅读入门,它交代了SpringMVC的基础知识和源码阅读的技巧 本文将通过源码(基于Spring ...
随机推荐
- HMS Core地理围栏能力助你实现指定范围人群的精准消息推送
精准推送是移动端产品留存阶段的主要运营手段,精准推送常常会与用户画像紧密结合,针对用户的喜好.画像,采用不同策略,但基于用户所属区域推送消息却很难实现.目前市面上大多数第三方消息推送服务商,在系统未深 ...
- Spring 源码(9)Spring Bean的创建过程的前期准备
回顾总结 到目前为止,Spring源码中AbstractApplicationContext#refresh方法的已经解读到第11个方法finishBeanFactoryInitialization, ...
- pyhon对excel的xls与xlsx的读取,写入
import shutilimport osfrom openpyxl import load_workbookfrom xlutils.copy import copyimport win32com ...
- 《Java编程思想》读书笔记(二)
三年之前就买了<Java编程思想>这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第一章到第十章的内容,这一次记录的是第 ...
- 如何在 pyqt 中解决启用 DPI 缩放后 QIcon 模糊的问题
问题描述 如今显示器的分辨率越来越高,如果不启用 DPI 缩放,软件的字体和图标在高分屏下就会显得非常小,看得很累人.从 5.6 版本开始,Qt 便能支持 DPI 缩放功能,Qt6 开始这个功能是默认 ...
- 关于『进击的Markdown』:第五弹
关于『进击的Markdown』:第五弹 建议缩放90%食用 路漫漫其修远兮,吾将上下而求索. 我们要接受Mermaid的考验了呢 Markdown 语法真香(一如既往地安利) ( 进击吧!Mark ...
- 【摸鱼神器】UI库秒变LowCode工具——列表篇(二)维护json的小工具
上一篇介绍了一下如何实现一个可以依赖 json 渲染的列表控件,既然需要 json 文件,那么要如何维护这个 json 文件就成了重点,如果没有好的维护方案的话,那么还不如直接用UI库. 所以需要我们 ...
- Hyperledger Fabric 智能合约开发及 fabric-sdk-go/fabric-gateway 使用示例
前言 在上个实验 Hyperledger Fabric 多组织多排序节点部署在多个主机上 中,我们已经实现了多组织多排序节点部署在多个主机上,但到目前为止,我们所有的实验都只是研究了联盟链的网络配置方 ...
- 网络协议之:memcached binary protocol详解
目录 简介 memcached的协议包 memcached命令举例 总结 简介 前面讲到了memcached的文本协议,虽然文本协议看起来非常简单,但是对于客户端来说一般还是会选择效率更高的二进制协议 ...
- python亲密数设计
'''亲密数 (如果a的所有正因子和等于b,b的所有正因子和等于a,因子包括1但不包括本身,且a不等于b,则称a,b为亲密数对.一般通过叠代编程求出相应的亲密数对)'''n = 3000def fun ...