spring-mvc源码阅读(三)RequestMappingHandlerMapping
2013-10-28 22:23
381 查看
RequestMappingHandlerMapping主要有两个功能注册和查找
注册指的是注册Interceptor和controller
查找是根据request查找与之对应的controller和Interceptor
我们知道初始化DispatcherServlet的时候首先要初始化HandlerMapping,这个时候就会初始化spring容器中注册的HandlerMapping就是RequestMappingHandlerMapping
RequestMappingHandlerMapping的初始化主要分成两个部分
初始化Interceptor和controller
初始化的工作在AbstractHandlerMapping类中完成代码如下
完成了Interceptor的初始化后,就是controller的初始化
controller的初始化在AbstractHandlerMethodMapping中进行代码如下
上面的代码中首先是找到spring容器中注册了的所有类的beamName
然后遍历这些类,检查它们是否是controller如果是则调用detectHandlerMethods方法代码如下
在getMappingForMethod方法里面,找到方法里面的RequestMapping注解,然后根据注解生成RequestMappingInfo
完成上面的步骤之后,就会将找到的controller注册 代码如下
这里面有两个map一个是urlMap,一个是handlerMethods
通过url我们可以找到与之对应的mapping,而通过mapping找到url对应的HandlerMethod 也就是要执行的controller和方法
注册指的是注册Interceptor和controller
查找是根据request查找与之对应的controller和Interceptor
我们知道初始化DispatcherServlet的时候首先要初始化HandlerMapping,这个时候就会初始化spring容器中注册的HandlerMapping就是RequestMappingHandlerMapping
RequestMappingHandlerMapping的初始化主要分成两个部分
初始化Interceptor和controller
初始化的工作在AbstractHandlerMapping类中完成代码如下
protected void initApplicationContext() throws BeansException { extendInterceptors(this.interceptors); detectMappedInterceptors(this.mappedInterceptors); initInterceptors(); }
完成了Interceptor的初始化后,就是controller的初始化
controller的初始化在AbstractHandlerMethodMapping中进行代码如下
protected void initHandlerMethods() { if (logger.isDebugEnabled()) { logger.debug("Looking for request mappings in application context: " + getApplicationContext()); } String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class)); for (String beanName : beanNames) { if (isHandler(getApplicationContext().getType(beanName))){ detectHandlerMethods(beanName); } } handlerMethodsInitialized(getHandlerMethods()); } protected boolean isHandler(Class<?> beanType) { return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) || (AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null)); }
上面的代码中首先是找到spring容器中注册了的所有类的beamName
然后遍历这些类,检查它们是否是controller如果是则调用detectHandlerMethods方法代码如下
protected void detectHandlerMethods(final Object handler) { Class<?> handlerType = (handler instanceof String) ? getApplicationContext().getType((String) handler) : handler.getClass(); final Class<?> userType = ClassUtils.getUserClass(handlerType); Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() { public boolean matches(Method method) { return getMappingForMethod(method, userType) != null; } }); for (Method method : methods) { T mapping = getMappingForMethod(method, userType); registerHandlerMethod(handler, method, mapping); } } protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { RequestMappingInfo info = null; RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class); if (methodAnnotation != null) { RequestCondition<?> methodCondition = getCustomMethodCondition(method); info = createRequestMappingInfo(methodAnnotation, methodCondition); RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class); if (typeAnnotation != null) { RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType); info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info); } } return info; }
在getMappingForMethod方法里面,找到方法里面的RequestMapping注解,然后根据注解生成RequestMappingInfo
完成上面的步骤之后,就会将找到的controller注册 代码如下
protected void registerHandlerMethod(Object handler, Method method, T mapping) { HandlerMethod newHandlerMethod = createHandlerMethod(handler, method); HandlerMethod oldHandlerMethod = handlerMethods.get(mapping); if (oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod)) { throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean() + "' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '" + oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped."); } this.handlerMethods.put(mapping, newHandlerMethod); if (logger.isInfoEnabled()) { logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod); } Set<String> patterns = getMappingPathPatterns(mapping); for (String pattern : patterns) { if (!getPathMatcher().isPattern(pattern)) { this.urlMap.add(pattern, mapping); } } }
这里面有两个map一个是urlMap,一个是handlerMethods
通过url我们可以找到与之对应的mapping,而通过mapping找到url对应的HandlerMethod 也就是要执行的controller和方法
相关文章推荐
- Spring MVC PageNotFound.noHandlerFound No mapping found for HTTP request with URI
- @FeignClient with top level @RequestMapping annotation is also registered as Spring MVC handler
- mvc:annotation-driven 元素,HttpMessageConverter,RequestMappingHandlerAdapter
- spring mvc No mapping found for HTTP request with URI
- Spring Web MVC 的HandlerMapping的使用之-------SimpleUrlHandlerMapping(有三种配法)
- springMVC源码分析--RequestMappingHandlerAdapter(五)
- 本人小白一枚,刚学习SpringMVC+MyBatis,遇到了一个问题一直报错 **No mapping found for HTTP request with URI**
- Spring MVC @RequestMapping Annotation Example with Controller, Methods, Headers, Params, @RequestParam, @PathVariable--转载
- No mapping found for HTTP request with URI [/springmvc/queryitems.action] in DispatcherServlet with
- 解决spring mvc No mapping found for HTTP request with URI错误的三种方法
- 警告: No mapping found for HTTP request with URI [/Springmvc/test] in DispatcherServlet with dispatche
- springMVC源码分析--RequestMappingHandlerAdapter(五)
- springmvc No mapping found for HTTP request with URI in Dispatc
- Spring MVC No mapping found for HTTP request with URI
- SpringMVC源码解读之HandlerMapping - AbstractUrlHandlerMapping系列request分发
- Spring MVC BeanNameUrlHandlerMapping example
- Spring4 MVC 笔记: ControllerClassNameHandlerMapping 实现DispatcherServlet
- spring-mvc源码阅读(一)servlet
- Spring MVC ControllerClassNameHandlerMapping example
- springMVC No mapping found for HTTP request with URI