资讯专栏INFORMATION COLUMN

SpringMVC之源码分析--HandlerMapping(三)

fsmStudy / 1723人阅读

摘要:与类图对比,类继承自抽象类,其又继承自抽象类,再往上继承关系与一致。创建初始化上一章我们分析了的创建初始化过程,的创建初始化过程与一样,方法的入口在抽象类中的方法。至此,代码编写完毕。

概述

本节我们继续分析HandlerMapping另一个实现类BeanNameUrlHandlerMapping,从类的名字可知,该类会根据请求的url与spring容器中定义的bean的name属性值进行匹配。

本系列文章是基于Spring5.0.5RELEASE。

类图

类的继承关系,如下图:

红框的类就是我们本章要分析的类。

与SimpleUrlHandlerMapping类图对比,BeanNameUrlHandlerMapping类继承自AbstractDetectingUrlHandlerMapping抽象类,其又继承自AbstractUrlHandlerMapping抽象类,再往上继承关系与SimpleUrlHandlerMapping一致。

创建/初始化

上一章我们分析了SimpleUrlHandlerMapping的创建初始化过程,BeanNameUrlHandlerMapping的创建初始化过程与SimpleUrlHandlerMapping一样,方法的入口在抽象类AbstractDetectingUrlHandlerMapping中的initApplicationContext()方法。调用原理参考https://segmentfault.com/a/1190000014951551

分析

AbstractDetectingUrlHandlerMapping

通过在应用程序上下文中对所有已定义的bean,检测handler与URL的映射。主要代码如下:

// 初始化容器上下文时调用
@Override
public void initApplicationContext() throws ApplicationContextException {
    // 调用父类AbstractHandlerMapping初始化拦截器,与SimpleUrlHandlerMapping一样
    super.initApplicationContext();
    // 处理url和bean name,具体注册调用父类AbstractUrlHandlerMapping类完成
    detectHandlers();
}

protected void detectHandlers() throws BeansException {
    // 获取应用上下文
    ApplicationContext applicationContext = obtainApplicationContext();
    if (logger.isDebugEnabled()) {
        logger.debug("Looking for URL mappings in application context: " + applicationContext);
    }
    // 获取上下文中定义的bean
    String[] beanNames = (this.detectHandlersInAncestorContexts ?
            BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) :
            applicationContext.getBeanNamesForType(Object.class));

    // Take any bean name that we can determine URLs for.
    for (String beanName : beanNames) {
        // 通过模板方法模式调用BeanNameUrlHandlerMapping子类处理
        String[] urls = determineUrlsForHandler(beanName);
        if (!ObjectUtils.isEmpty(urls)) {
            // 调用父类AbstractUrlHandlerMapping将url与handler存入map
            registerHandler(urls, beanName);
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Rejected bean name "" + beanName + "": no URL paths identified");
            }
        }
    }
}

BeanNameUrlHandlerMapping

实现HandlerMapping接口,将url与handler bean进行映射,bean的name属性需以"/"开头,源码如下:

@Override
protected String[] determineUrlsForHandler(String beanName) {
    List urls = new ArrayList<>();
    if (beanName.startsWith("/")) {
        urls.add(beanName);
    }
    String[] aliases = obtainApplicationContext().getAliases(beanName);
    for (String alias : aliases) {
        if (alias.startsWith("/")) {
            urls.add(alias);
        }
    }
    return StringUtils.toStringArray(urls);
}
实战

pom文件

引入Spring MVC支持,代码如下:


    org.springframework
    spring-webmvc
    5.0.5.RELEASE


    javax.servlet
    javax.servlet-api
    3.1.0
    provided

spring配置文件

新建spring MVC配置文件,代码如下:







    




web部署描述文件

配置Spring MVC 前端控制器DispatcherServlet,代码如下:



    Archetype Created Web Application
    
        
        dispatcher
        
        org.springframework.web.servlet.DispatcherServlet
        
        
            contextConfigLocation
            classpath:spring-servlet.xml
        
        
        
            detectAllHandlerMappings
            false
        
        
        1
        true
    
    
    
        
        dispatcher
        
        /
    

Handler控制器

编写Controller控制器,代码如下:

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DemoController implements Controller{

    @Nullable
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        request.getServletContext().log("进入Controller(Handler)处理器。。。" + this);

        return null;
    }
}

至此,代码编写完毕。

测试

启动程序,访问地址http://localhost:8087/demo,在控制台看到日志信息,说明验证成功。如下图:

总结

本文分析了BeanNameUrlHandlerMapping类,如果看过上篇文章就发现,SimpleUrlHandlerMapping与BeanNameUrlHandlerMapping都实现HandlerMapping接口,即处理url与handler的映射,只是处理的策略不同而已。

BeanNameUrlHanderlMapping有如下不足:

处理器bean的id/name为一个url请求路径,前面有"/",怪怪的;

如果多个url映射同一个处理器bean,那么就需要定义多个bean,导致容器创建多个处理器实例,占用内存空间;

处理器bean定义与url请求耦合在一起。

最后创建了qq群方便大家交流,可扫描加入,同时也可加我qq:276420284,共同学习、共同进步,谢谢!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69460.html

相关文章

  • SpringMVC源码分析--HandlerMapping(一)

    摘要:接口接口作用是将请求映射到处理程序,以及预处理和处理后的拦截器列表,映射是基于一些标准的,其中的细节因不同的实现而不相同。该参数是类型,作用是检查所有的映射解析器或使用或为的,默认为,即从上下文中检查所有的。 概述 在Spring MVC启动章节https://segmentfault.com/a/1190000014674239,介绍到了DispatcherServlet的onRef...

    ralap 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(五)

    摘要:概述通过前三章的分析,我们简要分析了和,但对拦截器部分做详细的分析,拦截器的加载和初始化是三个相同的部分。 概述 通过前三章的分析,我们简要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但对拦截器部分做详细的分析,拦截器的加载和初始化是三个HandlerMapping相...

    nanchen2251 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(六)

    摘要:概述上一节我们分析了的初始化过程,即创建并注册,本章我们分析下的请求处理过程,即查找。本系列文章是基于。最后创建了群方便大家交流,可扫描加入,同时也可加我,共同学习共同进步,谢谢 概述 上一节我们分析了RequestMappingHandlerMapping的初始化过程,即创建并注册HandlerMehtod,本章我们分析下RequestMappingHandlerMapping的请求...

    BDEEFE 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(二)

    摘要:由于抽象类重写了父类的方法,所以此时会调用的方法,在该方法中通过调用父类的方法,该方法通过模板方法模式最终调到类的方法。分析该类间接实现了接口,直接实现该接口的是抽象类,映射与请求。 概述 在前一章https://segmentfault.com/a/1190000014901736的基础上继续分析,主要完成SimpleUrlHandlerMapping类的原理。 本系列文章是基于Sp...

    Imfan 评论0 收藏0
  • SpringMVC源码分析--HandlerAdapter(

    摘要:概述回顾上两章,我们主要分析了的概念作业以及如何使用的组件,本节以及后续几章,将介绍为我们提供的的具体实现类,基于源码和设计层面进行介绍,欢迎大家关注。本系列文章是基于。 概述 回顾上两章,我们主要分析了HandlerAdapter的概念、作业以及Spring MVC如何使用的HandlerAdapter组件,本节以及后续几章,将介绍Spring为我们提供的HandlerAdapter...

    Dionysus_go 评论0 收藏0

发表评论

0条评论

fsmStudy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<