默认情况下,Spring MVC会加载在当前系统中所有实现了HandlerMapping接口的bean,再进行按优先级排序。如果只期望Spring MVC只加载指定的HandlerMapping,可以修改web.xml中的DispatcherServlet的初始化参数,将detectAllHandlerMappings的值设置为false。这样,Spring MVC就只会查找名为“handlerMapping”的bean,并作为当前系统的唯一的HandlerMapping。所以在DispatcherServlet的initHandlerMappings()方法中,优先判断detectAllHandlerMappings的值,如果没有定义HandlerMapping的话,Spring MVC就会按照DispatcherServlet.properties所定义的内容来加载默认的HandlerMapping
- SimpleUrlHandlerMapping 支持映射bean实例和映射bean名称,需要手工维护urlmap,通过key指定访问路径,
- BeanNameUrlHandlerMapping 支持映射bean的name属性值,扫描以”/“开头的beanname,通过id指定访问路径
- RequestMappingHandlerMapping 支持@Controller和@RequestMapping注解,通过注解定义访问路径
作用是将请求映射到处理程序,以及预处理和处理后的拦截器列表,映射是基于一些标准的,其中的细节因不同的实现而不相同。这是官方文档上一段描述,该接口只有一个方法getHandler(request),返回一个HandlerExecutionChain对象
public interface HandlerMapping {
// 返回请求的一个处理程序handler和拦截器interceptors
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
initHandlerMappings
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
//默认为true,可通过DispatcherServlet的init-param参数进行设置
if (this.detectAllHandlerMappings) {
//在ApplicationContext中找到所有的handlerMapping, 包括父级上下文
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
//排序,可通过指定order属性进行设置,order的值为int型,数越小优先级越高
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
} else {
try {
//从ApplicationContext中取id(或name)="handlerMapping"的bean,此时为空
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
// 将hm转换成list,并赋值给属性handlerMappings
this.handlerMappings = Collections.singletonList(hm);
} catch (NoSuchBeanDefinitionException ex) {
}
}
//如果没有自定义则使用默认的handlerMappings
//默认的HandlerMapping在DispatcherServlet.properties属性文件中定义,
// 该文件是在DispatcherServlet的static静态代码块中加载的
// 默认的是:BeanNameUrlHandlerMapping和RequestMappingHandlerMapping
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);//默认策略
if (logger.isTraceEnabled()) {
logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
String key = strategyInterface.getName();//HandlerMappings
//获取HandlerMappings为key的value值,defaultStrategies在static块中读取DispatcherServlet.properties
String value = defaultStrategies.getProperty(key);
if (value != null) {
//逗号,分割成数组
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<>(classNames.length);
for (String className : classNames) {
try {
//反射加载并存储strategies
Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
//通过容器创建bean 触发后置处理器
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
。。。
}
return strategies;
}
else {
return new LinkedList<>();
}
}
protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
//通过容器创建bean
return context.getAutowireCapableBeanFactory().createBean(clazz);
}
DispatcherServlet.properties中的三个HandlerMapping
AbstractHandlerMapping
模板类
protected void initApplicationContext() throws BeansException {
// 提供给子类去重写的,不过Spring并未去实现,提供扩展
extendInterceptors(this.interceptors);
// 加载拦截器
detectMappedInterceptors(this.adaptedInterceptors);
// 归并拦截器
initInterceptors();
}
/**
* 空实现
*/
protected void extendInterceptors(List<Object> interceptors) {
}
/**
* 从上下文中加载MappedInterceptor类型的拦截器,比如我们在配置文件中使用
* <mvc:interceptors></mvc:interceptors>
* 标签配置的拦截器
*/
protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(
obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}
/**
* 合并拦截器,即将<mvc:interceptors></mvc:interceptors>中的拦截器与HandlerMapping中通过属性interceptors设置的拦截器进行合并
*/
protected void initInterceptors() {
if (!this.interceptors.isEmpty()) {
for (int i = 0; i < this.interceptors.size(); i++) {
Object interceptor = this.interceptors.get(i);
if (interceptor == null) {
throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
}
// 适配后加入adaptedInterceptors
this.adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
/**
* 适配HandlerInterceptor和WebRequestInterceptor
*/
protected HandlerInterceptor adaptInterceptor(Object interceptor) {
if (interceptor instanceof HandlerInterceptor) {
return (HandlerInterceptor) interceptor;
} else if (interceptor instanceof WebRequestInterceptor) {
return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
} else {
throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
}
}
/**
* 返回请求处理的HandlerExecutionChain,从AbstractHandlerMapping中的adaptedInterceptors和mappedInterceptors属性中获取
*/
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// getHandlerInternal()为抽象方法,具体需子类实现
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 = obtainApplicationContext().getBean(handlerName);
}
// 将请求处理器封装为HandlerExectionChain
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;
}
/**
* 钩子函数,需子类实现
*/
@Nullable
protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;
/**
* 构建handler处理器的HandlerExecutionChain,包括拦截器
*/
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) {
// 如果拦截器是MappedInterceptor,判断是否对该handler进行拦截,是的情况下添加
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else { // HandlerInterceptor直接添加,即通过HandingMapping属性配置的拦截器
chain.addInterceptor(interceptor);
}
}
return chain;
}
RequestMappingHandlerMapping
处理注解@RequestMapping及@Controller
- 实现InitializingBean接口,增加了bean初始化的能力,也就是说在bean初始化时可以做一些控制
- 实现EmbeddedValueResolverAware接口,即增加了读取属性文件的能力
继承自AbstractHandlerMethodMapping
//RequestMappingHandlerMapping
@Override
public void afterPropertiesSet() {
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setUrlPathHelper(getUrlPathHelper());
this.config.setPathMatcher(getPathMatcher());
this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
this.config.setContentNegotiationManager(getContentNegotiationManager());
super.afterPropertiesSet();
}
//AbstractHandlerMethodMapping
@Override
public void afterPropertiesSet() {
initHandlerMethods();
}
protected void initHandlerMethods() {
//获取上下文中所有bean的name,不包含父容器
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
//日志记录HandlerMethods的总数量
handlerMethodsInitialized(getHandlerMethods());
}
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
//根据name找出bean的类型
beanType = obtainApplicationContext().getType(beanName);
} catch (Throwable ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
//处理Controller和RequestMapping
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
//RequestMappingHandlerMapping
@Override
protected boolean isHandler(Class<?> beanType) {
//获取@Controller和@RequestMapping
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
//整个controller类的解析过程
protected void detectHandlerMethods(Object handler) {
//根据name找出bean的类型
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
//获取真实的controller,如果是代理类获取父类
Class<?> userType = ClassUtils.getUserClass(handlerType);
//对真实的controller所有的方法进行解析和处理 key为方法对象,T为注解封装后的对象RequestMappingInfo
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
// 调用子类RequestMappingHandlerMapping的getMappingForMethod方法进行处理,即根据RequestMapping注解信息创建匹配条件RequestMappingInfo对象
return getMappingForMethod(method, userType);
}catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
methods.forEach((method, mapping) -> {
//找出controller中可外部调用的方法
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
//注册处理方法
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
//requestMapping封装成RequestMappingInfo对象
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = createRequestMappingInfo(method);//解析方法上的requestMapping
if (info != null) {
//解析方法所在类上的requestMapping
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
info = typeInfo.combine(info);//合并类和方法上的路径,比如Controller类上有@RequestMapping("/demo"),方法的@RequestMapping("/demo1"),结果为"/demo/demo1"
}
String prefix = getPathPrefix(handlerType);//合并前缀
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
}
}
return info;
}
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
//找到方法上的RequestMapping注解
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
//获取自定义的类型条件(自定义的RequestMapping注解)
RequestCondition<?> condition = (element instanceof Class ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
protected RequestMappingInfo createRequestMappingInfo(
RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
//获取RequestMapping注解的属性,封装成RequestMappingInfo对象
RequestMappingInfo.Builder builder = RequestMappingInfo
.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
.methods(requestMapping.method())
.params(requestMapping.params())
.headers(requestMapping.headers())
.consumes(requestMapping.consumes())
.produces(requestMapping.produces())
.mappingName(requestMapping.name());
if (customCondition != null) {
builder.customCondition(customCondition);
}
return builder.options(this.config).build();
}
//再次封装成对应的对象 面向对象编程 每一个属性都存在多个值得情况需要排重封装
@Override
public RequestMappingInfo build() {
ContentNegotiationManager manager = this.options.getContentNegotiationManager();
PatternsRequestCondition patternsCondition = new PatternsRequestCondition(
this.paths, this.options.getUrlPathHelper(), this.options.getPathMatcher(),
this.options.useSuffixPatternMatch(), this.options.useTrailingSlashMatch(),
this.options.getFileExtensions());
return new RequestMappingInfo(this.mappingName, patternsCondition,
new RequestMethodsRequestCondition(this.methods),
new ParamsRequestCondition(this.params),
new HeadersRequestCondition(this.headers),
new ConsumesRequestCondition(this.consumes, this.headers),
new ProducesRequestCondition(this.produces, this.headers, manager),
this.customCondition);
}
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
//mapping是RequestMappingInfo对象 handler是controller类的beanName method为接口方法
public void register(T mapping, Object handler, Method method) {
...
this.readWriteLock.writeLock().lock();
try {
//beanName和method封装成HandlerMethod对象
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
//验证RequestMappingInfo是否有对应不同的method,有则抛出异常
validateMethodMapping(handlerMethod, mapping);
//RequestMappingInfo和handlerMethod绑定
this.mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = getDirectUrls(mapping);//可以配置多个url
for (String url : directUrls) {
//url和RequestMappingInfo绑定 可以根据url找到RequestMappingInfo,再找到handlerMethod
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
addMappingName(name, handlerMethod);//方法名和Method绑定
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
//将RequestMappingInfo url handlerMethod绑定到MappingRegistration对象 放入map
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
BeanNameUrlHandlerMapping
处理场景,id必须以/开头
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView("index");
mav.addObject("message", "默认的映射处理器示例");
return mav;
}
<bean id="resourceView"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="/name.do" class="com.luban.mvc.controller.HelloController"></bean>
//向上继承自ApplicationObjectSupport实现ApplicationContextAware接口
public abstract class ApplicationObjectSupport implements ApplicationContextAware {
protected final Log logger = LogFactory.getLog(this.getClass());
@Nullable
private ApplicationContext applicationContext;
...
public final void setApplicationContext(@Nullable ApplicationContext context) throws BeansException {
if (context == null && !this.isContextRequired()) {
this.applicationContext = null;
this.messageSourceAccessor = null;
} else if (this.applicationContext == null) {
if (!this.requiredContextClass().isInstance(context)) {
throw new ApplicationContextException("Invalid application context: needs to be of type [" + this.requiredContextClass().getName() + "]");
}
this.applicationContext = context;
this.messageSourceAccessor = new MessageSourceAccessor(context);
this.initApplicationContext(context);//模板方法,调子类
} else if (this.applicationContext != context) {
throw new ApplicationContextException("Cannot reinitialize with different application context: current one is [" + this.applicationContext + "], passed-in one is [" + context + "]");
}
}
...
}
@Override
public void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();//加载拦截器
// 处理url和bean name,具体注册调用父类AbstractUrlHandlerMapping类完成
detectHandlers();
}
//建立当前ApplicationContext中controller和url的对应关系
protected void detectHandlers() throws BeansException {
// 获取应用上下文
ApplicationContext applicationContext = obtainApplicationContext();
//获取ApplicationContext中的所有bean的name(也是id,即@Controller的属性值)
String[] beanNames = (this.detectHandlersInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) : applicationContext.getBeanNamesForType(Object.class));
//遍历所有beanName
for (String beanName : beanNames) {
// 通过模板方法模式调用BeanNameUrlHandlerMapping子类处理
String[] urls = determineUrlsForHandler(beanName);//判断是否以/开始
if (!ObjectUtils.isEmpty(urls)) {
//调用父类AbstractUrlHandlerMapping将url与handler存入map
registerHandler(urls, beanName);
}
}
}
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler;
// Eagerly resolve handler if referencing singleton via name.
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
ApplicationContext applicationContext = obtainApplicationContext();
if (applicationContext.isSingleton(handlerName)) {
resolvedHandler = applicationContext.getBean(handlerName);
}
}
//已存在且指向不同的Handler抛异常
Object mappedHandler = this.handlerMap.get(urlPath);
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) {
throw new IllegalStateException(
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
}
}
else {
if (urlPath.equals("/")) {
if (logger.isTraceEnabled()) {
logger.trace("Root mapping to " + getHandlerDescription(handler));
}
setRootHandler(resolvedHandler);//设置根处理器,即请求/的时候
}
else if (urlPath.equals("/*")) {
if (logger.isTraceEnabled()) {
logger.trace("Default mapping to " + getHandlerDescription(handler));
}
setDefaultHandler(resolvedHandler);//默认处理器
}
else {
this.handlerMap.put(urlPath, resolvedHandler);//注册进map
if (logger.isTraceEnabled()) {
logger.trace("Mapped [" + urlPath + "] onto " + getHandlerDescription(handler));
}
}
}
}
- 处理器bean的id/name为一个url请求路径,前面有"/";
- 如果多个url映射同一个处理器bean,那么就需要定义多个bean,导致容器创建多个处理器实例,占用内存空间;
- 处理器bean定义与url请求耦合在一起。
##### SimpleUrlHandlerMapping
间接实现了org.springframework.web.servlet.HandlerMapping接口,直接实现该接口的是org.springframework.web.servlet.handler.AbstractHandlerMapping抽象类,映射Url与请求handler bean。支持映射bean实例和映射bean名称
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
// 存储url和bean映射
private final Map<String, Object> urlMap = new LinkedHashMap<>();
// 注入property的name为mappings映射
public void setMappings(Properties mappings) {
CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
}
// 注入property的name为urlMap映射
public void setUrlMap(Map<String, ?> urlMap) {
this.urlMap.putAll(urlMap);
}
public Map<String, ?> getUrlMap() {
return this.urlMap;
}
// 实例化本类实例入口
@Override
public void initApplicationContext() throws BeansException {
// 调用父类AbstractHandlerMapping的initApplicationContext方法,只要完成拦截器的注册
super.initApplicationContext();
// 处理url和bean name,具体注册调用父类完成
registerHandlers(this.urlMap);
}
// 注册映射关系,及将property中的值解析到map对象中,key为url,value为bean id或name
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if (urlMap.isEmpty()) {
logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
} else {
urlMap.forEach((url, handler) -> {
// 增加以"/"开头
if (!url.startsWith("/")) {
url = "/" + url;
}
// 去除handler bean名称的空格
if (handler instanceof String) {
handler = ((String) handler).trim();
}
// 调用父类AbstractUrlHandlerMapping完成映射
registerHandler(url, handler);
});
}
}
}
SimpleUrlHandlerMapping类主要接收用户设定的url与handler的映射关系,其实际的工作都是交由其父类来完成的
- AbstractHandlerMapping
在创建初始化SimpleUrlHandlerMapping类时,调用其父类的initApplicationContext()方法,该方法完成拦截器的初始化
@Override
protected void initApplicationContext() throws BeansException {
// 空实现。子类可重写此方法以注册额外的拦截器
extendInterceptors(this.interceptors);
// 从上下文中查询拦截器并添加到拦截器列表中
detectMappedInterceptors(this.adaptedInterceptors);
// 初始化拦截器
initInterceptors();
}
// 查找实现了MappedInterceptor接口的bean,并添加到映射拦截器列表
protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(
obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}
// 将自定义bean设置到适配拦截器中,bean需实现HandlerInterceptor或WebRequestInterceptor
protected void initInterceptors() {
if (!this.interceptors.isEmpty()) {
for (int i = 0; i < this.interceptors.size(); i++) {
Object interceptor = this.interceptors.get(i);
if (interceptor == null) {
throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
}
this.adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
- AbstractUrlHandlerMapping
在创建初始化SimpleUrlHandlerMapping类时,调用AbstractUrlHandlerMapping类的registerHandler(urlPath,handler)方法
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler;
// 不是懒加载,默认为false,即不是,通过配置SimpleUrlHandlerMapping属性lazyInitHandlers的值进行控制
// 如果不是懒加载并且handler为单例,即从上下文中查询实例处理,此时resolvedHandler为handler实例对象;
// 如果是懒加载或者handler不是单例,即resolvedHandler为handler逻辑名
if (!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String) handler;
ApplicationContext applicationContext = obtainApplicationContext();
// 如果handler是单例,通过bean的scope控制
if (applicationContext.isSingleton(handlerName)) {
resolvedHandler = applicationContext.getBean(handlerName);
}
}
Object mappedHandler = this.handlerMap.get(urlPath);
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) {
throw new IllegalStateException(
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
}
}
else {
if (urlPath.equals("/")) {
if (logger.isInfoEnabled()) {
logger.info("Root mapping to " + getHandlerDescription(handler));
}
setRootHandler(resolvedHandler);
}
else if (urlPath.equals("/*")) {
if (logger.isInfoEnabled()) {
logger.info("Default mapping to " + getHandlerDescription(handler));
}
setDefaultHandler(resolvedHandler);
}
else {
// 把url与handler(名称或实例)放入map,以供后续使用
this.handlerMap.put(urlPath, resolvedHandler);
if (logger.isInfoEnabled()) {
logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
}
}
}
}