`
Donald_Draper
  • 浏览: 951855 次
社区版块
存档分类
最新评论

Spring的DefaultAnnotationHandlerMapping详解

阅读更多
前面我们讲解过DispatcherServlet:http://donald-draper.iteye.com/blog/2325394
Spring-DispatcherServlet请求处理:http://donald-draper.iteye.com/blog/2325415
下面我们来看看DispatcherServlet的handlerMappings初始化所做的事情
public class DispatcherServlet extends FrameworkServlet
{
 public DispatcherServlet(WebApplicationContext webApplicationContext)
    {
        super(webApplicationContext);
        detectAllHandlerMappings = true;
        detectAllHandlerAdapters = true;
        detectAllHandlerExceptionResolvers = true;
        detectAllViewResolvers = true;
        throwExceptionIfNoHandlerFound = false;
        cleanupAfterInclude = true;
    }
   
    //初始化控制器映射
     private void initHandlerMappings(ApplicationContext context)
    {
        handlerMappings = null;
        if(detectAllHandlerMappings)
        {
            Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, org/springframework/web/servlet/HandlerMapping, true, false);
            if(!matchingBeans.isEmpty())
            {
	       //List<HashMap<String,HandlerMapping>>,Key为beanName,value值为HandlerMapping实例
                handlerMappings = new ArrayList(matchingBeans.values());
                OrderComparator.sort(handlerMappings);
            }
        } 
    }
    //初始化控制器方法适配器
      private void initHandlerAdapters(ApplicationContext context)
    {
        handlerAdapters = null;
        if(detectAllHandlerAdapters)
        {
            Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, org/springframework/web/servlet/HandlerAdapter, true, false);
            if(!matchingBeans.isEmpty())
            {
	        //List<HashMap<String,HandlerAdapter>>,Key为beanName,value值为HandlerAdapter实例
                handlerAdapters = new ArrayList(matchingBeans.values());
                OrderComparator.sort(handlerAdapters);
            }
        }
    }

    private List handlerMappings;//List<HashMap<String,HandlerMapping>>,Key为beanName,value值为HandlerMapping实例
    private List handlerAdapters;//List<HashMap<String,HandlerAdapter>>,Key为beanName,value值为HandlerAdapter实例
    private List handlerExceptionResolvers;
    private List viewResolvers;

    static 
    {
        try
        {
	    //加载默认配置文件
            ClassPathResource resource = new ClassPathResource("DispatcherServlet.properties", org/springframework/web/servlet/DispatcherServlet);
            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
        }
    }
}

//Spring日志追踪我们可以发现,DispatcherServletd的控制器映射处理器为
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
//静态文件的映射js,css等
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
这里我们来讲默认注解控制器映射处理器DefaultAnnotationHandlerMapping
public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping
{

    public DefaultAnnotationHandlerMapping()
    {
        useDefaultSuffixPattern = true;
    }

    public void setUseDefaultSuffixPattern(boolean useDefaultSuffixPattern)
    {
        this.useDefaultSuffixPattern = useDefaultSuffixPattern;
    }
    //这里我们找不到任何头绪
}

查看AbstractDetectingUrlHandlerMapping
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping
{

    public AbstractDetectingUrlHandlerMapping()
    {
        detectHandlersInAncestorContexts = false;
    }

    public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts)
    {
        this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts;
    }
    //初始化应用上下文,这里好像有点头绪
    public void initApplicationContext()
        throws ApplicationContextException
    {
        //查看父类
        super.initApplicationContext();
        detectHandlers();
    }
 }

查看AbstractUrlHandlerMapping
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping
{
//没有任何迹象
}

查看AbstractHandlerMapping
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
    implements HandlerMapping, Ordered
{
  //貌似有点头绪
protected void initApplicationContext()
        throws BeansException
    {
        extendInterceptors(interceptors);
        detectMappedInterceptors(mappedInterceptors);
	//初始化拦截器
        initInterceptors();
    }
 }

查看WebApplicationObjectSupport
public abstract class WebApplicationObjectSupport extends ApplicationObjectSupport
    implements ServletContextAware
{
     //还是没看到怎么回事
protected void initApplicationContext(ApplicationContext context)
    {
        super.initApplicationContext(context);
        if(servletContext == null && (context instanceof WebApplicationContext))
        {
            servletContext = ((WebApplicationContext)context).getServletContext();
            if(servletContext != null)
                initServletContext(servletContext);
        }
    }
    protected void initServletContext(ServletContext servletcontext)
    {
    }
}

查看ApplicationObjectSupport
public abstract class ApplicationObjectSupport
    implements ApplicationContextAware
{  
public final void setApplicationContext(ApplicationContext context)
        throws BeansException
    {
        if(context == null && !isContextRequired())
        {
            applicationContext = null;
            messageSourceAccessor = null;
        } else
        if(applicationContext == null)
        {   //关键,是不是有点意思了
            initApplicationContext(context);
        }
    }
    protected void initApplicationContext(ApplicationContext context)
        throws BeansException
    {
        initApplicationContext();
    }
   //留给子类扩展
    protected void initApplicationContext()
        throws BeansException
    {
    }
}

好了,看到这里,我们知道一二,再看AbstractDetectingUrlHandlerMapping
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping
{

    public AbstractDetectingUrlHandlerMapping()
    {
        detectHandlersInAncestorContexts = false;
    }

    public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts)
    {
        this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts;
    }
    //初始化应用上下文,
    public void initApplicationContext()
        throws ApplicationContextException
    {
        //初始化父类应用上下文
        super.initApplicationContext();
	//探测Handlers
        detectHandlers();
    }
    protected void detectHandlers()
        throws BeansException
    {
        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder()).append("Looking for URL mappings in application context: ").append(getApplicationContext()).toString());
	String beanNames[] = detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), java/lang/Object) : getApplicationContext().getBeanNamesForType(java/lang/Object);
        String as[] = beanNames;
        int i = as.length;
        for(int j = 0; j < i; j++)
        {
            String beanName = as[j];
	    //获取处理器的urls
            String urls[] = determineUrlsForHandler(beanName);
            if(!ObjectUtils.isEmpty(urls))
            {
	       //注册urls,与beanName的映射
                registerHandler(urls, beanName);
                continue;
            }
        }

    }
    //获取处理器的urls,父类扩展
    protected abstract String[] determineUrlsForHandler(String s);
 }

查看DefaultAnnotationHandlerMapping
public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping
{
    
     protected String[] determineUrlsForHandler(String beanName)
    {
        ApplicationContext context = getApplicationContext();
        Class handlerType = context.getType(beanName);
	//获取beanName的@RequestMapping
        RequestMapping mapping = (RequestMapping)context.findAnnotationOnBean(beanName, org/springframework/web/bind/annotation/RequestMapping);
        if(mapping != null)
        {
            cachedMappings.put(handlerType, mapping);
            Set urls = new LinkedHashSet();
            String typeLevelPatterns[] = mapping.value();
            if(typeLevelPatterns.length > 0)
            {
	       //获取Controller方法urls
                String methodLevelPatterns[] = determineUrlsForHandlerMethods(handlerType, true);
                String as[] = typeLevelPatterns;
                int i = as.length;
                for(int j = 0; j < i; j++)
                {
                    String typeLevelPattern = as[j];
		    //不以/开头,添加/
                    if(!typeLevelPattern.startsWith("/"))
                        typeLevelPattern = (new StringBuilder()).append("/").append(typeLevelPattern).toString();
                    boolean hasEmptyMethodLevelMappings = false;
                    String as1[] = methodLevelPatterns;
                    int k = as1.length;
                    for(int l = 0; l < k; l++)
                    {
                        String methodLevelPattern = as1[l];
                        if(methodLevelPattern == null)
                        {
                            hasEmptyMethodLevelMappings = true;
                        } else
                        {
                            String combinedPattern = getPathMatcher().combine(typeLevelPattern, methodLevelPattern);
                            addUrlsForPath(urls, combinedPattern);
                        }
                    }
                    //bean带@Controller注解添加Path到urls
                    if(hasEmptyMethodLevelMappings || org/springframework/web/servlet/mvc/Controller.isAssignableFrom(handlerType))
                        addUrlsForPath(urls, typeLevelPattern);
                }
                return StringUtils.toStringArray(urls);
            } else
            {
                return determineUrlsForHandlerMethods(handlerType, false);
            }
        }
        if(AnnotationUtils.findAnnotation(handlerType, org/springframework/stereotype/Controller) != null)
            return determineUrlsForHandlerMethods(handlerType, false);
        else
            return null;
    }
    //获取方法urls
    protected String[] determineUrlsForHandlerMethods(Class handlerType, final boolean hasTypeLevelMapping)
    {
        String subclassResult[] = determineUrlsForHandlerMethods(handlerType);
        if(subclassResult != null)
            return subclassResult;
        final Set urls = new LinkedHashSet();
        Set handlerTypes = new LinkedHashSet();
        handlerTypes.add(handlerType);
        handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces()));
        Class currentHandlerType;
        for(Iterator iterator = handlerTypes.iterator(); iterator.hasNext(); ReflectionUtils.doWithMethods(currentHandlerType, new org.springframework.util.ReflectionUtils.MethodCallback() {
        public void doWith(Method method)
        {
	    //获取bean方法method的@RequestMapping
            RequestMapping mapping = (RequestMapping)AnnotationUtils.findAnnotation(method, org/springframework/web/bind/annotation/RequestMapping);
            if(mapping != null)
            {
                String mappedPatterns[] = mapping.value();
                if(mappedPatterns.length > 0)
                {
                    String as[] = mappedPatterns;
                    int i = as.length;
                    for(int j = 0; j < i; j++)
                    {
                        String mappedPattern = as[j];
			 //不以/开头,添加/
                        if(!hasTypeLevelMapping && !mappedPattern.startsWith("/"))
                            mappedPattern = (new StringBuilder()).append("/").append(mappedPattern).toString();
			 //添加method的Path到urls
                        addUrlsForPath(urls, mappedPattern);
                    }

                } else
                if(hasTypeLevelMapping)
                    urls.add(null);
            }
        }

        final boolean val$hasTypeLevelMapping;
        final Set val$urls;
        final DefaultAnnotationHandlerMapping this$0;

            
            {
                this.this$0 = DefaultAnnotationHandlerMapping.this;
                hasTypeLevelMapping = flag;
                urls = set;
                super();
            }
    }, ReflectionUtils.USER_DECLARED_METHODS))
            currentHandlerType = (Class)iterator.next();

        return StringUtils.toStringArray(urls);
    }
    //默认返回的urls为null
     protected String[] determineUrlsForHandlerMethods(Class handlerType)
    {
        return null;
    }
    //添加path到urls-set
     protected void addUrlsForPath(Set urls, String path)
    {
        urls.add(path);
        if(useDefaultSuffixPattern && path.indexOf('.') == -1 && !path.endsWith("/"))
        {
            urls.add((new StringBuilder()).append(path).append(".*").toString());
            urls.add((new StringBuilder()).append(path).append("/").toString());
        }
    }
     private final Map cachedMappings = new HashMap();//HashMap<Class,RequestMapping>,key为Controller类,value为RequestMapping
}

//RequestMapping
public interface RequestMapping
    extends Annotation
{
    public abstract String[] value();
    public abstract RequestMethod[] method();
    public abstract String[] params();
    public abstract String[] headers();
    public abstract String[] consumes();
    public abstract String[] produces();
}

再来看registerHandler方法
//注册urls,与beanName的映射
registerHandler(urls, beanName);
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping
{
//注册urlPaths,与beanName的映射
 protected void registerHandler(String urlPaths[], String beanName)
        throws BeansException, IllegalStateException
    {
        Assert.notNull(urlPaths, "URL path array must not be null");
        String as[] = urlPaths;
        int i = as.length;
        for(int j = 0; j < i; j++)
        {
            String urlPath = as[j];
            registerHandler(urlPath, beanName);
        }

    }
   //注册urlPath,与beanName的映射
    protected void registerHandler(String urlPath, Object handler)
        throws BeansException, IllegalStateException
    {
        
        Object resolvedHandler = handler;
        if(!lazyInitHandlers && (handler instanceof String))
        {
            String handlerName = (String)handler;
            if(getApplicationContext().isSingleton(handlerName))
	        //获取bean实例,实际Controller实例
                resolvedHandler = getApplicationContext().getBean(handlerName);
        }
        Object mappedHandler = handlerMap.get(urlPath);
        if(mappedHandler != null)
        {
	    //如果urlPath已经存在,抛出异常
            if(mappedHandler != resolvedHandler)
                throw new IllegalStateException((new StringBuilder()).append("Cannot map ").append(getHandlerDescription(handler)).append(" to URL path [").append(urlPath).append("]: There is already ").append(getHandlerDescription(mappedHandler)).append(" mapped.").toString());
        } else
        if(urlPath.equals("/"))
        {
            if(logger.isInfoEnabled())
                logger.info((new StringBuilder()).append("Root mapping to ").append(getHandlerDescription(handler)).toString());
            //如果以/开头设为根处理器
	    setRootHandler(resolvedHandler);
        } else
        if(urlPath.equals("/*"))
        {
            if(logger.isInfoEnabled())
                logger.info((new StringBuilder()).append("Default mapping to ").append(getHandlerDescription(handler)).toString());
            //如果以/开头设为默认处理器
	    setDefaultHandler(resolvedHandler);
        } else
        {
	    //添加url路径与Handler映射到handlerMap
            handlerMap.put(urlPath, resolvedHandler);
            if(logger.isInfoEnabled())
                logger.info((new StringBuilder()).append("Mapped URL path [").append(urlPath).append("] onto ").append(getHandlerDescription(handler)).toString());
        }
    }
    //设置根处理器
    public void setRootHandler(Object rootHandler)
    {
        this.rootHandler = rootHandler;
    }
    //根据urlPath,寻找Handler
    protected Object lookupHandler(String urlPath, HttpServletRequest request)
        throws Exception
    {
        Object handler = handlerMap.get(urlPath);
        if(handler != null)
        {
            if(handler instanceof String)
            {
                String handlerName = (String)handler;
                handler = getApplicationContext().getBean(handlerName);
            }
            validateHandler(handler, request);
            return buildPathExposingHandler(handler, urlPath, urlPath, null);
        }
        List matchingPatterns = new ArrayList();
        String bestPatternMatch = handlerMap.keySet().iterator();
        do
        {
            if(!bestPatternMatch.hasNext())
                break;
            String registeredPattern = (String)bestPatternMatch.next();
            if(getPathMatcher().match(registeredPattern, urlPath))
                matchingPatterns.add(registeredPattern);
        } while(true);
        bestPatternMatch = null;
        Comparator patternComparator = getPathMatcher().getPatternComparator(urlPath);
        if(!matchingPatterns.isEmpty())
        {
            Collections.sort(matchingPatterns, patternComparator);
            if(logger.isDebugEnabled())
                logger.debug((new StringBuilder()).append("Matching patterns for request [").append(urlPath).append("] are ").append(matchingPatterns).toString());
            bestPatternMatch = (String)matchingPatterns.get(0);
        }
        if(bestPatternMatch != null)
        {
            handler = handlerMap.get(bestPatternMatch);
            if(handler instanceof String)
            {
                String handlerName = (String)handler;
                handler = getApplicationContext().getBean(handlerName);
            }
            validateHandler(handler, request);
            String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
            Map uriTemplateVariables = new LinkedHashMap();
            Iterator iterator = matchingPatterns.iterator();
            do
            {
                if(!iterator.hasNext())
                    break;
                String matchingPattern = (String)iterator.next();
                if(patternComparator.compare(bestPatternMatch, matchingPattern) == 0)
                {
                    Map vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
                    Map decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
                    uriTemplateVariables.putAll(decodedVars);
                }
            } while(true);
            if(logger.isDebugEnabled())
                logger.debug((new StringBuilder()).append("URI Template variables for request [").append(urlPath).append("] are ").append(uriTemplateVariables).toString());
            return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
        } else
        {
            return null;
        }
    }
    private Object rootHandler;
    private boolean lazyInitHandlers;
    private final Map handlerMap = new LinkedHashMap();//LinkedHashMap<String,Object>,key为urlPath,value为对应的handler
}

//AbstractHandlerMapping
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
    implements HandlerMapping, Ordered
{
    //设置默认Handler
    public void setDefaultHandler(Object defaultHandler)
    {
        this.defaultHandler = defaultHandler;
    }
    private int order;
    private Object defaultHandler;
    private UrlPathHelper urlPathHelper;
    private PathMatcher pathMatcher;
    private final List interceptors = new ArrayList();
    private final List adaptedInterceptors = new ArrayList();
    private final List mappedInterceptors = new ArrayList();
}

总结:
DefaultAnnotationHandlerMapping主要做的事情是,
将Controller的RequestMapping注解值(类路径及方法路径)与Controller实例映射起来
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics