本文讲的是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)的更多相关文章

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

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

  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. 利用Web Services开发分布式应用

    一.引言 在前面文章中分别介绍了MSMQ和.NET Remoting技术,今天继续分享.NET 平台下另一种分布式技术——Web Services 二.Web Services 详细介绍 2.1 We ...

  2. Html页面Dom对象之Event

    HTML DOM Event 对象 实例 哪个鼠标按钮被点击? 光标的坐标是? 被按的按键的 unicode 是? 相对于屏幕,光标的坐标是? shift 键被按了吗? 哪个元素被点击了? 哪个事件类 ...

  3. flow flow-typed 定义简单demo

    flow-typed 安装 全局 npm install -g flow-typed 测试代码 一个简单全局函数 目录根目录 flow-typed userLibDef.js declare func ...

  4. Python学习思维导图

     刚学习Python时,边学边总结的,采用思维导图的形式, 适合回顾使用.内容参考<Python:从入门到实践>一书.   再给出一张Datacamp网站上的一张关于Python基础的总结 ...

  5. baby用品

    新生嬰兒用品清單 1.哺育用品: 大奶瓶:6支,240ml左右.選擇PC材質耐高溫120度,可消毒:玻璃材質建議選用印刷安全無鉛材料,可消毒. 小奶瓶:2-3支,120ml左右.寬口徑/一般口徑(喝水 ...

  6. Chrome 解决flash问题

    Chrome 无法显示使用插件的内容 Chrome 不再支持很多插件.不过网站创建者已经通过更安全的方式,将多数这类功能添加到 Chrome 中. 为什么 NPAPI 插件现在无法正常运行过去,许多插 ...

  7. QT:QByteArray和QByteArray、char *(转)

    //常用参数类型:char *字符串, QByteArray字符数组, QString字符串//需要转换:char * ---转--- QByteArray ---需要调用QByteArray类的构造 ...

  8. Linux下用文件IO的方式操作GPIO(/sys/class/gpio)(转)

    通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction ...

  9. BeagleBoneBlack Linux开发相关链接收藏

    ubuntu挂载vdi文件 官方linux代码地址 官方devicetree代码地址 [转]使用BBB的device tree和cape(重新整理版) iio: input: ti_am335x_ad ...

  10. 学习blus老师js(2)--深入JavaScript

    1.函数传参 可变参(不定参):arguments 参数的个数可变,参数数组   例1.求和 求所有参数的和 <!DOCTYPE HTML> <html> <head&g ...