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 ...
随机推荐
- Jenkins搭建windows service自动编译发布环境
类库项目(Task)部署 前面搭建了Web站点的环境,类库项目发布不同于站点项目,它只需要将MSBuild编译出来的dll复制到目标服务器上即可,而不需要通过Web Deploy,下面来说一下如何发布 ...
- Linux function: unshare
When a new process is created with the clone() system call, a set of flags is provided which tells t ...
- 转 HTTP/2: The Long-Awaited Sequel
HTTP/2: The Long-Awaited Sequel Thursday, October 9, 2014 2:01 AM 6 Ready to speed things up? Here a ...
- Outlook中在Exchange服务器无法保存邮件副本
最近帮同事设置Outlook2007,结果她直接登录公司网页Exchange,发现存在Exchange上的邮件副本全没了,原以为是Outlook邮箱账号设置里”保存服务器项副本“没打勾,后来才发现账号 ...
- centos下memcached安装
memcached是一款高速.分布式的内存缓存系统.其官方主页在http://www.danga.com/memcached/ 1.安装前的准备 要安装memcached,需要有libevent的支持 ...
- springMvc上传文件、读取zip/rar文件
参考文章: http://www.cnblogs.com/interdrp/p/6734033.html 方法一: 1)没有配置org.springframework.web.multipart.co ...
- native关键字(本地方法)、 java调用so动态链接库
Java native关键字 一. 什么是Native Method 简单地讲,一个Native Method就是一个java调用非java代码的接口.一个Native Method是这样一个ja ...
- JVM体系结构之三:方法区之2(jdk1.6,jdk1.7,jdk1.8下的方法区变迁)
方法区 方法区存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据.HotSpot中也称为永久代(Permanent Generation),(存储的是除了Java应用程序创建的对象之 ...
- POJ 2395 Out of Hay(求最小生成树的最长边+kruskal)
Out of Hay Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18472 Accepted: 7318 Descr ...
- 大白话系列之C#委托与事件讲解(序言)
声明:本系列非原创,因为太精彩才转载,如有侵权请通知删除,原文:http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1698795.html 在讲 ...