• 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)

  • 相关阅读:
    2022SDNU-ACM结训赛题解
    Java项目:SSM演唱会售票管理系统
    优秀智慧园区案例 - 三亚市崖州湾科技城智慧园区,先进智慧园区建设方案经验
    地理信息系统概论——知识点总结
    如何解决:navicat中Redis(本地主机:6379):连接被拒绝
    wangeditor5在vue3中的全使用过程(图片上传、附件上传、工具栏配置、编辑器配置)
    【mmWave】二、IWR6843ISK-ODS毫米波雷达【固件开发】流程
    D-Link确认数据泄露:员工成为钓鱼攻击受害者
    【vue】elmentUI封装自定义表单组件
    面试问烂了的Java线程池执行流程,具体的执行细节你还会吗?
  • 原文地址:https://blog.csdn.net/qq_25073223/article/details/127829725