Spirng 源代码学习笔记 Web 篇(二)HandlerMapping
HandlerMapping 负责将请求映射到实际处理对象。
?
当应用上下文中未配置?HandlerMapping 的实现类时,DispatcherServlet 在初始化时会根据DispatcherServlet.properties 的配置设置 Spring 自己的实现类。?
?
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
?
继承结构:
?
HandlerMapping
接口声明如下,入参为 request 对象,返回为?HandlerExecutionChain。?
?
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
??
HandlerExecutionChain 包含实际处理请求的对象和拦截器。实际处理请求的对象例子是普通的 Controller 对象;拦截器的例子:如对 http 返回设置统一的防止浏览器缓存头信息。
?
AbstractHandlerMapping
继承自 WebApplicationObjectSupport,支持 ordering, a default handler, and handler interceptors.
使用 template method:
?
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } return getHandlerExecutionChain(handler, request); } protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception; protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { if (handler instanceof HandlerExecutionChain) { HandlerExecutionChain chain = (HandlerExecutionChain) handler; chain.addInterceptors(getAdaptedInterceptors()); return chain; } else { return new HandlerExecutionChain(handler, getAdaptedInterceptors()); } }?
?
AbstractUrlHandlerMapping
for URL-mapped。Provides infrastructure for mapping handlers to URLs;
Supports direct matches and various Ant-style pattern matches。
?
// 注册映射关系
protected void registerHandler(String urlPath, Object handler)
?
// 根据已注册的映射集合找到所有匹配项,并确定一个 best match
protected Object lookupHandler(String urlPath, HttpServletRequest request)
?
// 调用 lookupHandler,设置拦截器,返回 HandlerExecutionChain
protected Object getHandlerInternal(HttpServletRequest request)
?
SimpleUrlHandlerMapping
根据用户配置的 Map<String, Object> 集合,注册映射集合。
?
AbstractDetectingUrlHandlerMapping
扫描所有 spring 上下文中的 bean 实例,存在映射的自动进行注册。
再次 template method:
?
protected void detectHandlers() throws BeansException { if (logger.isDebugEnabled()) { logger.debug("Looking for URL mappings in application context: " + getApplicationContext()); } String[] beanNames = (this.detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class)); // Take any bean name that we can determine URLs for. for (String beanName : beanNames) { String[] urls = determineUrlsForHandler(beanName); if (!ObjectUtils.isEmpty(urls)) { // URL paths found: Let's consider it a handler. registerHandler(urls, beanName); } else { if (logger.isDebugEnabled()) { logger.debug("Rejected bean name '" + beanName + "': no URL paths identified"); } } } } protected abstract String[] determineUrlsForHandler(String beanName);?
?
BeanNameUrlHandlerMapping
beanName 映射,只处理以 “/” 开始的 beanName。
protected String[] determineUrlsForHandler(String beanName) { List<String> urls = new ArrayList<String>(); if (beanName.startsWith("/")) { urls.add(beanName); } String[] aliases = getApplicationContext().getAliases(beanName); for (String alias : aliases) { if (alias.startsWith("/")) { urls.add(alias); } } return StringUtils.toStringArray(urls); }?
?
DefaultAnnotationHandlerMapping
类和方法上 RequestMapping 注解中的 value 值作为 url 的构成部分。
?
AbstractControllerUrlHandlerMapping
基于约定,面向 Controller 类型的映射。可配置不希望包含的类或者包。
Controller 类型是指实现了 org.springframework.web.servlet.mvc.Controller 接口或者类上使用了 @Controller 注解。
?
ControllerBeanNameHandlerMapping
根据 beanName 和配置的前缀、后缀作为映射的 url。
?
ControllerClassNameHandlerMapping
根据类的名称生成 url,可配置大小写敏感、路径前缀、basePackage。
org.springframework.web.servlet.mvc.Controller
-
WelcomeController
->/welcome*
-
HomeController
->/home*
For MultiActionControllers
and @Controller
beans
-
WelcomeController
->/welcome
,/welcome/*
-
CatalogController
->/catalog
,/catalog/*