Spring MVC的handlermapping之请求分发如何找到正确的Handler(BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping)
本文讲的是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)的更多相关文章
- Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)
这个思路同样是通过在AbstractHandlerMethodMapping里面来实现getHandlerInternal()实现自己的方法来处理寻找正确的处理器,不懂得请看上一篇. protecte ...
- 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 ...
随机推荐
- 利用Web Services开发分布式应用
一.引言 在前面文章中分别介绍了MSMQ和.NET Remoting技术,今天继续分享.NET 平台下另一种分布式技术——Web Services 二.Web Services 详细介绍 2.1 We ...
- Html页面Dom对象之Event
HTML DOM Event 对象 实例 哪个鼠标按钮被点击? 光标的坐标是? 被按的按键的 unicode 是? 相对于屏幕,光标的坐标是? shift 键被按了吗? 哪个元素被点击了? 哪个事件类 ...
- flow flow-typed 定义简单demo
flow-typed 安装 全局 npm install -g flow-typed 测试代码 一个简单全局函数 目录根目录 flow-typed userLibDef.js declare func ...
- Python学习思维导图
刚学习Python时,边学边总结的,采用思维导图的形式, 适合回顾使用.内容参考<Python:从入门到实践>一书. 再给出一张Datacamp网站上的一张关于Python基础的总结 ...
- baby用品
新生嬰兒用品清單 1.哺育用品: 大奶瓶:6支,240ml左右.選擇PC材質耐高溫120度,可消毒:玻璃材質建議選用印刷安全無鉛材料,可消毒. 小奶瓶:2-3支,120ml左右.寬口徑/一般口徑(喝水 ...
- Chrome 解决flash问题
Chrome 无法显示使用插件的内容 Chrome 不再支持很多插件.不过网站创建者已经通过更安全的方式,将多数这类功能添加到 Chrome 中. 为什么 NPAPI 插件现在无法正常运行过去,许多插 ...
- QT:QByteArray和QByteArray、char *(转)
//常用参数类型:char *字符串, QByteArray字符数组, QString字符串//需要转换:char * ---转--- QByteArray ---需要调用QByteArray类的构造 ...
- Linux下用文件IO的方式操作GPIO(/sys/class/gpio)(转)
通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction ...
- BeagleBoneBlack Linux开发相关链接收藏
ubuntu挂载vdi文件 官方linux代码地址 官方devicetree代码地址 [转]使用BBB的device tree和cape(重新整理版) iio: input: ti_am335x_ad ...
- 学习blus老师js(2)--深入JavaScript
1.函数传参 可变参(不定参):arguments 参数的个数可变,参数数组 例1.求和 求所有参数的和 <!DOCTYPE HTML> <html> <head&g ...