Spring MVC的handlermapping之请求分发如何找到正确的Handler(BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping)
本文讲的是Spring MVC如何找到正确的handler, 前面请求具体怎么进入到下面的方法,不再细说。
大概就是Spring mvc通过servlet拦截请求,实现doService方法,然后进入doDispatch()方法,这个是完成请求的方法.
今天我们只分析:mappedHandler = this.getHandler(processedRequest, false); 这一个方法;
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Iterator i$ = this.handlerMappings.iterator();//handlerMapping 是初始化的时候就保存好的,如果多个的话已经排序好了
HandlerExecutionChain handler; //实际上返回的handler是一个 handler链,包含了处理器和拦截器
do {
if (!i$.hasNext()) {
return null;
}
//这块发现实际上就是取第一个就好了
HandlerMapping hm = (HandlerMapping)i$.next();
if (this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
handler = hm.getHandler(request); //然后调用具体处理器的getHandler方法
} while(handler == null);
return handler;
}
现在以BeanNameUrlHandlerMapping为例:
这个类的继承关系前面几篇文章已经介绍过了。实际上父类AbstractHandlerMapping实现了gethandler方法,还记得这个类初始化的时候做的是初始化拦截器,然后让子类重写方法initApplicationContext进行处理注册
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 handlerName = (String)handler;
handler = this.getApplicationContext().getBean(handlerName);
}
return this.getHandlerExecutionChain(handler, request);//封装 处理器链
}
}
getHandlerInternal是由AbstractUrlHandlerMapping实现的, 他是BeanNameUrlHandlerMapping和SimpleUrlHandlerMapping的父类,所以,两个映射器都是通过这个方法查找的,
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request); //从请求中获取URL
Object handler = this.lookupHandler(lookupPath, request); //查找handler
if (handler == null) { //如果没找到 给一个默认的处理器
Object rawHandler = null;
if ("/".equals(lookupPath)) {
rawHandler = this.getRootHandler();
}
if (rawHandler == null) {
rawHandler = this.getDefaultHandler();
}
if (rawHandler != null) {
if (rawHandler instanceof String) {
String handlerName = (String)rawHandler;
rawHandler = this.getApplicationContext().getBean(handlerName);
}
this.validateHandler(rawHandler, request);
handler = this.buildPathExposingHandler(rawHandler, lookupPath, lookupPath, (Map)null);//添加两个拦截器,作用?
}
}
if (handler != null && this.logger.isDebugEnabled()) {
this.logger.debug("Mapping [" + lookupPath + "] to " + handler);
} else if (handler == null && this.logger.isTraceEnabled()) {
this.logger.trace("No handler mapping found for [" + lookupPath + "]");
}
return handler;
}
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
Object handler = this.handlerMap.get(urlPath); //直接从map中获取
if (handler != null) {
if (handler instanceof String) {
String handlerName = (String)handler;
handler = this.getApplicationContext().getBean(handlerName);
}
this.validateHandler(handler, request);
return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);//添加拦截器
} else {
List<String> matchingPatterns = new ArrayList(); //如果没找到就遍历所有的map的url,进行匹配
Iterator i$ = this.handlerMap.keySet().iterator();
while(i$.hasNext()) {
String registeredPattern = (String)i$.next();
if (this.getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
}
}
String bestPatternMatch = null;
Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
Collections.sort(matchingPatterns, patternComparator);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
}
bestPatternMatch = (String)matchingPatterns.get(); //如果有匹配的上的,取第一个
}
if (bestPatternMatch != null) {
handler = this.handlerMap.get(bestPatternMatch);
String pathWithinMapping;
if (handler instanceof String) {
pathWithinMapping = (String)handler;
handler = this.getApplicationContext().getBean(pathWithinMapping);
}
this.validateHandler(handler, request);
pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
Map<String, String> uriTemplateVariables = new LinkedHashMap();
Iterator i$ = matchingPatterns.iterator();
while(i$.hasNext()) {
String matchingPattern = (String)i$.next();
if (patternComparator.compare(bestPatternMatch, matchingPattern) == ) {
Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}
return this.buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
} else {
return null;
}
}
}
到此为止就找到了handler,并且添加了拦截器
Spring MVC的handlermapping之请求分发如何找到正确的Handler(BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping)的更多相关文章
- Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)
这个思路同样是通过在AbstractHandlerMethodMapping里面来实现getHandlerInternal()实现自己的方法来处理寻找正确的处理器,不懂得请看上一篇. protecte ...
- Spring MVC 原理探秘 - 一个请求的旅行过程
1.简介 在前面的文章中,我较为详细的分析了 Spring IOC 和 AOP 部分的源码,并写成了文章.为了让我的 Spring 源码分析系列文章更为丰富一些,所以从本篇文章开始,我将来向大家介绍一 ...
- Spring MVC体系结构和处理请求控制器
Spring MVC体系结构和处理请求控制器 一:MVC设计模式: (1.)数据访问接口:DAO层 (2.)处理业务逻辑层:Service层 (3.)数据实体:POJO (4.)负责前段请求接受并处理 ...
- Spring MVC的handlermapping之SimpleUrlHandlerMapping初始化
前面信息同BeanNameUrlHandlerMapping,这里不再过多分析,详情请看 :Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化 ...
- spring mvc 自定义Handlermapping
上次大概写了个可以解决velocity 多视图的东西. 但是实际运用过程中又到处找了些资料看了下.这里 小计下: DispatcherServlet解析过程: ..1..HandlerMapping. ...
- Spring MVC 梳理 - handlerMapping和handlerAdapter分析
参考图片 综上所述我们来猜测一下spring mvc 中根据URL找到处理器Controller中相应方法的流程 ①:获取Request的URL ②:从UrlLookup这个map中找到相应的requ ...
- spring mvc(4) HandlerMapping
在前面一节里提到,DispatcherServlet在接收到请求后,通过HandlerMapping找到处理请求对应的Controller(其实处理请求器并不一定是Controller,还可以是Htt ...
- Spring MVC:HandlerMapping
HandlerMapping 的类图 Spring中存在两种类型的handlers.第一种是 handler mappings(处理程序映射).它们的角色定位与前面所描述的功能完全相同.它们尝试将当前 ...
- Ajax+Spring MVC实现跨域请求(JSONP)JSONP 跨域
JSONP原理及实现 接下来,来实际模拟一个跨域请求的解决方案.后端为Spring MVC架构的,前端则通过Ajax进行跨域访问. 1.首先客户端需要注册一个callback(服务端通过该callba ...
随机推荐
- Python ---- list和dict遍历
refer to: http://www.cnblogs.com/icejoywoo/p/3531869.html 对于python3, 可能有不一样之处, refer to: http://do ...
- nats 学习 request/reply 模式基本使用
nats 一个云原生的消息系统,使用简单,客户端丰富,支持的模式是pub/sub 但是集成比较灵活,可以支持loadblance, request/reply pub/sub 代码演示的是reques ...
- redis Linux 、Windows ubuntu 下的安装
Redis 安装 2018-07-05 Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 ...
- pycharm修改代码模板支持中文输出
python2.x默认不支持中文输出,需要在py的开头添加 #coding: utf- 在pycharm里面,选项,editor,file and code templates,选择python sc ...
- emacs之配置php
php-setting.el (require 'php-mode) 以后丰富
- find 和 find_all 用法
soup = BeautifulSoup(requests.get(url).text, 'html.parser') soup.find('span', class_='item_hot_topic ...
- 八、jdk工具之JvisualVM、JvisualVM之二--Java程序性能分析工具Java VisualVM
目录 一.jdk工具之jps(JVM Process Status Tools)命令使用 二.jdk命令之javah命令(C Header and Stub File Generator) 三.jdk ...
- mysql 5.6.15升级到5.6.43
今天闲来无事,观察测试环境的zabbix服务器,发现内存泄漏严重,于是重启了,想起了前几天写的帖子发生了严重的内存泄漏可以把mysql升级到最新的小版本 于是乎就试着升级 old version:5. ...
- 在window的IIS中搭配Php的简单方法
在window的IIS中搭配Php的简单方法.搭配php的时候找到的一个超级简单方法 关键的核心是 PHP Manager for IIS 这是微软开发的一个项目,使用它可以在window下最方便简单 ...
- ElasticSearch 基础概念学习(未完)
1.基本定义 摘自百度百科 elasticseaElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elastic ...