码迷,mamicode.com
首页 > 移动开发 > 详细

handlerMapping的初始化以及查找handler

时间:2018-08-22 13:16:20      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:extends   直接   dwr   初始   父类   www.   with   ams   efault   

前提: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;
    }

 

handlerMapping的初始化以及查找handler

标签:extends   直接   dwr   初始   父类   www.   with   ams   efault   

原文地址:https://www.cnblogs.com/honger/p/9516925.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!