HandlerMapping处理器映射器
作用是根据request找到相应的处理器Handler和Interceptors,然后封装成HandlerExecutionChain对象返回
1
| HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
|
实现类
HandlerMapping帮助DispatcherServlet进行web请求的url到具体处理类的匹配,用来根据请求的url查找Handler,内部维护的Map<String, Object>
映射,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等
1
| private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();
|
spring自带了多个处理器映射实现
- BeanNameUrlHandlerMapping 根据控制器Bean的名字将控制器映射到URL
- ControllerBeanNameHandlerMapping 与BeanNameUrlHandlerMapping类似
- ControllerClassNameHandlerMapping 通过使用控制器的类名作为URL基础将控制器映射到URL
- DefaultAnnotationHandlerMapping 将请求映射给使用@RequestMapping注解的控制器和控制器方法
- SimplerUrlHandlerMapping 使用定义在Spring应用上下文的集合将控制器映射到URL
- RequestMappingHandlerMapping SpringMVC3.1新增的,在springMVC3.1之前,DefaultAnnotationHandlerMapping会在类级别上选中一个控制器,然后通过AnnotationMethodHandlerAdapter定位到具体要调用的方法;而在SpringMVC3.1之后,这些操作全都放生在RequestMappingHandlerMapping中,从类级别和方法级别的@RequestMapping注解中获取到路径映射信息,使得在HandlerInterceptor中获取到的处理器肯定是一个HandlerMethod类型
配置
1 2 3
| <mvc:annotation-driven/> <bean id="defaultAnnotationHandlerMapping" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
|
mvc:annotation-driven配置的作用
<mvc:annotation-driven/>
会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdater、ExceptionHandlerExceptionResolver三个bean
- 支持使用ConversionService实例对表单参数进行类型转换
- 支持使用@NumberFormatannotation、@DataTimeFormat注解完成数据类型的格式化
- 支持使用@Vaild注解对JavaBean实例进行JSR 303验证
- 支持使用@RequestBody和@ResponseBody注解
RequestMappingHandlerMapping源码
由于一般都使用<mvc:annotation-driven/>
进行配置,所以就以RequestMappingHandlerMapping为例进行讲解
创建
RequestMappingHandlerMapping实现了ApplicationContextAware接口,会执行setApplicationContext
1 2 3 4 5 6 7 8 9 10
|
protected void initApplicationContext() throws BeansException { extendInterceptors(this.interceptors); detectMappedInterceptors(this.adaptedInterceptors); initInterceptors(); }
|
RequestMappingHandlerMapping实现了InitializingBean接口,会执行afterPropertiesSet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public void afterPropertiesSet() { initHandlerMethods(); }
protected void initHandlerMethods() { String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class));
for (String beanName : beanNames) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { Class<?> beanType = null; try { beanType = getApplicationContext().getType(beanName); } catch (Throwable ex) { } if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); } } } handlerMethodsInitialized(getHandlerMethods()); }
|
访问
在进行访问的时候会通过org.springframework.web.servlet.DispatcherServlet#getHandler方法来遍历handlerMappings
1
| HandlerExecutionChain handler = hm.getHandler(request);
|
来调用HandlerMapping的getHandler方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); }
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
|
getHandlerInternal
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); this.mappingRegistry.acquireReadLock(); try { HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } }
|
getHandlerExecutionChain
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
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; }
|