spring mvc

RequestMappingHandlerMapping初始化

最近想弄清楚spring mvc的调用过程,想到怎么样根据url访问到对应的method,于是看了下spring mvc的相关源码,在此分析下。
找到 RequestMappingHandlerMapping 类,可以看到实现了InitializingBean接口。
类继承关系图

找到 RequestMappingHandlerMapping 的afterPropertiesSet() 方法

public void afterPropertiesSet() {
        this.config = new BuilderConfiguration();
        this.config.setUrlPathHelper(this.getUrlPathHelper());
        this.config.setPathMatcher(this.getPathMatcher());
        this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
        this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
        this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
        this.config.setContentNegotiationManager(this.getContentNegotiationManager());
       //调用AbstractHandlerMethodMapping afterPropertiesSet()方法
        super.afterPropertiesSet();
}

AbstractHandlerMethodMapping 的afterPropertiesSet()方法

 public void afterPropertiesSet() {
        //初始化控制层方法
        this.initHandlerMethods();
    }

initHandlerMethods()

protected void initHandlerMethods() {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Looking for request mappings in application context: " + this.getApplicationContext());
        }

       //获取spring mvc 容器注册的bean名称
        String[] beanNames = this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.getApplicationContext(), Object.class) : this.getApplicationContext().getBeanNamesForType(Object.class);
        String[] var2 = beanNames;
        int var3 = beanNames.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String beanName = var2[var4];
            if (!beanName.startsWith("scopedTarget.")) {
                Class beanType = null;
                try {
                    beanType = this.getApplicationContext().getType(beanName);
                } catch (Throwable var8) {
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Could not resolve target class for bean with name '" + beanName + "'", var8);
                    }
                }
                //判断controller 类是否带有@Controller 或者@RequestMapping注解
                if (beanType != null && this.isHandler(beanType)) {
                    this.detectHandlerMethods(beanName);
                }
            }
        }

        this.handlerMethodsInitialized(this.getHandlerMethods());
    }

detectHandlerMethods(Object handler)

protected void detectHandlerMethods(Object handler) {
        Class<?> handlerType = handler instanceof String ? this.getApplicationContext().getType((String)handler) : handler.getClass();
        final Class<?> userType = ClassUtils.getUserClass(handlerType);
        //获取所有userType带有@RequestMapping注解的方法  Map<Method,RequestMappingInfo>
        Map<Method, T> methods = MethodIntrospector.selectMethods(userType, new MetadataLookup<T>() {
            public T inspect(Method method) {
                try {
                    return AbstractHandlerMethodMapping.this.getMappingForMethod(method, userType);
                } catch (Throwable var3) {
                    throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, var3);
                }
            }
        });
        if (this.logger.isDebugEnabled()) {
            this.logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
        }

        Iterator var5 = methods.entrySet().iterator();

        while(var5.hasNext()) {
            Entry<Method, T> entry = (Entry)var5.next();
            Method invocableMethod = AopUtils.selectInvocableMethod((Method)entry.getKey(), userType);
            T mapping = entry.getValue();
            //将
            this.registerHandlerMethod(handler, invocableMethod, mapping);
        }

    }


AbstractHandlerMethodMapping内部类MappingRegistry,这个是核心类,所有的路径相关信息全部存放在MappingRegistry中。
registry:key为RequestMapping,value为MappingRegistration;
mappingLookup:key为RequestMapping,value为HandlerMethod;
urlLookup:key为url,value为RequestMappingInfo;
nameLookup:key为mappingName,value为List;
corsLookup:key为HandlerMethod,value为CorsConfiguration;

class MappingRegistry {
        //(RequestMappingInfo,MappingRegistration)
        private final Map<T, AbstractHandlerMethodMapping.MappingRegistration<T>> registry = new HashMap();
        // (RequestMappingInfo,HandlerMethod)
        private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap();
        // (url,RequestMappingInfo)
        private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap();
        //(mappingName,List<HandlerMethod>)
        private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap();
        //跨域信息(HandlerMethod,CorsConfiguration)
        private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap();
        //读写锁
        private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  }

AbstractHandlerMethodMapping内部类MappingRegistration


private static class MappingRegistration<T> {
        //RequestMappingInfo
        private final T mapping;
        //HandlerMethod
        private final HandlerMethod handlerMethod;
        //requestMapping路径 /user/create
        private final List<String> directUrls;
        //例如类名为UserController的create方法, 则mappingName 为 UC#create , UC为类名的大写字母
        private final String mappingName;

        public MappingRegistration(T mapping, HandlerMethod handlerMethod, List<String> directUrls, String mappingName) {
            Assert.notNull(mapping, "Mapping must not be null");
            Assert.notNull(handlerMethod, "HandlerMethod must not be null");
            this.mapping = mapping;
            this.handlerMethod = handlerMethod;
            this.directUrls = directUrls != null ? directUrls : Collections.emptyList();
            this.mappingName = mappingName;
        }
    }

registerHandlerMethod(Object handler, Method method, T mapping)

protected void registerHandlerMethod(Object handler, Method method, T mapping) {
        this.mappingRegistry.register(mapping, handler, method);
}

mappingRegistry 的 register(T mapping, Object handler, Method method)

public void register(T mapping, Object handler, Method method) {
            this.readWriteLock.writeLock().lock();
            try {
               //构造HandlerMethod
                HandlerMethod handlerMethod = AbstractHandlerMethodMapping.this.createHandlerMethod(handler, method);
               //校验 mappingLookup 是否已经存在key为mapping的记录,也就是校验是否存在两个相同的url
                this.assertUniqueMethodMapping(handlerMethod, mapping);
                if (AbstractHandlerMethodMapping.this.logger.isInfoEnabled()) {
                    AbstractHandlerMethodMapping.this.logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
                }

               //**mappingLookup存放(RequestMappingInfo,HandlerMethod)**
                this.mappingLookup.put(mapping, handlerMethod);
                // url  例如: /user/create
                List<String> directUrls = this.getDirectUrls(mapping);
                Iterator var6 = directUrls.iterator();

                while(var6.hasNext()) {
                    String url = (String)var6.next();
                    // **urlLookup (url,RequestMappingInfo)**
                    this.urlLookup.add(url, mapping);
                }

                String name = null;
                if (AbstractHandlerMethodMapping.this.getNamingStrategy() != null) {
                    name = AbstractHandlerMethodMapping.this.getNamingStrategy().getName(handlerMethod, mapping);
                   // **nameLookup (name,List<HandlerMethod>)**
                    this.addMappingName(name, handlerMethod);
                }
  				  // Cors 跨域访问的处理
                CorsConfiguration corsConfig = AbstractHandlerMethodMapping.this.initCorsConfiguration(handler, method, mapping);
                if (corsConfig != null) {
                   //**corsLookup(HandlerMethod,CorsConfiguration)**
                    this.corsLookup.put(handlerMethod, corsConfig);
                }
                //**registry (RequestMappingInfo,MappingRegistration)**
                this.registry.put(mapping, new AbstractHandlerMethodMapping.MappingRegistration(mapping, handlerMethod, directUrls, name));
            } finally {
                this.readWriteLock.writeLock().unlock();
            }
        }

FrameworkServlet 类有一个监听器内部类

//在初始化容器时,AbstractApplicationContext 的refresh()方法里,调用 finishRefresh()方法,
private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
        private ContextRefreshListener() {
        }
        public void onApplicationEvent(ContextRefreshedEvent event) {
            FrameworkServlet.this.onApplicationEvent(event);
        }
    }

public void onApplicationEvent(ContextRefreshedEvent event) {
        this.refreshEventReceived = true;
        this.onRefresh(event.getApplicationContext());
    }

**

spring mvc 处理过程

**
DispatcherServlet是spring mvc 前端控制器,是spring mvc的核心类,其继承关系图如下所示。
DispatcherServlet类继承图
tomcat 启动时,会调用init()方法初始化spring mvc容器,其初始化容器过程,和初始化spring 容器类似,最终都是调用AbstractApplicationContext 的 refresh()方法,具体过程可以参考:https://mp.csdn.net/mdeditor/89609303

访问路径会调用doService方法

doService(HttpServletRequest request, HttpServletResponse response)

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (this.logger.isDebugEnabled()) {
            String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
            this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
        }

        Map<String, Object> attributesSnapshot = null;
        if (WebUtils.isIncludeRequest(request)) {
            attributesSnapshot = new HashMap();
            Enumeration attrNames = request.getAttributeNames();

            label108:
            while(true) {
                String attrName;
                do {
                    if (!attrNames.hasMoreElements()) {
                        break label108;
                    }

                    attrName = (String)attrNames.nextElement();
                } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));

                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }

        /**
        * 设置request attribute属性
        */

        request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
        request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
        request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
        FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
        if (inputFlashMap != null) {
            request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
        }

        request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
        request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

        try {
            //spring mvc 工作处理过程
            this.doDispatch(request, response);
        } finally {
            if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
                this.restoreAttributesAfterInclude(request, attributesSnapshot);
            }
        }
    }

doDispatch(HttpServletRequest request, HttpServletResponse response)

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            try {
                ModelAndView mv = null;
                Object dispatchException = null;

                try {
                    //校验请求contentType是否为multipart/**
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    //根据url 从
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }

                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                        }

                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }

                   //拦截器preHandle处理,如果有一个拦截器的preHandle()方法返回为false,则直接返回退出
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }

                    //处理@RequestMapping的方法
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                   //设置默认视图名称
                    this.applyDefaultViewName(processedRequest, mv);
                    
                    //处理拦截器postHandle方法,返回ModelAndView
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }
                //异常处理
                //视图解析
                // 处理拦截器afterCompletion方法
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
            } catch (Exception var22) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
            } catch (Throwable var23) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
            }

        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response)

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //获取所有的拦截器
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            //按照顺序调用拦截器preHandle方法,并且记录interceptorIndex,
            //只要返回值为false,则调用 triggerAfterCompletion()方法,也就是调用拦截器的afterCompletion()方法
            for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
                HandlerInterceptor interceptor = interceptors[i];
                if (!interceptor.preHandle(request, response, this.handler)) {
                    this.triggerAfterCompletion(request, response, (Exception)null);
                    return false;
                }
            }
        }
        return true;
    }

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv)

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            //逆向调用拦截器postHandle方法
            for(int i = interceptors.length - 1; i >= 0; --i) {
                HandlerInterceptor interceptor = interceptors[i];
                interceptor.postHandle(request, response, this.handler, mv);
            }
        }
    }

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
        HandlerInterceptor[] interceptors = this.getInterceptors();
        if (!ObjectUtils.isEmpty(interceptors)) {
            //从preHandle()返回false的那个拦截器的interceptorIndex,逆向调用afterCompletion()方法
            for(int i = this.interceptorIndex; i >= 0; --i) {
                HandlerInterceptor interceptor = interceptors[i];
                try {
                    interceptor.afterCompletion(request, response, this.handler, ex);
                } catch (Throwable var8) {
                    logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
                }
            }
        }
    }
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
        boolean errorView = false;
        if (exception != null) {
            if (exception instanceof ModelAndViewDefiningException) {
                this.logger.debug("ModelAndViewDefiningException encountered", exception);
                mv = ((ModelAndViewDefiningException)exception).getModelAndView();
            } else {
                Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
                mv = this.processHandlerException(request, response, handler, exception);
                errorView = mv != null;
            }
        }

        if (mv != null && !mv.wasCleared()) {
            this.render(mv, request, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        } else if (this.logger.isDebugEnabled()) {
            this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling");
        }

        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
            }

        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值