本文讲的是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)的更多相关文章

  1. Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)

    这个思路同样是通过在AbstractHandlerMethodMapping里面来实现getHandlerInternal()实现自己的方法来处理寻找正确的处理器,不懂得请看上一篇. protecte ...

  2. Spring MVC 原理探秘 - 一个请求的旅行过程

    1.简介 在前面的文章中,我较为详细的分析了 Spring IOC 和 AOP 部分的源码,并写成了文章.为了让我的 Spring 源码分析系列文章更为丰富一些,所以从本篇文章开始,我将来向大家介绍一 ...

  3. Spring MVC体系结构和处理请求控制器

    Spring MVC体系结构和处理请求控制器 一:MVC设计模式: (1.)数据访问接口:DAO层 (2.)处理业务逻辑层:Service层 (3.)数据实体:POJO (4.)负责前段请求接受并处理 ...

  4. Spring MVC的handlermapping之SimpleUrlHandlerMapping初始化

    前面信息同BeanNameUrlHandlerMapping,这里不再过多分析,详情请看 :Spring MVC的handlermapping之BeanNameUrlHandlerMapping初始化 ...

  5. spring mvc 自定义Handlermapping

    上次大概写了个可以解决velocity 多视图的东西. 但是实际运用过程中又到处找了些资料看了下.这里 小计下: DispatcherServlet解析过程: ..1..HandlerMapping. ...

  6. Spring MVC 梳理 - handlerMapping和handlerAdapter分析

    参考图片 综上所述我们来猜测一下spring mvc 中根据URL找到处理器Controller中相应方法的流程 ①:获取Request的URL ②:从UrlLookup这个map中找到相应的requ ...

  7. spring mvc(4) HandlerMapping

    在前面一节里提到,DispatcherServlet在接收到请求后,通过HandlerMapping找到处理请求对应的Controller(其实处理请求器并不一定是Controller,还可以是Htt ...

  8. Spring MVC:HandlerMapping

    HandlerMapping 的类图 Spring中存在两种类型的handlers.第一种是 handler mappings(处理程序映射).它们的角色定位与前面所描述的功能完全相同.它们尝试将当前 ...

  9. Ajax+Spring MVC实现跨域请求(JSONP)JSONP 跨域

    JSONP原理及实现 接下来,来实际模拟一个跨域请求的解决方案.后端为Spring MVC架构的,前端则通过Ajax进行跨域访问. 1.首先客户端需要注册一个callback(服务端通过该callba ...

随机推荐

  1. 《DSP using MATLAB》示例 Example 10.1

    坚持到第10章了,继续努力! 代码: %% ------------------------------------------------------------------------ %% Ou ...

  2. mysql 源代码目录及安装目录介绍

    1.源代码目录介绍: 1.BUILD    BUILD目录是编译.安装脚本目录,绝大部分以compile-开头,其中的SETUP.sh脚本为C和C++编译器设置了优化选项.2.client    cl ...

  3. js基础篇(dom操作,字符串,this等)

    首先我们来看这样一道题 <div id='foo' class='aa bb cc'></div>写出如何判断此div中是否含有aa(注:aa成立,aaa不成立) 首先,我们一 ...

  4. ruby的代码风格

    http://stylesror.github.io/ 大部分同意,有小部分,不敢苟同.

  5. 给iOS开发新手送点福利,简述UIPageControl的属性和用法

    UIPageControl 1.   numberOfPages // 设置有多少页 默认为0 [pageControl setNumberOfPages:kImageCount]; 2.   cur ...

  6. POI导出Excel和InputStream存储为文件

    POI导出Excel和InputStream存储为文件   本文需要说明的两个问题 InputStream如何保存到某个文件夹下 POI生成Excel POI操作utils类 代码如下.主要步骤如下: ...

  7. linux下python3离线加载nltk_data,不用nltk.download()

    在不能上网的服务器上把nltk_data关联到python3,已经安装anaconda3所以不需要安装nltk,环境是linux 首先没有nltk_data在使用nltk会报错 LookupError ...

  8. vim删除行首数字

  9. android手机 ping 虚拟机ubuntu的ip地址

    今天使用android手机往虚拟机上ubuntu 上搭建的nginx 和rtmp服务器推送东西的时候,怎么都推不上去. 后来在windows下的cmd里: # adb shell # ping 192 ...

  10. Ubuntu12.04编译vlc-android详细流程

    作者:wainiwann 出处:http://www.cnblogs.com/wainiwann/ 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...