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 ...
随机推荐
- hive:(group by, having;order by)的使用;group by+多个字段,以及wiki说的group by两种使用限制验证
hive> select * from app_data_stats_historical where os='1' group by dt limit 100; 出现结果如下: 2014-01 ...
- 【Java编程】Java中的大整数计算
在上一篇文章中,我们实现了c语言中的大整数的运算,并且用Miller-Rabin算法实现了对大素数的测试.本来我准备用Java代码实现大整数的运算,查了一下资料发现Java中java.math的Big ...
- rhel6.4 安装nodejs和Mysql DB服务
rhel6.4 安装nodejs和Mysql DB服务 安装好redhat6.4虚拟机后, 安装软件: # yum install gcc-c++ openssl-devel Loaded plugi ...
- 物理引擎中velocity的单位是个什么鬼?
现在, 你可能对于什么是velocity的单位感到奇怪.他是单位秒中经过点的一个可测量的量(pt/s).如果你想要在iphone横屏从左往右的移动物体,并且你想在1秒内移动1024个点,那么物体的x速 ...
- Spring--ClassPathResource
/* * 用一个给定的类加载器或者给定的类来加载资源 */ public class ClassPathResource extends AbstractFileResolvingResource { ...
- Linux - 用make进行工程编译
首先建立好自己的工作目录 然后创建主函数main.cpp 接着写sinValue.h和cosValue.h函数文件 先按照传统方式进行编译运行 然后用make,先写makefile文件 将原来生成的文 ...
- Shell Scripts - 条件语句,case语句,function功能
修改之前的代码 1.判断 $1 是否为 hello,如果是的话,就显示 "Hello, how are you ?": 2.如果没有加任何参数,就提示使用者必须要使用的参数 ...
- Win7笔记本电脑启用虚拟WIFI共享上网
今天看了一个帖子,win7系统通过笔记本的无线网卡,启用虚拟Wifi功能共享上网,自己尝试了一下,感觉很好用,至少没有无线路由的自己,手机可以上wifi了,更新软件玩微信等等,都方便多了,好了,废话不 ...
- LeetCode(36)- Implement Stack using Queues
题目: Implement the following operations of a stack using queues. push(x) -- Push element x onto stack ...
- 【Web页面测试】测试点和测试用例
1. 需求符合度测试 1. 各级菜单名称显示是否按照需求说明书规定的设计,并且没有遗漏和多余 2. 各级菜单所完成的功能是否按照需求说明书规定的设计,并且没有遗漏和多余 3. 各级菜单的操作顺序和操作 ...