SSM-SpringMVC-04:SpringMVC深入浅出理解HandleMapping(源码刨析)
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------
先从概念理解,从中央调度器,携带参数request,调度到HandleMapping处理器映射器,处理器映射器返回处理器执行链给中央调度器
我从底层走一遍,印证这个概念:
1.都说是中央调度器的,所以先找到中央调度器DispatcherServlet
2.从他里面找到一个方法 ctrl+f 找(doDistch)
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView err = null;
Exception dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest);
if(mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ex = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if(isGet || "HEAD".equals(method)) {
long lastModified = ex.getLastModified(request, mappedHandler.getHandler());
if(this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if(!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
err = ex.handle(processedRequest, response, mappedHandler.getHandler());
if(asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, err);
mappedHandler.applyPostHandle(processedRequest, response, err);
} catch (Exception var19) {
dispatchException = var19;
}
this.processDispatchResult(processedRequest, response, mappedHandler, err, dispatchException);
} catch (Exception var20) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20);
} catch (Error var21) {
this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21);
}
} finally {
if(asyncManager.isConcurrentHandlingStarted()) {
if(mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if(multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
这个方法里面很多内容不需要关注,需要关注的的我讲讲
HttpServletRequest processedRequest = request;
//接收请求
HandlerExecutionChain mappedHandler = null;
//处理器执行链
boolean multipartRequestParsed = false;
//多部分请求,文件上传
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
//异部请求 try {
try { ModelAndView err = null;
//视图解析 try { processedRequest = this.checkMultipart(request);
//检查是否是多部分请求
multipartRequestParsed = processedRequest != request; mappedHandler = this.getHandler(processedRequest);
//这就返回处理器执行链
3.到这儿,点击getHandler(processedRequest)查看
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Iterator var2 = this.handlerMappings.iterator();
HandlerExecutionChain handler;
do {
if(!var2.hasNext()) {
return null;
}
HandlerMapping hm = (HandlerMapping)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
}
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
我把关键代码提炼出来解释一波
//迭代器,没做泛型,handlerMapping是list集合
Iterator var2 = this.handlerMappings.iterator();
//处理器执行链
HandlerExecutionChain handler;
do {
if(!var2.hasNext()) {
return null;
}
//处理器映射器
HandlerMapping hm = (HandlerMapping)var2.next(); //继续追踪
handler = hm.getHandler(request);
} while(handler == null); return handler;
4.追踪hm.getHandler(request)方法,发现他是HandlerMapping接口的,(Ctrl+H)找它的实现类AbstractHandlerMapping,ctrl+F找getHandler
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = this.getHandlerInternal(request);
if(handler == null) {
handler = this.getDefaultHandler();
}
if(handler == null) {
return null;
} else {
if(handler instanceof String) {
String executionChain = (String)handler;
handler = this.getApplicationContext().getBean(executionChain);
}
HandlerExecutionChain executionChain1 = this.getHandlerExecutionChain(handler, request);
if(CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
CorsConfiguration config = globalConfig != null?globalConfig.combine(handlerConfig):handlerConfig;
executionChain1 = this.getCorsHandlerExecutionChain(request, executionChain1, config);
}
return executionChain1;
}
}
同样,我把关键代码提出来解释一波
//获取处理器
Object handler = this.getHandlerInternal(request);
//处理器为空就用默认的
if(handler == null) {
handler = this.getDefaultHandler();
}
//默认的也是空就返回null
if(handler == null) {
return null;
} else {
//判断是否是String类型
if(handler instanceof String) {
//这儿就是我们一般用的处理器的从配置文件bean的id
String handlerName = (String)handler; // /hello
//这就是Spring啊
handler = this.getApplicationContext().getBean(handlerName);
}
//获取处理程序执行链
HandlerExecutionChain executionChain1 = this.getHandlerExecutionChain(handler, request);
//返回的时候变成携带处理器的了
return this.getHandlerExecutionChain(handler, request); }
5.追踪获取程序执行链,this.getHandlerExecutionChain(handler,request)
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
//三元表达式,是处理器执行链就强转,不是就获取根据处理器生成一个
HandlerExecutionChain chain = handler instanceof HandlerExecutionChain?(HandlerExecutionChain)handler:new HandlerExecutionChain(handler);
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
Iterator var5 = this.adaptedInterceptors.iterator();
while(var5.hasNext()) {
//只需要知道这儿添加拦截器即可
HandlerInterceptor interceptor = (HandlerInterceptor)var5.next();
if(interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor;
if(mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
SSM-SpringMVC-04:SpringMVC深入浅出理解HandleMapping(源码刨析)的更多相关文章
- 30s源码刨析系列之函数篇
前言 由浅入深.逐个击破 30SecondsOfCode 中函数系列所有源码片段,带你领略源码之美. 本系列是对名库 30SecondsOfCode 的深入刨析. 本篇是其中的函数篇,可以在极短的时间 ...
- HashMap源码刨析(面试必看)
目录 1.Hash的计算规则? 2.HashMap是怎么形成环形链表的(即为什么不是线程安全)?(1.7中的问题) 3.JDK1.7和1.8的HashMap不同点? 4.HashMap和HashTab ...
- Java 源码刨析 - 线程的状态有哪些?它是如何工作的?
线程(Thread)是并发编程的基础,也是程序执行的最小单元,它依托进程而存在. 一个进程中可以包含多个线程,多线程可以共享一块内存空间和一组系统资源,因此线程之间的切换更加节省资源.更加轻量化,也因 ...
- MapReduce源码刨析
MapReduce编程刨析: Map map函数是对一些独立元素组成的概念列表(如单词计数中每行数据形成的列表)的每一个元素进行指定的操作(如把每行数据拆分成不同单词,并把每个单词计数为1),用户可以 ...
- Flask上下文管理及源码刨析
基本流程概述 - 与django相比是两种不同的实现方式. - django/tornado是通过传参数形式实现 - 而flask是通过上下文管理, 两种都可以实现,只不实现的方式不一样罢了. - 上 ...
- ConcurrentHashMap源码刨析(基于jdk1.7)
看源码前我们必须先知道一下ConcurrentHashMap的基本结构.ConcurrentHashMap是采用分段锁来进行并发控制的. 其中有一个内部类为Segment类用来表示锁.而Segment ...
- Java 源码刨析 - String
[String 是如何实现的?它有哪些重要的方法?] String 内部实际存储结构为 char 数组,源码如下: public final class String implements java. ...
- Java 源码刨析 - HashMap 底层实现原理是什么?JDK8 做了哪些优化?
[基本结构] 在 JDK 1.7 中 HashMap 是以数组加链表的形式组成的: JDK 1.8 之后新增了红黑树的组成结构,当链表大于 8 并且容量大于 64 时,链表结构会转换成红黑树结构,它的 ...
- form 源码刨析
def clean_name(self) value = self.cleaned_data.get('name') if "金-瓶-梅" not in value: raise ...
随机推荐
- Retinex图像增强算法
前一段时间研究了一下图像增强算法,发现Retinex理论在彩色图像增强.图像去雾.彩色图像恢复方面拥有很好的效果,下面介绍一下我对该算法的理解. Retinex理论 Retinex理论始于Land和M ...
- Makefile的obj-y 和 obj-m
目标定义是Kbuild Makefile的主要部分,也是核心部分.主要是定义了要编 译的文件,所有的选项,以及到哪些子目录去执行递归操作. 最简单的Kbuild makefile 只包含一行: 例子: ...
- linux 网络不通问题排查
基本的排错步骤(从上往下)ping 127.0.0.1ping的通说明tcp协议栈没有问题ping 主机地址 ping的通说明网卡没有问题ping 路由器默认网关 ping的通说明包可以到达路由器最后 ...
- 销售行业ERP数据统计分析都有哪些维度?
场景描述 当前的企业信息化建设主要包括ERP系统.OA系统等.企业希望实现信息系统数据的整合,对企业资源进行分析汇总,方便对企业相关数据的掌控从而便于对业务流程进行及时调整监控. 但是由于系统间数据的 ...
- iOS评分功能、APP中打开其他应用程序
1.评分功能 iOS中评分支持功能开发非常简单. NSString *str = [NSString stringWithFormat: @"itms-apps://itunes.apple ...
- Android使用统计图AChartEngine 来展示数据
本文采用的统计图参考:AChartEngine 访问地址 :http://code.google.com/p/achartengine/ 先给出效果图 本文的开发代码主要是这些:对一些代码进行修改 以 ...
- Java反编译工具(Java Decompiler)
Java Decompiler是一种非常实用的JAVA反编译工具,可以对整个jar包进行反编译,也可以将其集成到eclipse上,非常方便的根据class文件的源码.,官网地址http://jd.be ...
- obj-c编程10:Foundation库中类的使用(1)[数字,字符串]
我们知道在mac或iphone上编程最终逃不开os x平台,你无法在windows或linux上开发纯正的apple程序.(so不要舍不得银子买mac啦)虽说linux和windows上有移植的obj ...
- python socketserver框架解析
socketserver框架是一个基本的socket服务器端框架, 使用了threading来处理多个客户端的连接, 使用seletor模块来处理高并发访问, 是值得一看的python 标准库的源码之 ...
- MySql 行转列 存储过程实现
同学们在使用mysql的过程中,会遇到一个行转列的问题,就是把多条数据转化成一条数据 用多列显示. 方法1. 实现方式用下面的存储过程,表名对应的修改就行. BEGIN declare current ...