摘要:

SimpleUrlHandlerMapping只是参与Handler的注册,请求映射时由AbstractUrlHandlerMapping搞定.

初始化时,通过setMappings(Properties mappings)或者setUrlMap(Map<String, ?> urlMap)设置映射关系,然后通过WebApplicationObjectSupport的initApplicationContext调用registerHandlers进行注册.

覆写initApplicationContext方法时,先调用父类实现,然后才调用registerHandlers进行注册.其中最终的注册registerHandler实现是由AbstractUrlHandlerMapping实现的.

父类AbstractHandlerMapping继承了WebApplicationObjectSupport,所以SimpleUrlHandlerMapping可以通过覆写initApplicationContext注册Handler.

注册Handler前,不忘靠AbstractHandlerMapping来初始化拦截器.

// SimpleUrlHandlerMapping

     /**
* Calls the {@link #registerHandlers} method in addition to the
* superclass's initialization.
*/
@Override
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
registerHandlers(this.urlMap);
}

initApplicationContext主要是进行拦截器的初始化.

  extendInterceptors是留给子类用的扩展接口,暂时没有使用

  detectMappedInterceptors是通过BeanFactoryUtils扫描应用下的全部MappedInterceptor类

  initInterceptors初始化特定的拦截器,检查MappedInterceptor,在需要时适配adaptor HandlerInterceptor

// AbstractHandlerMapping

     /**
* Initializes the interceptors.
* @see #extendInterceptors(java.util.List)
* @see #initInterceptors()
*/
@Override
protected void initApplicationContext() throws BeansException {
extendInterceptors(this.interceptors);
detectMappedInterceptors(this.mappedInterceptors);
initInterceptors();
}

// AbstractHandlerMapping

     /**
* Extension hook that subclasses can override to register additional interceptors,
* given the configured interceptors (see {@link #setInterceptors}).
* <p>Will be invoked before {@link #initInterceptors()} adapts the specified
* interceptors into {@link HandlerInterceptor} instances.
* <p>The default implementation is empty.
* @param interceptors the configured interceptor List (never {@code null}),
* allowing to add further interceptors before as well as after the existing
* interceptors
*/
protected void extendInterceptors(List<Object> interceptors) {
}

springmvc中经常使用BeanFactoryUtils扫描应用下的类来进行初始化.

// AbstractHandlerMapping

     /**
* Detects beans of type {@link MappedInterceptor} and adds them to the list of mapped interceptors.
* This is done in addition to any {@link MappedInterceptor}s that may have been provided via
* {@link #setInterceptors(Object[])}. Subclasses can override this method to change that.
*
* @param mappedInterceptors an empty list to add MappedInterceptor types to
*/
protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(
getApplicationContext(),MappedInterceptor.class, true, false).values());
}

// AbstractHandlerMapping

     /**
* Initialize the specified interceptors, checking for {@link MappedInterceptor}s and adapting
* HandlerInterceptors where necessary.
* @see #setInterceptors
* @see #adaptInterceptor
*/
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");
}
if (interceptor instanceof MappedInterceptor) {
mappedInterceptors.add((MappedInterceptor) interceptor);
}
else {
adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
}

适配HandlerInterceptor和WebRequestHandlerInterceptorAdapter(什么是WebRequestHandlerInterceptorAdapter,晚点再说吧,具体看到时候拦截器部分的分析)

// AbstractHandlerMapping

     /**
* Adapt the given interceptor object to the HandlerInterceptor interface.
* <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
* Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
* Can be overridden in subclasses.
* @param interceptor the specified interceptor object
* @return the interceptor wrapped as HandlerInterceptor
* @see org.springframework.web.servlet.HandlerInterceptor
* @see org.springframework.web.context.request.WebRequestInterceptor
* @see WebRequestHandlerInterceptorAdapter
*/
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());
}
}

这才到SimpleUrlHandlerMapping干活的地方,迭代urlMap调用AbstractUrlHandlerMapping的registerHandler进行注册

(保障url以"/"开头就不多说了)

// SimpleUrlHandlerMapping

     /**
* Register all handlers specified in the URL map for the corresponding paths.
* @param urlMap Map with URL paths as keys and handler beans or bean names as values
* @throws BeansException if a handler couldn't be registered
* @throws IllegalStateException if there is a conflicting handler registered
*/
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if (urlMap.isEmpty()) {
logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
}
else {
for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
String url = entry.getKey();
Object handler = entry.getValue();
// Prepend with slash if not already present.
if (!url.startsWith("/")) {
url = "/" + url;
}
// Remove whitespace from handler bean name.
if (handler instanceof String) {
handler = ((String) handler).trim();
}
registerHandler(url, handler);
}
}
}

// AbstractUrlHandlerMapping

 /**
* Register the specified handler for the given URL path.
* @param urlPath the URL the bean should be mapped to
* @param handler the handler instance or handler bean name String
* (a bean name will automatically be resolved into the corresponding handler bean)
* @throws BeansException if the handler couldn't be registered
* @throws IllegalStateException if there is a conflicting handler registered
*/
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;
if (getApplicationContext().isSingleton(handlerName)) {
resolvedHandler = getApplicationContext().getBean(handlerName);
}
} Object mappedHandler = this.handlerMap.get(urlPath);// 获取之前已经匹配的Handler
if (mappedHandler != null) {
if (mappedHandler != resolvedHandler) {// 如果新匹配得到的跟之前已解析到的handler不一致,则抛异常
throw new IllegalStateException(
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
}
}
else {
if (urlPath.equals("/")) {// 设置rootHandler
if (logger.isInfoEnabled()) {
logger.info("Root mapping to " + getHandlerDescription(handler));
}
setRootHandler(resolvedHandler);
}
else if (urlPath.equals("/*")) {// 设置默认的defaultHandler
if (logger.isInfoEnabled()) {
logger.info("Default mapping to " + getHandlerDescription(handler));
}
setDefaultHandler(resolvedHandler);
}
else {// 最后才是普通handler的设置
this.handlerMap.put(urlPath, resolvedHandler);
if (logger.isInfoEnabled()) {
logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
}
}
}
}

SpringMVC源码解读 - HandlerMapping - SimpleUrlHandlerMapping初始化的更多相关文章

  1. SpringMVC源码解读 - HandlerMapping - RequestMappingHandlerMapping初始化

    RequestMappingHandlerMapping ,用于注解@Controller,@RequestMapping来定义controller. @Controller @RequestMapp ...

  2. SpringMVC源码解读 - HandlerMapping

    SpringMVC在请求到handler处理器的分发这步是通过HandlerMapping模块解决的.handlerMapping 还处理拦截器. 先看看HandlerMapping的继承树吧 可以大 ...

  3. SpringMVC源码解读 - HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化

    AbstractDetectingUrlHandlerMapping是通过扫描方式注册Handler,收到请求时由AbstractUrlHandlerMapping的getHandlerInterna ...

  4. SpringMVC源码解读 - HandlerMapping - RequestMappingHandlerMapping请求分发

    AbstractHandlerMethodMapping实现接口getHandlerInternal,定义查找流程 RequestMappingInfoHandlerMapping根据RequestM ...

  5. SpringMVC源码解读 - HandlerMapping - AbstractUrlHandlerMapping系列request分发

    AbstractHandlerMapping实现HandlerMapping接口定的getHandler 1. 提供getHandlerInternal模板方法给子类实现 2. 如果没有获取Handl ...

  6. SpringMVC源码解读 - RequestMapping注解实现解读 - RequestCondition体系

    一般我们开发时,使用最多的还是@RequestMapping注解方式. @RequestMapping(value = "/", param = "role=guest& ...

  7. SpringMVC源码解读 - RequestMapping注解实现解读

    SpringMVC源码解读 - RequestMapping注解实现解读 - RequestCondition体系  https://www.cnblogs.com/leftthen/p/520840 ...

  8. SpringMVC源码解读 - RequestMapping注解实现解读 - RequestMappingInfo

    使用@RequestMapping注解时,配置的信息最后都设置到了RequestMappingInfo中. RequestMappingInfo封装了PatternsRequestCondition, ...

  9. springMVC源码分析--HandlerMapping(一)

    HandlerMapping的工作就是为每个请求找到合适的请求找到一个处理器handler,其实现机制简单来说就是维持了一个url到Controller关系的Map结构,其提供的实际功能也是根据req ...

随机推荐

  1. ThinkPHP实例—实现登录验证

    ThinkPHP 验证 本篇我们将运用商城实例讲解一下如何运用ThinkPHP做一个登录验证 我们的框架目录结构如下图所示: 其中 app  文件夹就是我们的应用文件夹  它的目录结构如下所示 其中 ...

  2. Java中RMI远程调用demo

    Java远程方法调用,即Java RMI(Java Remote Method Invocation),一种用于实现远程过程调用的应用程序编程接口.它使客户机上运行的程序可以调用远程服务器上的对象.远 ...

  3. 下载pubmed数据

    1 import requests 2 import json 3 4 search_url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils ...

  4. 深入浅出 Java Concurrency (13): 锁机制 part 8 读写锁 (ReentrantReadWriteLock) (1)

      从这一节开始介绍锁里面的最后一个工具:读写锁(ReadWriteLock). ReentrantLock 实现了标准的互斥操作,也就是一次只能有一个线程持有锁,也即所谓独占锁的概念.前面的章节中一 ...

  5. Swift 动画片段

    UIView.transitionWithView( self.WeatherDetailsView, duration: 0.7, options: .TransitionCrossDissolve ...

  6. C# 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke [问题点数:40分

    注意:  this.DateTimeRun = true;            new Thread(jishi_kernel).Start(); 线程的启动,不能放在    public Form ...

  7. 更改AD域安全策略-密码必须符合复杂性要求

    在域环境中,修改域用户密码时,会提示不符合密码策略, 更改"本地安全策略"是不会对域产生任何的作用的. 上图中可以看,这里按钮都是灰色的! 下面这个步骤教你如何找到"域安 ...

  8. c#文件下载---以文件流形式

    /// <summary> /// 文件下载 /// </summary> /// <param name="FileName">文件名< ...

  9. C#模板的效率问题

    1,有拆装箱的情景时,可使用模板方式避免拆装箱,这时候使用模板比不使用效率要高很多. 2,无拆装箱的操作时,全部是值传递,使用模板会比使用基本类型慢一半

  10. MantisBT 缺陷管理系统

    简介: 公司需要一套缺陷管理系统,这种系统比较热门的有 Jira.Redmine.MantisBT 等. 这次来整理一下 MantisBT,正好公司需要,以前的文档又丢失了. 下载地址:http:// ...