• HandlerMapping类是如何找到相应的controller呢?


    转自:

    HandlerMapping类是如何找到相应的controller呢?

    下文笔者讲述HandlerMapping类通过Mapping找到相应Controller的方法分享,如下所示:

    HandlerMapping在SpringMVC中的作用:
        完成url和Controller之间映射
    注意事项:
        当HandlerMapping的匹配关系无法满足我们的规则时,我们可实现HandlerMapping接口对其进行扩展
    

    HandlerMapping的组成部分

    HandlerMapping由:HandlerMapping映射注册、根据url获取对应的处理器、拦截器注册三部分组成

    HandlerMapping原理

    HandlerMapping接口定义

    package org.springframework.web.servlet;
    public interface HandlerMapping {
    	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
    }
    

    AbstractHandlerMapping实现接口

    AbstractHandlerMapping属性

    // order赋了最大值,优先级是最小的
    private int order = Integer.MAX_VALUE;  // default: same as non-Ordered
    // 默认的Handler,这边使用的Obejct,子类实现的时候,使用HandlerMethod,HandlerExecutionChain等
    private Object defaultHandler;
    // url计算的辅助类
    private UrlPathHelper urlPathHelper = new UrlPathHelper();
    // 基于ant进行path匹配,解决如/books/{id}场景
    private PathMatcher pathMatcher = new AntPathMatcher();
    // 拦截器配置:1,HandlerMapping属性设置;2,extendInterceptors设置
    private final Listinterceptors = new ArrayList();
    // 从interceptors中解析得到,直接添加给全部handler
    private final ListadaptedInterceptors = new ArrayList();
    // 使用前需要跟url进行匹配,匹配通过才会使用
    private final ListmappedInterceptors = new ArrayList();
    

    AbstractHandlerMapping拦截器初始化

    @Override
    protected void initApplicationContext() throws BeansException {
        extendInterceptors(this.interceptors);
        detectMappedInterceptors(this.mappedInterceptors);
        initInterceptors();
    }
    
    /**
     * 提供给子类扩展拦截器 
     */
    protected void extendInterceptors(Listinterceptors) {
    }
    
    /**
     * 扫描应用下的MappedInterceptor,并添加到mappedInterceptors
     */
    protected void detectMappedInterceptors(ListmappedInterceptors) {
        mappedInterceptors.addAll(
                BeanFactoryUtils.beansOfTypeIncludingAncestors(
                        getApplicationContext(),MappedInterceptor.class, true, false).values());
    }
    
    /**
     * 归集MappedInterceptor,并适配HandlerInterceptor和WebRequestInterceptor
     */
    protected void initInterceptors() {
        if (!this.interceptors.isEmpty()) {
            for (int i = 0; i < this.interceptors.size(); i++) { 
                Object interceptor = this.interceptors.get(i); 
                if (interceptor == null) { throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null"); } 
                if (interceptor instanceof MappedInterceptor) { mappedInterceptors.add((MappedInterceptor) interceptor); } 
                else { adaptedInterceptors.add(adaptInterceptor(interceptor)); } } } } 
    
    protected HandlerInterceptor adaptInterceptor(Object interceptor) { 
        if (interceptor instanceof HandlerInterceptor) { return (HandlerInterceptor) interceptor; } 
        else if (interceptor instanceof WebRequestInterceptor) { return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor); } 
        else { throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName()); } } 
    3. getHandler实现
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        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);
        }
        return getHandlerExecutionChain(handler, request);
    }
    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        HandlerExecutionChain chain =
            (handler instanceof HandlerExecutionChain) ?
                (HandlerExecutionChain) handler : new HandlerExecutionChain(handler);
    
        chain.addInterceptors(getAdaptedInterceptors());
    
        String lookupPath = urlPathHelper.getLookupPathForRequest(request);
        for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
            if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        }
    
        return chain;
    }
    
    封装拦截器到HandlerExecutionChain
    HandlerExecutionChain中只包含一个handler
    包含N个拦截器,把这个对象返回给了中央调度器
    其中adaptedInterceptors是直接添加
    mappedInterceptors需要根据url匹配通过后添加
    

    HandlerMapping总结

    HandlerMapping是处理器映射器
    根据请求找到处理器Handler
    但并不是简单的返回处理器
    而是将处理器和拦截器封装
    形成一个处理器执行链(HandlerExecuteChain)

  • 相关阅读:
    计算机毕业设计django基于python教学互动系统(源码+系统+mysql数据库+Lw文档)
    定点数原码二位乘法
    10 # 手写 every 方法
    计算思维相关书籍 计算机思维、数学思维与逻辑思维
    【动态规划】【C++算法】2742. 给墙壁刷油漆
    vue官方文档(18) :具名插槽示例
    Swingbench 压力测试(超详细)
    jQuery_DOM操作标签中的属性值和标签文本内容
    spring boot 接入prometheus+grafana监控API
    vue中el-table的行拖拽和el-dialog中表格的行拖拽
  • 原文地址:https://blog.csdn.net/qq_25073223/article/details/127829725