• handlerMapping的初始化以及查找handler


    前提:HttpServletBean初始化了一些servlet配置,接着FrameWorkServlet创建了WebApplicationContext,最后DispatcherServlet初始化一些解析器,mapping(九大组件)。
    
    一、从DispatcherServlet的doDispatch开始。
    但WebApplicationContext加载完毕后FrameWorkdServlet调用DispatcherServlet的onRefresh方法
    @Override
        protected void onRefresh(ApplicationContext context) {
            initStrategies(context);
        }
    initStrategies方法如下:
    protected void initStrategies(ApplicationContext context) {
            initMultipartResolver(context);
            initLocaleResolver(context);
            initThemeResolver(context);
            initHandlerMappings(context);
            initHandlerAdapters(context);
            initHandlerExceptionResolvers(context);
            initRequestToViewNameTranslator(context);
            initViewResolvers(context);
            initFlashMapManager(context);
        }
    这里初始化了九大组件,如果在初始化组件的时候没有明确规定使用那个组件时,会使用默认策略。
    
    现在我们只关心initHandlerMappings(context);这个方法
    private void initHandlerMappings(ApplicationContext context) {
            this.handlerMappings = null;
    
            if (this.detectAllHandlerMappings) {
                // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
    //从applicationContext获取HandlerMapping.class类型的bean
                Map<String, HandlerMapping> matchingBeans =
                        BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
                if (!matchingBeans.isEmpty()) {
                    this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
                    // We keep HandlerMappings in sorted order.
                    AnnotationAwareOrderComparator.sort(this.handlerMappings);
                }
            }
            else {
                try {
                    HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
                    this.handlerMappings = Collections.singletonList(hm);
                }
                catch (NoSuchBeanDefinitionException ex) {
                    // Ignore, we'll add a default HandlerMapping later.
                }
            }
    
            // Ensure we have at least one HandlerMapping, by registering
            // a default HandlerMapping if no other mappings are found.
            if (this.handlerMappings == null) {
                this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
                if (logger.isDebugEnabled()) {
                    logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
                }
            }
        }
    
    将找到的HandlerMapping全部存到DispatcherServlet的this.handlerMappings中
    
    二、doDispatch方法
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            HttpServletRequest processedRequest = request;
            HandlerExecutionChain mappedHandler = null;
            boolean multipartRequestParsed = false;
    
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
            try {
                ModelAndView mv = null;
                Exception dispatchException = null;
    
                try {
                    processedRequest = checkMultipart(request);
                    multipartRequestParsed = (processedRequest != request);
    
                    // Determine handler for the current request.通过request获取HandlerExecutionChain,这个执行链中保存了handler和需要做拦截的拦截器
                    mappedHandler = getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
    
                    // Determine handler adapter for the current request.通过handler寻找能够处理这个handler的handlerAdapter。
                    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
                    // Process last-modified header, if supported by the handler.
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (logger.isDebugEnabled()) {
                            logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                        }
                        if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
    
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
    
                    // Actually invoke the handler.
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                }
                catch (Exception ex) {
                    dispatchException = ex;
                }
                processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
            }
            catch (Exception ex) {
                triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
            }
            catch (Error err) {
                triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
            }
            finally {
                if (asyncManager.isConcurrentHandlingStarted()) {
                    // Instead of postHandle and afterCompletion
                    if (mappedHandler != null) {
                        mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                    }
                }
                else {
                    // Clean up any resources used by a multipart request.
                    if (multipartRequestParsed) {
                        cleanupMultipart(processedRequest);
                    }
                }
            }
        }
    
    
    来看看getHandler方法
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            for (HandlerMapping hm : this.handlerMappings) {
                if (logger.isTraceEnabled()) {
                    logger.trace(
                            "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
                }
    //遍历所有的HandlerMapping,如果这个handlerMapping能够找到handler,那么就会返回
                HandlerExecutionChain handler = hm.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
            return null;
        }
    
    
    //调用handlerMpping的getHandler方法
    @Override
        public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    //调用模板方法getHandlerInternal,这个方法由子类实现
            Object handler = getHandlerInternal(request);
            if (handler == null) {
                handler = getDefaultHandler();
            }
            if (handler == null) {
                return null;
            }
            // Bean name or resolved handler?如果是String类型就从applicationContext中查找
            if (handler instanceof String) {
                String handlerName = (String) handler;
                handler = getApplicationContext().getBean(handlerName);
            }
    //获取处理器链,内部在构造HandlerExecutionChain的同时会查找符合条件的拦截器
            HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
            if (CorsUtils.isCorsRequest(request)) {
                CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
                CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
                CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
                executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
            }
            return executionChain;
        }
    
    
    
    AbstractHandlerMethodMapping的继承结构:
    
    这个处理器映射是用来查找方法处理器
    
    AbstractUrlHandlerMapping:
    
    这种处理器是通过url来查找handler的,比如我们在配置文件中配置
    <bean name=''/index" class="com.test.indexContrller" />
    它的url是/index,如果有比较复杂的,那么就会使用PatchMatcher来匹配url,如果匹配就返回对应的handler。
    
    @Override
        public void initApplicationContext() throws BeansException {
            super.initApplicationContext();
            registerHandlers(this.urlMap);
        }
    
    初始化initApplicationContext方法初始化了一些拦截器。
    registerHandlers注册了处理器。
    
    protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
            if (urlMap.isEmpty()) {
                logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
            }
            else {
                for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
                    String url = entry.getKey();
                    Object handler = entry.getValue();
                    // Prepend with slash if not already present.
                    if (!url.startsWith("/")) {
                        url = "/" + url;
                    }
                    // Remove whitespace from handler bean name.
                    if (handler instanceof String) {
                        handler = ((String) handler).trim();
                    }
                    registerHandler(url, handler);
                }
            }
        }
    
    
    
    protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
            Assert.notNull(urlPath, "URL path must not be null");
            Assert.notNull(handler, "Handler object must not be null");
            Object resolvedHandler = handler;
    
            // Eagerly resolve handler if referencing singleton via name.
            if (!this.lazyInitHandlers && handler instanceof String) {
                String handlerName = (String) handler;
                if (getApplicationContext().isSingleton(handlerName)) {
                    resolvedHandler = getApplicationContext().getBean(handlerName);
                }
            }
    
            Object mappedHandler = this.handlerMap.get(urlPath);
            if (mappedHandler != null) {
                if (mappedHandler != resolvedHandler) {
                    throw new IllegalStateException(
                            "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
                            "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
                }
            }
            else {
                if (urlPath.equals("/")) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Root mapping to " + getHandlerDescription(handler));
                    }
                    setRootHandler(resolvedHandler);
                }
                else if (urlPath.equals("/*")) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Default mapping to " + getHandlerDescription(handler));
                    }
                    setDefaultHandler(resolvedHandler);
                }
                else {
                    this.handlerMap.put(urlPath, resolvedHandler);
                    if (logger.isInfoEnabled()) {
                        logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
                    }
                }
            }
        }
    
    以UrlPath handler的方式存入map。
    
    
    @Override
        protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
    //获取出去了ContextPath的uri
            String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
            Object handler = lookupHandler(lookupPath, request);
            if (handler == null) {
                // We need to care for the default handler directly, since we need to
                // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
                Object rawHandler = null;
    //如果是web Contextpath的根路径就直接获取根处理器,这个处理器在registHandler方法时就set进去了
                if ("/".equals(lookupPath)) {
                    rawHandler = getRootHandler();
                }
                if (rawHandler == null) {
                    rawHandler = getDefaultHandler();
                }
                if (rawHandler != null) {
                    // Bean name or resolved handler?
                    if (rawHandler instanceof String) {
                        String handlerName = (String) rawHandler;
                        rawHandler = getApplicationContext().getBean(handlerName);
                    }
    //检验处理器,比如检验请求方法,看看是不是支持的请求方法。
                    validateHandler(rawHandler, request);
    //
                    handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
                }
            }
            if (handler != null && logger.isDebugEnabled()) {
                logger.debug("Mapping [" + lookupPath + "] to " + handler);
            }
            else if (handler == null && logger.isTraceEnabled()) {
                logger.trace("No handler mapping found for [" + lookupPath + "]");
            }
            return handler;
        }
    
    
    buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);方法是这样的,设置了一些拦截器
    protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
                String pathWithinMapping, Map<String, String> uriTemplateVariables) {
    
            HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
            chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
            if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
                chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
            }
            return chain;
        }
    
    
    查找到handler后通过handler去寻找匹配的handlerAdapter,像simpleHandlerMapping弄出来的handler,其对应的adapter是SimpleControllerHandlerAdapter
    
    它有个方法:@Override
        public boolean supports(Object handler) {
            return (handler instanceof Controller);
        }
    从这里可以看到它只支持实现了Controller的类。
    看到这里其实我们也可以定义自己的HandlerMapping,实现getHandlerInterna方法,从applicationContext中寻找,加入我们自定义一个借口叫做IController
    
    package com.booway.custominterface;
    
    import org.springframework.web.servlet.ModelAndView;
    
    public interface IController {
    
        public ModelAndView IHandlerRequest() throws Exception;
        
    }
    
    定义一个HandlerMapping
    
    package com.booway.customhandlermapping;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.util.PathMatcher;
    import org.springframework.web.servlet.handler.AbstractHandlerMapping;
    
    import com.booway.custominterface.IController;
    
    public class ISimapleHandlerMapping extends AbstractHandlerMapping {
    
        @Override
        protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
            String[] beanNames = super.getApplicationContext().getBeanNamesForType(IController.class);
            String lookupPath = super.getUrlPathHelper().getLookupPathForRequest(request);
            PathMatcher pathMatcher = getPathMatcher();
            for (String beanName : beanNames) {
                if(pathMatcher.match(beanName, lookupPath))
                {
                    return super.getApplicationContext().getBean(beanName);
                }
            }
            
            return null;
        }
    
    }
    
    定义一个adapter
    package com.booway.customhandleradapter;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.servlet.HandlerAdapter;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.LastModified;
    
    import com.booway.custominterface.IController;
    
    public class ISimpleHandlerAdapter implements HandlerAdapter {
    
        @Override
        public boolean supports(Object handler) {
            
            return handler instanceof IController;
        }
    
        @Override
        public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            
            return ((IController)handler).IHandlerRequest();
        }
    
        @Override
        public long getLastModified(HttpServletRequest request, Object handler) {
            if (handler instanceof LastModified) {
                return ((LastModified) handler).getLastModified(request);
            }
            return -1L;
        }
    
    }
    
    定义一个controller
    
    package com.booway.controller;
    
    import org.springframework.web.servlet.ModelAndView;
    
    import com.booway.custominterface.IController;
    
    public class TestController implements IController {
        
        @Override
        public ModelAndView IHandlerRequest() throws Exception {
            
            ModelAndView mav = new ModelAndView();
            mav.setViewName("test");
            return mav;
        }
        
    }
    
    在配置文件中配置响应的bean
    
    <bean name="/*" class="com.booway.controller.TestController"></bean>
        
        <bean id="handlerAdapter" class="com.booway.customhandleradapter.ISimpleHandlerAdapter"></bean>
        
        <bean id="handlerMapping" class="com.booway.customhandlermapping.ISimapleHandlerMapping">
    //定义顺序,防止spring的HandlerMapping处理
            <property name="order" value="1"></property>
        </bean>
    jsp页面
    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>hello world</title>
    </head>
    <body>
        <h1>hello world</h1>
    </body>
    </html>
    
    结果:
    
    
    三、来看看AbstractHandlerMethodMapping系列
    
    由于AbstractHandlerMethodMapping实现了InitializingBean接口,所以会自动调用afterPropertiesSet方法,这个方法里面直接调用了initHandlerMethods方法
    获取handler
    protected void initHandlerMethods() {
            if (logger.isDebugEnabled()) {
                logger.debug("Looking for request mappings in application context: " + getApplicationContext());
            }
            String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
    //获取applicationContext中的所有bean,Obejct类是所有bean的基类
    BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
                    getApplicationContext().getBeanNamesForType(Object.class));
    
            for (String beanName : beanNames) {
                if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                    Class<?> beanType = null;
                    try {
    //获取对应beanName的Bean的类型
                        beanType = getApplicationContext().getType(beanName);
                    }
                    catch (Throwable ex) {
                        // An unresolvable bean type, probably from a lazy bean - let's ignore it.
                        if (logger.isDebugEnabled()) {
                            logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
                        }
                    }
                    if (beanType != null && isHandler(beanType)) {
                        detectHandlerMethods(beanName);
                    }
                }
            }
            handlerMethodsInitialized(getHandlerMethods());
        }
    
    
    看到isHandler方法:
    
    @Override
        protected boolean isHandler(Class<?> beanType) {
            return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
                    (AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
        }
    
    只要类上面标注了controller或者requestMapping就属于它能够处理的handler。
    
    protected void detectHandlerMethods(final Object handler) {
    //如果handler是String类型的就从ApplicationContext中获取它的类型,如果不是就直接获取它的类型
            Class<?> handlerType = (handler instanceof String ?
                    getApplicationContext().getType((String) handler) : handler.getClass());
    //获取用户的class,如果是Cglib代理类,那么就会获取它的父类class
            final Class<?> userType = ClassUtils.getUserClass(handlerType);
    
            Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
                    new MethodIntrospector.MetadataLookup<T>() {
                        @Override
                        public T inspect(Method method) {
                            return getMappingForMethod(method, userType);
                        }
                    });
    
            if (logger.isDebugEnabled()) {
                logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods);
            }
            for (Map.Entry<Method, T> entry : methods.entrySet()) {
                registerHandlerMethod(handler, entry.getKey(), entry.getValue());
            }
        }
    
    MethodIntrospector.selectMethods
    
    public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {
            final Map<Method, T> methodMap = new LinkedHashMap<Method, T>();
            Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>();
            Class<?> specificHandlerType = null;
    //目标类型是否是代理类
            if (!Proxy.isProxyClass(targetType)) {
                handlerTypes.add(targetType);
                specificHandlerType = targetType;
            }
            handlerTypes.addAll(Arrays.asList(targetType.getInterfaces()));
    
            for (Class<?> currentHandlerType : handlerTypes) {
                final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
    
                ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {
                    @Override
                    public void doWith(Method method) {
                        Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
                        T result = metadataLookup.inspect(specificMethod);
                        if (result != null) {
                            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
                            if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {
                                methodMap.put(specificMethod, result);
                            }
                        }
                    }
                }, ReflectionUtils.USER_DECLARED_METHODS);
            }
    
            return methodMap;
        }
    
    
    ReflectionUtils.doWithMethods
    
    public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
            // Keep backing up the inheritance hierarchy.
    //获取这个handler类的所有方法,当然也可能是接口的方法
            Method[] methods = getDeclaredMethods(clazz);
            for (Method method : methods) {
    //mf.matches(method)使用的是传进来的匿名类
                if (mf != null && !mf.matches(method)) {
                    continue;
                }
                try {
                    mc.doWith(method);
                }
                catch (IllegalAccessException ex) {
                    throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
                }
            }
            if (clazz.getSuperclass() != null) {
                doWithMethods(clazz.getSuperclass(), mc, mf);
            }
            else if (clazz.isInterface()) {
                for (Class<?> superIfc : clazz.getInterfaces()) {
                    doWithMethods(superIfc, mc, mf);
                }
            }
        }
    
    //这是doMatch方法中调用的一个方法
    public static Method getMostSpecificMethod(Method method, Class<?> targetClass) {
    //如果方法不为空,并且是可以重载的,即不是private修饰的,
            if (method != null && isOverridable(method, targetClass) &&
                    targetClass != null && targetClass != method.getDeclaringClass()) {
                try {
                    if (Modifier.isPublic(method.getModifiers())) {
                        try {
                            return targetClass.getMethod(method.getName(), method.getParameterTypes());
                        }
                        catch (NoSuchMethodException ex) {
                            return method;
                        }
                    }
                    else {
                        Method specificMethod =
                                ReflectionUtils.findMethod(targetClass, method.getName(), method.getParameterTypes());
                        return (specificMethod != null ? specificMethod : method);
                    }
                }
                catch (SecurityException ex) {
                    // Security settings are disallowing reflective access; fall back to 'method' below.
                }
            }
            return method;
        }
    
    
    
    getMappingForMethod(method, userType);
    
    @Override
        protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
            RequestMappingInfo info = createRequestMappingInfo(method);
            if (info != null) {
                RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
                if (typeInfo != null) {
                    info = typeInfo.combine(info);
                }
            }
            return info;
        }
    
    private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
    //如果当前方法包含RequestMapping注解
            RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
            RequestCondition<?> condition = (element instanceof Class<?> ?
                    getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
            return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
        }
    
    如果这个方法有requestMapping注解,那么就创建RequestMappingInfo对象
    protected RequestMappingInfo createRequestMappingInfo(
                RequestMapping requestMapping, RequestCondition<?> customCondition) {
    
            return RequestMappingInfo
                    .paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
                    .methods(requestMapping.method())
                    .params(requestMapping.params())
                    .headers(requestMapping.headers())
                    .consumes(requestMapping.consumes())
                    .produces(requestMapping.produces())
                    .mappingName(requestMapping.name())
                    .customCondition(customCondition)
                    .options(this.config)
                    .build();
        }
    
    此方法返回后又回到了
    @Override
        protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
            RequestMappingInfo info = createRequestMappingInfo(method);
            if (info != null) {
                RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
                if (typeInfo != null) {
                    info = typeInfo.combine(info);
                }
            }
            return info;
        }
    这个方法
    如果info 不为空,那么就检测类上面是否有requestMapping注解,如果有也创建一个requestMappingInfo对象,最后进行合并(combine)。
    createRequestMappingInfo里面有判断当前方法是否为桥接方法,桥接方法是在泛型中出现的,这是因为编译器在编译时会擦除泛型,比如子类实现带泛型的父类,并且在实现的时候指定了这个泛型的类型,比如
    
    public interface Action<T> {
    public void eat(T t);
    }
    
    public class DogAction implements Action<Dog> {
    public void eat(Dog t) {
    System.out.println("");
    }
    }
    
    在编译字节码的时候会在DogAction 出现连个方法,一个是擦除泛型的方法
    public void eat(Dog t) {
    System.out.println("");
    }
    
    另一个是桥接方法
    public void eat(Object t) {
    this.eat((Dog)t);
    }
    
    由于在jdk5以前是没有泛型的,为了能得到兼容,所以就有了桥接方法,在jdk5以前是没有泛型的,
    所以以前不管是什么都会当做Object的对象来处理,此时,如果传入了Object类型(实际类型是Dog)的,那么就会调用桥接方法,如果出入一个真实类型为Object的对象,那么在运行的时候就会报错。
    
    
    最后构造methodMap.put(specificMethod, result);一个用method做为key,用requestMappingInfo做值的Map
    
    
    接下来注册处理器存在HandlerMapping中等待使用
    for (Map.Entry<Method, T> entry : methods.entrySet()) {
                registerHandlerMethod(handler, entry.getKey(), entry.getValue());
            }
    
    
    protected void registerHandlerMethod(Object handler, Method method, T mapping) {
            this.mappingRegistry.register(mapping, handler, method);
        }
    
    
    public void register(T mapping, Object handler, Method method) {
    //获取写锁
                this.readWriteLock.writeLock().lock();
                try {
     //创建handlerMethod对象
                    HandlerMethod handlerMethod = createHandlerMethod(handler, method);
    //判断该handle人Mthod是不是唯一的处理器,如果不是就抛出错误
                    assertUniqueMethodMapping(handlerMethod, mapping);
    
                    if (logger.isInfoEnabled()) {
                        logger.info("Mapped "" + mapping + "" onto " + handlerMethod);
                    }
    //将处理器方法按照requestMappingInfo-》handle人Mthod键值对的方式存入mappingLookup
                    this.mappingLookup.put(mapping, handlerMethod);
    //获取可以映射到这个requestMappingInfo的url
                    List<String> directUrls = getDirectUrls(mapping);
                    for (String url : directUrls) {
    //URLLookup是一个继承了Map的容器,不过它的值是一个list
                        this.urlLookup.add(url, mapping);
                    }
    
                    String name = null;
                    if (getNamingStrategy() != null) {
    //name-》handlermethod,命名策略使用的类名中大写字母的组合加#和方法名组成的key
                        name = getNamingStrategy().getName(handlerMethod, mapping);
    //将以name-》handlermethod的方式加入到nameLookup这个map中,一样的值是一个list,这个list存着handlermethod
                        addMappingName(name, handlerMethod);
                    }
    //初始化跨域配置
                    CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
                    if (corsConfig != null) {
                        this.corsLookup.put(handlerMethod, corsConfig);
                    }
    
                    this.registry.put(mapping, new MappingRegistration<T>(mapping, handlerMethod, directUrls, name));
                }
                finally {
                    this.readWriteLock.writeLock().unlock();
                }
            }
    
    //创建handlermethod实例
    protected HandlerMethod createHandlerMethod(Object handler, Method method) {
            HandlerMethod handlerMethod;
            if (handler instanceof String) {
                String beanName = (String) handler;
                handlerMethod = new HandlerMethod(beanName,
                        getApplicationContext().getAutowireCapableBeanFactory(), method);
            }
            else {
                handlerMethod = new HandlerMethod(handler, method);
            }
            return handlerMethod;
        }
    //handleMthod的构造方法
    public HandlerMethod(Object bean, Method method) {
            Assert.notNull(bean, "Bean is required");
            Assert.notNull(method, "Method is required");
            this.bean = bean;
            this.beanFactory = null;
            this.beanType = ClassUtils.getUserClass(bean);
            this.method = method;
            this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            this.parameters = initMethodParameters();
            this.resolvedFromHandlerMethod = null;
        }
    
    //获取handlerMthod
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
            String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
            if (logger.isDebugEnabled()) {
                logger.debug("Looking up handler method for path " + lookupPath);
            }
            this.mappingRegistry.acquireReadLock();
            try {
                HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
                if (logger.isDebugEnabled()) {
                    if (handlerMethod != null) {
                        logger.debug("Returning handler method [" + handlerMethod + "]");
                    }
                    else {
                        logger.debug("Did not find handler method for [" + lookupPath + "]");
                    }
                }
                return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
            }
            finally {
                this.mappingRegistry.releaseReadLock();
            }
        }
    
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    //这个match是一个内部类,有两个属性,分别为条件(默认是requestMappingInfo),handlerMethod
            List<Match> matches = new ArrayList<Match>();
    //通过url来查找条件(这里默认是requestMappinginfo)
            List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
            if (directPathMatches != null) {
    //找到匹配的条件,比如比较他们的请求方法,参数,headers等
                addMatchingMappings(directPathMatches, matches, request);
            }
    //如果没有找到,那么就直接遍历所有的条件
            if (matches.isEmpty()) {
                // No choice but to go through all mappings...
                addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
            }
    //如果不为空,就对进行排序
            if (!matches.isEmpty()) {
                Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
    //排序,排序方法是根据条件进行排序的,其中url的匹配优先级最高
                Collections.sort(matches, comparator);
                if (logger.isTraceEnabled()) {
                    logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
                            lookupPath + "] : " + matches);
                }
    //第一个匹配的做为最佳
                Match bestMatch = matches.get(0);
                if (matches.size() > 1) {
                    if (CorsUtils.isPreFlightRequest(request)) {
                        return PREFLIGHT_AMBIGUOUS_MATCH;
                    }
                    Match secondBestMatch = matches.get(1);
    //对比连个匹配的处理器,如果完全相等,那么就抛出异常
                    if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                        Method m1 = bestMatch.handlerMethod.getMethod();
                        Method m2 = secondBestMatch.handlerMethod.getMethod();
                        throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
                                request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
                    }
                }
    //重新封装成handlermethod
                handleMatch(bestMatch.mapping, lookupPath, request);
    //返回新的处理器方法
                return bestMatch.handlerMethod;
            }
            else {
                return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
            }
        }
    
    
    获取到handler以后返回到
    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);
            }
    //获取到handlerExecutionChain
            HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
            if (CorsUtils.isCorsRequest(request)) {
                CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
                CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
                CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
                executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
            }
            return executionChain;
        }
    
    
    
    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
            HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                    (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    //通过url找到需要拦截的拦截器
            String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
            for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
                if (interceptor instanceof MappedInterceptor) {
                    MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                    if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                        chain.addInterceptor(mappedInterceptor.getInterceptor());
                    }
                }
                else {
                    chain.addInterceptor(interceptor);
                }
            }
            return chain;
        }
    
    得到HandlerExecutionChain 后回到doDispatcher()方法
    
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
            for (HandlerAdapter ha : this.handlerAdapters) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Testing handler adapter [" + ha + "]");
                }
                if (ha.supports(handler)) {
                    return ha;
                }
            }
            throw new ServletException("No adapter for handler [" + handler +
                    "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
        }
    
    找打匹配的适配器
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    protected ModelAndView handleInternal(HttpServletRequest request,
                HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
            ModelAndView mav;
    //检查request的请求方法是否是允许的
            checkRequest(request);
    
            // Execute invokeHandlerMethod in synchronized block if required.
            if (this.synchronizeOnSession) {
                HttpSession session = request.getSession(false);
                if (session != null) {
                    Object mutex = WebUtils.getSessionMutex(session);
                    synchronized (mutex) {
                        mav = invokeHandlerMethod(request, response, handlerMethod);
                    }
                }
                else {
                    // No HttpSession available -> no mutex necessary
                    mav = invokeHandlerMethod(request, response, handlerMethod);
                }
            }
            else {
                // No synchronization on session demanded at all...
                mav = invokeHandlerMethod(request, response, handlerMethod);
            }
    
            if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
                if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
                    applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
                }
                else {
                    prepareResponse(response);
                }
            }
    
            return mav;
        }
  • 相关阅读:
    i春秋暑期训练营丨渗透测试工程师开课啦
    CTF必备技能丨Linux Pwn入门教程——环境配置
    i春秋四周年中奖名单出炉丨确认过眼神,你是中奖人
    i春秋四周年福利趴丨一纸证书教你赢在起跑线
    「你学习,我买单」i春秋四周年精品课程福利专场
    i春秋四周年庆典狂欢丨价值6000元的Web安全课程免费送啦
    倒计时3天!i春秋四周年盛典狂欢,钜惠不停
    「学习攻略」0基础转型白帽黑客第一步是什么?
    奖金高达150万元的NEST即将上线,速来报名
    「白帽挖洞技能」YxCMS 1.4.7 漏洞分析
  • 原文地址:https://www.cnblogs.com/honger/p/9516925.html
Copyright © 2020-2023  润新知