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

Spring的RequestMappingHandlerMapping详解

阅读更多
深刻理解IdentityHashMap:http://donald-draper.iteye.com/blog/2326264
深入理解Collections的unmodifiableMap(Map map)方法:http://donald-draper.iteye.com/blog/2326291
Spring-RequestMappingHandlerAdapter初始化及请求处理:http://donald-draper.iteye.com/blog/2326185
我们来看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.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
这里我们来看RequestMappingHandlerMapping
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
    implements EmbeddedValueResolverAware
{
//初始化
 public void afterPropertiesSet()
    {
        if(useRegisteredSuffixPatternMatch)
            fileExtensions.addAll(contentNegotiationManager.getAllFileExtensions());
        //调用父类的初始化
	super.afterPropertiesSet();
    }
    private boolean useSuffixPatternMatch;
    private boolean useRegisteredSuffixPatternMatch;
    private boolean useTrailingSlashMatch;
    private ContentNegotiationManager contentNegotiationManager;
    private final List fileExtensions = new ArrayList();
    private StringValueResolver embeddedValueResolver;
}
来查看AbstractHandlerMethodMapping
public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMapping
    implements InitializingBean
{
  //初始化
 public void afterPropertiesSet()
    {
        //委托给initHandlerMethods
        initHandlerMethods();
    }
    //初始化方法处理器
    protected void initHandlerMethods()
    {
        //获取所有bean容器的beanName
        String beanNames[] = detectHandlerMethodsInAncestorContexts ? 
	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];
            //如果bean为Controller
            if(!beanName.startsWith("scopedTarget.") && isHandler(getApplicationContext().getType(beanName)))
                //
		detectHandlerMethods(beanName);
        }
        handlerMethodsInitialized(getHandlerMethods());
    }
    //获取方法处理器Map
    public Map getHandlerMethods()
    {
        //返回一个不可修改的Map集
        return Collections.unmodifiableMap(handlerMethods);
    }
    //留给子类扩展
      protected void handlerMethodsInitialized(Map map)
    { }
    //委托给RequestMappingHandlerMapping
    protected abstract boolean isHandler(Class class1);
    //将handler带@RequestMapping的方法添加到方法处理器Map中handlerMethods,及路径映射Map中urlMap
    protected void detectHandlerMethods(Object handler)
    {
        Class handlerType = (handler instanceof String) ? getApplicationContext().getType((String)handler) : handler.getClass();
        //注意这里用的是IdentityHashMap
	final Map mappings = new IdentityHashMap();
        final Class userType = ClassUtils.getUserClass(handlerType);
	//获取Contoller所有带@RequestMapping的方法
        Set methods = HandlerMethodSelector.selectMethods(userType, new org.springframework.util.ReflectionUtils.MethodFilter() {
            public boolean matches(Method method)
            {
	        
		//获取handlerType的method的@RequestMapping注解信息
                Object mapping = getMappingForMethod(method, userType);
                if(mapping != null)
                {
                    mappings.put(method, mapping);
                    return true;
                } else
                {
                    return false;
                }
            }
            final Class val$userType;
            final Map val$mappings;
            final AbstractHandlerMethodMapping this$0;
            {
                this.this$0 = AbstractHandlerMethodMapping.this;
                userType = class1;
                mappings = map;
                super();
            }
        });
        Method method;
        for(Iterator iterator = methods.iterator(); iterator.hasNext(); 
	                 registerHandlerMethod(handler, method, mappings.get(method)))
            method = (Method)iterator.next();
    }
    protected void registerHandlerMethod(Object handler, Method method, Object mapping)
    {
        //创建方法处理器
        HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);
	//从handlerMethods中获取方法处理器信息根据@RequestMapping注解信息
        HandlerMethod oldHandlerMethod = (HandlerMethod)handlerMethods.get(mapping);
	//如果已经存在,则抛出不能映射异常
        if(oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod))
            throw new IllegalStateException((new StringBuilder()).append("Ambiguous mapping found. Cannot map '").append(newHandlerMethod.getBean()).append("' bean method \n").append(newHandlerMethod).append("\nto ").append(mapping).append(": There is already '").append(oldHandlerMethod.getBean()).append("' bean method\n").append(oldHandlerMethod).append(" mapped.").toString());
        //将方法处理器放入handlerMethods中
	handlerMethods.put(mapping, newHandlerMethod);
        if(logger.isInfoEnabled())
            logger.info((new StringBuilder()).append("Mapped \"").append(mapping).append("\" onto ").append(newHandlerMethod).toString());
        //获取路径集
	Set patterns = getMappingPathPatterns(mapping);
        Iterator iterator = patterns.iterator();
        do
        {
            if(!iterator.hasNext())
                break;
            String pattern = (String)iterator.next();
            if(!getPathMatcher().isPattern(pattern))
	        //将路径与mapping关联
                urlMap.add(pattern, mapping);
        } while(true);
    }
    //委托给RequestMappingInfoHandlerMapping
    protected abstract Object getMappingForMethod(Method method, Class class1);
    protected abstract Set getMappingPathPatterns(Object obj);
    //根据request的url寻找合适的HandlerMethod
    protected HandlerMethod getHandlerInternal(HttpServletRequest request)
        throws Exception
    {
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder()).append("Looking up handler method for path ").append(lookupPath).toString());
        //根据路径和request寻找handlerMethod
	HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        if(logger.isDebugEnabled())
            if(handlerMethod != null)
                logger.debug((new StringBuilder()).append("Returning handler method [").append(handlerMethod).append("]").toString());
            else
                logger.debug((new StringBuilder()).append("Did not find handler method for [").append(lookupPath).append("]").toString());
        return handlerMethod == null ? null : handlerMethod.createWithResolvedBean();
    }
      //根据路径和request寻找handlerMethod
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request)
        throws Exception
    {
        List matches = new ArrayList();
        List directPathMatches = (List)urlMap.get(lookupPath);
        if(directPathMatches != null)
            addMatchingMappings(directPathMatches, matches, request);
        if(matches.isEmpty())
            addMatchingMappings(handlerMethods.keySet(), matches, request);
        if(!matches.isEmpty())
        {
            Comparator comparator = new MatchComparator(getMappingComparator(request));
            Collections.sort(matches, comparator);
            if(logger.isTraceEnabled())
                logger.trace((new StringBuilder()).append("Found ").append(matches.size()).append(" matching mapping(s) for [").append(lookupPath).append("] : ").append(matches).toString());
            Match bestMatch = (Match)matches.get(0);
            if(matches.size() > 1)
            {
                Match secondBestMatch = (Match)matches.get(1);
                if(comparator.compare(bestMatch, secondBestMatch) == 0)
                {
                    Method m1 = bestMatch.handlerMethod.getMethod();
                    Method m2 = secondBestMatch.handlerMethod.getMethod();
                    throw new IllegalStateException((new StringBuilder()).append("Ambiguous handler methods mapped for HTTP path '").append(request.getRequestURL()).append("': {").append(m1).append(", ").append(m2).append("}").toString());
                }
            }
            handleMatch(bestMatch.mapping, lookupPath, request);
            return bestMatch.handlerMethod;
        } else
        {
            return handleNoMatch(handlerMethods.keySet(), lookupPath, request);
        }
    }
    private static final String SCOPED_TARGET_NAME_PREFIX = "scopedTarget.";
    private boolean detectHandlerMethodsInAncestorContexts;
    //LinkedHashMap<RequestMappingInfo,HandlerMethod>
    private final Map handlerMethods = new LinkedHashMap();
    /LinkedHashMap<String,RequestMappingInfo>,key为路径
    private final MultiValueMap urlMap = new LinkedMultiValueMap();
}

查看RequestMappingHandlerMapping.isHandler()
  //isHandler,判断bean是否带有@Controller
 protected boolean isHandler(Class beanType)
    {
        return AnnotationUtils.findAnnotation(beanType, org/springframework/stereotype/Controller) != null || AnnotationUtils.findAnnotation(beanType, org/springframework/web/bind/annotation/RequestMapping) != null;
    }

查看RequestMappingHandlerMapping.getMappingForMethod()
protected volatile Object getMappingForMethod(Method method, Class class1)
    {
        return getMappingForMethod(method, class1);
    }

//判断handlerType的method是否带@RequestMapping,并返回注解信息
protected RequestMappingInfo getMappingForMethod(Method method, Class handlerType)
    {
        RequestMappingInfo info = null;
        RequestMapping methodAnnotation = (RequestMapping)AnnotationUtils.findAnnotation(method, 
			org/springframework/web/bind/annotation/RequestMapping);
        if(methodAnnotation != null)
        {
            RequestCondition methodCondition = getCustomMethodCondition(method);
            info = createRequestMappingInfo(methodAnnotation, methodCondition);
            RequestMapping typeAnnotation = (RequestMapping)AnnotationUtils.findAnnotation(handlerType, org/springframework/web/bind/annotation/RequestMapping);
            if(typeAnnotation != null)
            {
                RequestCondition typeCondition = getCustomTypeCondition(handlerType);
                info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
            }
        }
        return info;
    }

查看RequestMappingInfoHandlerMapping.getMappingPathPatterns()
public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping
{
    protected Set getMappingPathPatterns(RequestMappingInfo info)
    {
        return info.getPatternsCondition().getPatterns();
    }
}

//RequestMappingInfo
public final class RequestMappingInfo
    implements RequestCondition
{
    public PatternsRequestCondition getPatternsCondition()
    {
        return patternsCondition;
    }
    private final PatternsRequestCondition patternsCondition;
    private final RequestMethodsRequestCondition methodsCondition;
    private final ParamsRequestCondition paramsCondition;
    private final HeadersRequestCondition headersCondition;
    private final ConsumesRequestCondition consumesCondition;
    private final ProducesRequestCondition producesCondition;
    private final RequestConditionHolder customConditionHolder;
}

查看PatternsRequestCondition
public final class PatternsRequestCondition extends AbstractRequestCondition
{   
   public Set getPatterns()
    {
        return patterns;
    }
    private final Set patterns;
    private final UrlPathHelper pathHelper;
    private final PathMatcher pathMatcher;
    private final boolean useSuffixPatternMatch;
    private final boolean useTrailingSlashMatch;
    private final List fileExtensions;
}

//RequestMappingInfo
public final class RequestMappingInfo
    implements RequestCondition
{
    public PatternsRequestCondition getPatternsCondition()
    {
        return patternsCondition;
    }
    private final PatternsRequestCondition patternsCondition;
    private final RequestMethodsRequestCondition methodsCondition;
    private final ParamsRequestCondition paramsCondition;
    private final HeadersRequestCondition headersCondition;
    private final ConsumesRequestCondition consumesCondition;
    private final ProducesRequestCondition producesCondition;
    private final RequestConditionHolder customConditionHolder;
}

查看PatternsRequestCondition
public final class PatternsRequestCondition extends AbstractRequestCondition
{   
   public Set getPatterns()
    {
        return patterns;
    }
    private final Set patterns;
    private final UrlPathHelper pathHelper;
    private final PathMatcher pathMatcher;
    private final boolean useSuffixPatternMatch;
    private final boolean useTrailingSlashMatch;
    private final List fileExtensions;
}

//HandlerMethod
public class HandlerMethod
{
     public HandlerMethod(Object bean, Method method)
    {
        this.bean = bean;
        beanFactory = null;
        this.method = method;
        bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
        parameters = initMethodParameters();
    }

    public transient HandlerMethod(Object bean, String methodName, Class parameterTypes[])
        throws NoSuchMethodException
    {
        this.bean = bean;
        beanFactory = null;
        method = bean.getClass().getMethod(methodName, parameterTypes);
        bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
        parameters = initMethodParameters();
    }

    public HandlerMethod(String beanName, BeanFactory beanFactory, Method method)
    {
        bean = beanName;
        this.beanFactory = beanFactory;
        this.method = method;
        bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
        parameters = initMethodParameters();
    }

    protected HandlerMethod(HandlerMethod handlerMethod)
    {
        bean = handlerMethod.bean;
        beanFactory = handlerMethod.beanFactory;
        method = handlerMethod.method;
        bridgedMethod = handlerMethod.bridgedMethod;
        parameters = handlerMethod.parameters;
    }

    private HandlerMethod(HandlerMethod handlerMethod, Object handler)
    {       
        bean = handler;
        beanFactory = handlerMethod.beanFactory;
        method = handlerMethod.method;
        bridgedMethod = handlerMethod.bridgedMethod;
        parameters = handlerMethod.parameters;
    }
    private final Object bean;
    private final BeanFactory beanFactory;
    private final Method method;
    private final Method bridgedMethod;
    private final MethodParameter parameters[];
}

总结:
从以上分析,可以看出RequestMappingHandlerMapping,主要做的工作是将Contoller的带RequestMapping方法,添加到处理方法映射器和路径方法解决器中。




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics