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

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实例映射起来
分享到:
评论

相关推荐

    spring-web.jar

    Spring提供多种HandlerMapping实现,如BeanNameUrlHandlerMapping、DefaultAnnotationHandlerMapping等。 3. Controller:处理业务逻辑的组件,通常是一个实现了Controller接口或带有@Controller注解的类。...

    Spring3MVC注解(附实例).doc

    Spring3MVC 注解详解 Spring3MVC 注解是基于 Java 的 Spring 框架中的一种编程模型,旨在简化 Web 应用程序的开发。下面将详细介绍 Spring3MVC 注解的概念、实现机制、配置方法和实践示例。 Spring3MVC 注解的...

    spring mvc

    ### Spring MVC 教程知识点详解 #### 一、Spring MVC 概述 Spring MVC 是 Spring 框架的一部分,主要用于构建基于 Java 的 Web 应用程序。它是一种模型-视图-控制器(Model-View-Controller,MVC)设计模式的实现...

    spring3.0MVC注解(附实例).

    ### Spring3.0MVC注解详解 #### 注解支持的Web应用程序示例 - **PetClinic**:这是一个随Spring发行版本一起提供的示例应用,主要展示了如何在简单的表单处理场景中运用注解来构建Web应用。PetClinic应用位于...

    springweb3.0MVC注解(附实例)

    ### Spring Web 3.0 MVC 注解详解及实例 #### 一、概述 Spring Web MVC 是 Spring Framework 的一部分,提供了一种强大而灵活的方式来构建基于 Web 的应用。随着 Spring 3.0 的发布,框架引入了一系列重要的改进,...

    Spring3 MVC 学习笔记 入门

    #### 三、Spring MVC 示例详解 根据题目提供的部分代码示例,我们可以进一步了解 Spring MVC 的基本使用方式。 ##### 1. HelloWorldController 类 ```java package org.spring.mvc; import org.slf4j.Logger; ...

    Spring MVC的总结梳理

    ### Spring MVC的核心概念与应用详解 #### 一、Spring MVC概述 **Spring MVC**是Spring框架的一个重要组成部分,它提供了一种实现Web MVC设计模式的轻量级解决方案。该框架旨在帮助开发者简化Web应用程序的开发...

    spring2.5.6.zip

    《Spring 2.5.6:基础模板配置详解》 Spring 框架自诞生以来,就以其强大的依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)能力,成为了Java开发中的核心框架之一。在...

    Spring MVC 中文资料

    ### Spring MVC 框架详解 #### 一、Spring MVC 的优势 Spring MVC 作为一款优秀的模型-视图-控制器(MVC)框架,在实际应用中展现出了诸多优点,尤其在其3.0版本之后,越来越多的开发团队选择采用 Spring MVC。 1...

    个人整理Spring 框架

    ### Spring框架的重要知识点详解 #### 1. **注解驱动** Spring 3.0对注解的支持进一步增强,使得开发者能够以更简洁的方式进行组件的定义和配置。例如: - **@Controller**:标记一个类作为Web层的控制器,通常...

    MyBatis 3 整合Spring3、SpringMVC.docx

    `dispatcher.xml`是Spring MVC的配置文件,这里定义了扫描注解的包`&lt;context:component-scan&gt;`,默认注解处理器`DefaultAnnotationHandlerMapping`以及处理控制器的适配器`HandlerAdapter`。这些配置使得Spring MVC...

    spring3mvc真正入门资料

    **Spring3 MVC 知识点详解** Spring3 MVC 是一款高度灵活、性能优秀的MVC框架,自3.0版本发布以来,受到了许多开发团队的青睐。它的简洁设计和强大的功能使其成为Java Web开发中的热门选择。相较于Struts2,Spring3...

    spring MVC快速入门-深入分析.pdf

    #### 四、Spring MVC 配置详解 - **Spring MVC 配置文件**:通常包含在项目中的 `spring-mvc.xml` 文件里。该文件用于配置 DispatcherServlet 的行为,以及 HandlerMapping、HandlerAdapter 等组件。 - **视图解析...

    SpringMVC配置详解.pdf

    &lt;bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/&gt; &lt;bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/&gt; ``` 视图...

    Spring学习笔记

    &lt;bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/&gt; &lt;!-- 处理器适配器 --&gt; &lt;bean class="org.springframework.web.servlet.mvc.annotation....

Global site tag (gtag.js) - Google Analytics