这个思路同样是通过在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. test20181020 B君的第一题

    题意 分析 二次剩余问题. x,y相当于二次方程 \[ x^2-bx+c=0 \mod{p} \] 的两根. 摸意义下的二次方程仍然考虑判别式\(\Delta=b^2-4c\). 它能开根的条件是\( ...

  2. 排列算法(reverse...rotate...next_permutation)

    #include <iostream> #include <algorithm> #include <cstring> using namespace std; i ...

  3. bzoj1925(SCOI2010)地精部落

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1925 要怎样才能想出正解呢? 当然有一维表示从1到 i . 发现最后是递增的方案数=最后是递 ...

  4. centos 6.5 下 安装 git

    2018-07-02 centos安装Git有两种方式,一种通过源安装,通过如下命今,即可一键安装成功: yum -y install git 但是通过源安装的Git,目前最高版本是1.7,想要使用更 ...

  5. codis须知

    codis是豌豆荚team出的一个redis集群,和官方的集群区别的地方在于 基于proxy,官方是基于gossip codis所有的读写都通过proxy,对于前端业务是透明的 官方的是读写发现在某个 ...

  6. 5月31日上课笔记-Mysql简介

    一.mysql 配置mysql环境变量 path中添加 D:\Program Files\MySQL\MySQL Server 5.7\bin cmd命令: 登录:mysql -uroot -p 退出 ...

  7. 管理Linux服务器的用户和组(续篇)

    用户切换 新建用户 useradd命令的选项 设置用户口令 passwd命令的选项 chage命令 修改用户帐户 禁用和恢复用户帐户 禁用和恢复用户帐户- Passwd命令 禁用和恢复用户帐户-直接修 ...

  8. modelsim 仿真xilinx fir ip

    到现在不管fir ip 用的对不对,但是在使用modelsim是可以仿真fir ip的. 具体步骤: 1.仿真库,添加到modelsim目录配置文件: 2.将这个文件中的: :List of dyna ...

  9. Python新利器之pipenv(转)

    pipenv 都包含什么? pipenv 是 Pipfile 主要倡导者.requests 作者 Kenneth Reitz 写的一个命令行工具,主要包含了Pipfile.pip.click.requ ...

  10. FoxPro 数据库文件及记录命令

    ADDTABLE 在当前数据库中添加一个自由表 APPEND 在表的末尾添加一个或多个新记录 APPEND FROM ARRAY 由数组添加记录到表中 APPEND FROM 从一个文件中读入记录,追 ...