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

     protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request); //同样从请求中获取url
if (this.logger.isDebugEnabled()) {
this.logger.debug("Looking up handler method for path " + lookupPath);
} HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);//查找handler
if (this.logger.isDebugEnabled()) {
if (handlerMethod != null) {
this.logger.debug("Returning handler method [" + handlerMethod + "]");
} else {
this.logger.debug("Did not find handler method for [" + lookupPath + "]");
}
} return handlerMethod != null ? handlerMethod.createWithResolvedBean() : null; //这块应该是为handler添加一些东西,参数等,
}
     protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList();
List<T> directPathMatches = (List)this.urlMap.get(lookupPath); //找到匹配url的匹配条件List
if (directPathMatches != null) {
this.addMatchingMappings(directPathMatches, matches, request); //添加匹配对象 Match实际上是匹配条件,和处理器的封装对象
} if (matches.isEmpty()) {
this.addMatchingMappings(this.handlerMethods.keySet(), matches, request);
} if (!matches.isEmpty()) {
Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request));
Collections.sort(matches, comparator);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
}
       //如果多个匹配条件,进行排序,子类自己实现比较方法,然后取第一个
AbstractHandlerMethodMapping<T>.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get();
if (matches.size() > ) { //如果存在两个复核条件的一样的处理器,则报错
AbstractHandlerMethodMapping<T>.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get();
if (comparator.compare(bestMatch, secondBestMatch) == ) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
}
} this.handleMatch(bestMatch.mapping, lookupPath, request); //实际上缓存到request域中 //这块子类也复写了,应该是多缓存了些东西
return bestMatch.handlerMethod;
} else {
return this.handleNoMatch(this.handlerMethods.keySet(), lookupPath, request); //没找到子类已进行了复写
}
}
 RequestMappingInfoHandlerMapping 中 handleNoMatch 的实现
     protected HandlerMethod handleNoMatch(Set<RequestMappingInfo> requestMappingInfos, String lookupPath, HttpServletRequest request) throws ServletException {
Set<String> allowedMethods = new HashSet();
Set<RequestMappingInfo> patternMatches = new HashSet();
Set<RequestMappingInfo> patternAndMethodMatches = new HashSet();
Iterator i$ = requestMappingInfos.iterator(); while(true) {
while(true) {
RequestMappingInfo info;
do {
if (!i$.hasNext()) {
if (patternMatches.isEmpty()) {
return null;
} if (patternAndMethodMatches.isEmpty() && !allowedMethods.isEmpty()) {
throw new HttpRequestMethodNotSupportedException(request.getMethod(), allowedMethods);
} Set consumableMediaTypes;
Set producibleMediaTypes;
if (patternAndMethodMatches.isEmpty()) {
consumableMediaTypes = this.getConsumableMediaTypes(request, patternMatches);
producibleMediaTypes = this.getProdicubleMediaTypes(request, patternMatches);
} else {
consumableMediaTypes = this.getConsumableMediaTypes(request, patternAndMethodMatches);
producibleMediaTypes = this.getProdicubleMediaTypes(request, patternAndMethodMatches);
} if (!consumableMediaTypes.isEmpty()) {
MediaType contentType = null;
if (StringUtils.hasLength(request.getContentType())) {
contentType = MediaType.parseMediaType(request.getContentType());
} throw new HttpMediaTypeNotSupportedException(contentType, new ArrayList(consumableMediaTypes));
} if (!producibleMediaTypes.isEmpty()) {
throw new HttpMediaTypeNotAcceptableException(new ArrayList(producibleMediaTypes));
} return null;
} info = (RequestMappingInfo)i$.next();
} while(info.getPatternsCondition().getMatchingCondition(request) == null); patternMatches.add(info);
if (info.getMethodsCondition().getMatchingCondition(request) != null) {
patternAndMethodMatches.add(info);
} else {
Iterator i$ = info.getMethodsCondition().getMethods().iterator(); while(i$.hasNext()) {
RequestMethod method = (RequestMethod)i$.next();
allowedMethods.add(method.name());
}
}
}
}
}

实际上这一步是又匹配了一遍,没有在返回空, 有的话 就报异常

Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)的更多相关文章

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

    本文讲的是Spring MVC如何找到正确的handler, 前面请求具体怎么进入到下面的方法,不再细说. 大概就是Spring mvc通过servlet拦截请求,实现doService方法,然后进入 ...

  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. Armadillo安装及使用

    以下转载自http://www.cnblogs.com/youthlion/archive/2012/05/15/2501465.html Armadillo是一个C++开发的线性代数库,在vs201 ...

  2. gpio_get_value的定义 (转)

    gpio_get_value等一系列函数,并非Linux标准函数,而是跟硬件相关的. 通常我们说的driver都是跟外围设备相关的,所以需要我们自己开发,但是这次我们说到的gpio是跟soc相关的,其 ...

  3. mysql索引优化续

    (1)索引类型: Btree索引:抽象的可以理解为“排好序的”快速查找结构myisam,innodb中默认使用Btree索引 hash索引:hash索引计算速度非常的快,但数据是随机放置的,无法对范围 ...

  4. linux svn soeasy

    http://blog.163.com/longsu2010@yeah/blog/static/173612348201202114212933/

  5. 学习笔记之Tips for Macbook

    写给Mac新手的入门指南 - 威锋网 https://mp.weixin.qq.com/s/pqmqGZhNwevx57KeLnzZmg https://bbs.feng.com/read-htm-t ...

  6. pythonNetday06

    进程 Process(target,name,args,kwargs) p.pid : 创建的新的进程的PID号 p.is_alive() 判断进程是否处于alive状态 p.daemon = Tru ...

  7. CentOS-7设置开机进入命令行界面(不进入图形界面)

    [root@localhost ~]# systemctl get-default graphical.target [root@localhost ~]# systemctl set-default ...

  8. springboot 邮件服务

    springboot仍然在狂速发展,才五个多月没有关注,现在看官网已经到1.5.3.RELEASE版本了.准备慢慢在写写springboot相关的文章,本篇文章使用springboot最新版本1.5. ...

  9. hive 创建/删除/截断 表(翻译自Hive wiki)

    这里罗列常用操作,更多参考 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL- ...

  10. Python Web框架——Flask

    简介 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理 ...