Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)
这个思路同样是通过在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); //没找到子类已进行了复写
}
}
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)的更多相关文章
- Spring MVC的handlermapping之请求分发如何找到正确的Handler(BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping)
本文讲的是Spring MVC如何找到正确的handler, 前面请求具体怎么进入到下面的方法,不再细说. 大概就是Spring mvc通过servlet拦截请求,实现doService方法,然后进入 ...
- 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 ...
随机推荐
- 归并排序(C语言)
合并排序(MERGE SORT)是又一类不同的排序方法,合并的含义就是将两个或两个以上的有序数据序列合并成一个新的有序数据序列,因此它又叫归并算法. 它的基本思想就是假设数组A有N个元素,那么可以看成 ...
- 重新学习之spring第一个程序,配置IOC容器
第一步:导入相关jar包(此范例导入的是spring3.2.4版本,spring2.5版本只需要导入spring核心包即可) 第二步:在项目的src下配置applicationContext.xml的 ...
- baby用品
新生嬰兒用品清單 1.哺育用品: 大奶瓶:6支,240ml左右.選擇PC材質耐高溫120度,可消毒:玻璃材質建議選用印刷安全無鉛材料,可消毒. 小奶瓶:2-3支,120ml左右.寬口徑/一般口徑(喝水 ...
- JSP动作指令
JSP动作指令 动作指令与编译指令不间,编译指令是通知 Servlet 引擎的处理消息,而动作指令只是运行时的脚本动作.编译指令在将JSP 编译成 Servlet 时起作用:处理指令通常可替换成 Ja ...
- php变量的实现
1.php变量的实现 变量名 zval ,变量值 zend_value,php7的变量内存管理的引用计数 在zend_value结构上,变量的操作也都是zend_value实现的. //zend_ty ...
- [html][javascript] 正则匹配示例
var str="akdlfaklhello 1234klfd1441ksalfd9000kals8998j2345fd;lsa"; var reg = new RegExp(/( ...
- CentOS下长时间ping网络加时间戳并记录到文本
Linux下长时间ping网络加时间戳并记录到文本 由于一些原因,比如需要检查网络之间是否存在掉包等问题,会长时间去ping一个地址,由于会输出大量的信息而且最好要有时间戳,因此我们可以使用简单的 ...
- 常见的加密和解密算法—BASE64
一.BASE64加密和解密概述 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,Base64编码可用于在HTTP环境下传递较长的标识信息.例如,在Java Persistence系 ...
- mangle和demangle
转:https://www.cnblogs.com/robinex/p/7892795.html. mangle和demangle C/C++语言在编译以后,函数的名字会被编译器修改,改成编译器内部的 ...
- 使用sqoop从Oracle或mysql抽取数据到HDFS遇到的报错及解决
一.参考文档: 1.https://www.rittmanmead.com/blog/2014/03/using-sqoop-for-loading-oracle-data-into-hadoop-o ...