Spring MVC-HandlerMapping

Spring MVC 使用HandlerMapping来找到并保存url请求和处理函数间的mapping关系。
以DefaultAnnotationHandlerMapping为例来具体看HandlerMapping的作用
DefaultAnnotationHandlerMapping将扫描当前所有已经注册的spring beans中的@requestmapping标注以找出url 和 handler method处理函数的关系并予以关联。
一般我们都是用Spring中配置的默认的HandlerMapping:BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping,下面我们就分析这两个类的源代码。

  • BeanNameUrlHandlerMapping
    首先看这个类的继承关系
    这里写图片描述
    对于《接口——抽象类——实现类》这种代码书写风格在Spring中到处可见,很简单,接口就是对使用者声明的服务,声明了是一定要实现。下面的所有类(抽象的、具体的)都是为了实现接口中方法而设计的。
    抽象类是为了将具体类中的公共的部分抽离出来——代码的复用。
    那么分析这种结构就从接口中声明的方法一点一点往类中渗透,HandlerMapping中声明的方法是HandlerExecutionChain getHandler(HttpServletRequest request),首先看第一级抽象继承类AbstractHandlerMapping中默认实现,这个类中有存放【拦截器】的成员变量List interceptors
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        //这里根据request中的参数得到其对应的handler,具体处理在AbstractUrlHandlerMapping中 
        Object handler = getHandlerInternal(request);
        if (handler == null) {
            handler = getDefaultHandler();
        }
        if (handler == null) {
            return null;
        }
        // Bean name or resolved handler?
        if (handler instanceof String) {
            String handlerName = (String) handler;
            handler = getApplicationContext().getBean(handlerName);
        }
        //生成一个HandlerExecutionChain,其中放了我们匹配上的handler和定义好的拦截器,就像我们在HandlerExecutionChain中看到的那样,它持有一个handler和一个拦截器组。  
        return getHandlerExecutionChain(handler, request);
}

通过代码我们知道关键代码是Object handler = getHandlerInternal(request);这个方法具体实现是在接口的二级抽象子类AbstractUrlHandlerMapping,这个类中有存放【request请求和Handler的映射关系】的成员变量Map handlerMap
找到关键性代码:

// 这里使用模式来对map中的所有handler进行匹配,调用了Jre中的Matcher类来完成匹配处理。          
List<String> matchingPatterns = new ArrayList<String>();           
for (String registeredPattern : this.handlerMap.keySet()) {        
    if (getPathMatcher().match(registeredPattern, urlPath)) {      
        matchingPatterns.add(registeredPattern);                   
    }                                                              
} 
………………………………
//这里根据匹配路径找到最象的一个
if (bestPatternMatch != null) {
    handler = this.handlerMap.get(bestPatternMatch);  
………………………………
return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);                                                               

至此你需要的接口中声明的方法返回的HandlerExecutionChain已经得到,那么大家一定会问,对于第三四级继承AbstractDetectingUrlHandlerMapping和BeanNameUrlHandlerMapping是做什么用的。他们的作用就是侦测Spring的bean工厂中的所有的handler存储到AbstractUrlHandlerMapping的成员变量Map handlerMap中。存储的方法是registerHandler(String urlPath, Object handler)

if (urlPath.equals("/")) {                                                                                                                    
    setRootHandler(resolvedHandler);                                      
}
else if (urlPath.equals("/*")) {                                                                                                                      
    setDefaultHandler(resolvedHandler);                                        
} 
else {                                              
     //把url和handler的对应关系放到handlerMap中去             
    this.handlerMap.put(urlPath, resolvedHandler); 
    ……………………                                                                                                                                                       

至此HandlerMapping的解析完成,但是我们发现这个类的继承关系类中都是从bean工厂直接得到handler,那么这些handler是什么时候放到bean工厂的那?这就要在《Spring IOC》相关文章中分享。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值