SimpleUrlHandlerMapping初始化

摘要:

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

1     /**
2      * Calls the {@link #registerHandlers} method in addition to the
3      * superclass‘s initialization.
4      */
5     @Override
6     public void initApplicationContext() throws BeansException {
7         super.initApplicationContext();
8         registerHandlers(this.urlMap);
9     }

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

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

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

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

// AbstractHandlerMapping

 1     /**
 2      * Initializes the interceptors.
 3      * @see #extendInterceptors(java.util.List)
 4      * @see #initInterceptors()
 5      */
 6     @Override
 7     protected void initApplicationContext() throws BeansException {
 8         extendInterceptors(this.interceptors);
 9         detectMappedInterceptors(this.mappedInterceptors);
10         initInterceptors();
11     }

// AbstractHandlerMapping

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

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

// AbstractHandlerMapping

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

// AbstractHandlerMapping

 1     /**
 2      * Initialize the specified interceptors, checking for {@link MappedInterceptor}s and adapting
 3      * HandlerInterceptors where necessary.
 4      * @see #setInterceptors
 5      * @see #adaptInterceptor
 6      */
 7     protected void initInterceptors() {
 8         if (!this.interceptors.isEmpty()) {
 9             for (int i = 0; i < this.interceptors.size(); i++) {
10                 Object interceptor = this.interceptors.get(i);
11                 if (interceptor == null) {
12                     throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
13                 }
14                 if (interceptor instanceof MappedInterceptor) {
15                     mappedInterceptors.add((MappedInterceptor) interceptor);
16                 }
17                 else {
18                     adaptedInterceptors.add(adaptInterceptor(interceptor));
19                 }
20             }
21         }
22     }

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

// AbstractHandlerMapping

 1     /**
 2      * Adapt the given interceptor object to the HandlerInterceptor interface.
 3      * <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
 4      * Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
 5      * Can be overridden in subclasses.
 6      * @param interceptor the specified interceptor object
 7      * @return the interceptor wrapped as HandlerInterceptor
 8      * @see org.springframework.web.servlet.HandlerInterceptor
 9      * @see org.springframework.web.context.request.WebRequestInterceptor
10      * @see WebRequestHandlerInterceptorAdapter
11      */
12     protected HandlerInterceptor adaptInterceptor(Object interceptor) {
13         if (interceptor instanceof HandlerInterceptor) {
14             return (HandlerInterceptor) interceptor;
15         }
16         else if (interceptor instanceof WebRequestInterceptor) {
17             return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
18         }
19         else {
20             throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
21         }
22     }

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

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

// SimpleUrlHandlerMapping

 1     /**
 2      * Register all handlers specified in the URL map for the corresponding paths.
 3      * @param urlMap Map with URL paths as keys and handler beans or bean names as values
 4      * @throws BeansException if a handler couldn‘t be registered
 5      * @throws IllegalStateException if there is a conflicting handler registered
 6      */
 7     protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
 8         if (urlMap.isEmpty()) {
 9             logger.warn("Neither ‘urlMap‘ nor ‘mappings‘ set on SimpleUrlHandlerMapping");
10         }
11         else {
12             for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
13                 String url = entry.getKey();
14                 Object handler = entry.getValue();
15                 // Prepend with slash if not already present.
16                 if (!url.startsWith("/")) {
17                     url = "/" + url;
18                 }
19                 // Remove whitespace from handler bean name.
20                 if (handler instanceof String) {
21                     handler = ((String) handler).trim();
22                 }
23                 registerHandler(url, handler);
24             }
25         }
26     }

// AbstractUrlHandlerMapping

 1 /**
 2      * Register the specified handler for the given URL path.
 3      * @param urlPath the URL the bean should be mapped to
 4      * @param handler the handler instance or handler bean name String
 5      * (a bean name will automatically be resolved into the corresponding handler bean)
 6      * @throws BeansException if the handler couldn‘t be registered
 7      * @throws IllegalStateException if there is a conflicting handler registered
 8      */
 9     protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
10         Assert.notNull(urlPath, "URL path must not be null");
11         Assert.notNull(handler, "Handler object must not be null");
12         Object resolvedHandler = handler;
13
14         // Eagerly resolve handler if referencing singleton via name.不是单例同时不是懒加载
15         if (!this.lazyInitHandlers && handler instanceof String) {
16             String handlerName = (String) handler;
17             if (getApplicationContext().isSingleton(handlerName)) {
18                 resolvedHandler = getApplicationContext().getBean(handlerName);
19             }
20         }
21
22         Object mappedHandler = this.handlerMap.get(urlPath);// 获取之前已经匹配的Handler
23         if (mappedHandler != null) {
24             if (mappedHandler != resolvedHandler) {// 如果新匹配得到的跟之前已解析到的handler不一致,则抛异常
25                 throw new IllegalStateException(
26                         "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
27                         "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
28             }
29         }
30         else {
31             if (urlPath.equals("/")) {// 设置rootHandler
32                 if (logger.isInfoEnabled()) {
33                     logger.info("Root mapping to " + getHandlerDescription(handler));
34                 }
35                 setRootHandler(resolvedHandler);
36             }
37             else if (urlPath.equals("/*")) {// 设置默认的defaultHandler
38                 if (logger.isInfoEnabled()) {
39                     logger.info("Default mapping to " + getHandlerDescription(handler));
40                 }
41                 setDefaultHandler(resolvedHandler);
42             }
43             else {// 最后才是普通handler的设置
44                 this.handlerMap.put(urlPath, resolvedHandler);
45                 if (logger.isInfoEnabled()) {
46                     logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
47                 }
48             }
49         }
50     }
时间: 2024-10-01 07:09:39

SimpleUrlHandlerMapping初始化的相关文章

SpringMVC源码解读 - HandlerMapping

SpringMVC在请求到handler处理器的分发这步是通过HandlerMapping模块解决的.handlerMapping 还处理拦截器. 先看看HandlerMapping的继承树吧 可以大致这样做个分类: 1. 一个接口HandlerMapping,定义一个api: HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception; 2. 一个基础抽象类:主要是准备上下文环境,提供getHand

SpringMVC深度探险(三) —— DispatcherServlet与初始化主线

本文是专栏文章(SpringMVC深度探险)系列的文章之一,博客地址为:http://downpour.iteye.com/blog/1341459. 在上一篇文章中,我们给出了构成SpringMVC应用程序的三要素以及三要素的设计过程.让我们来归纳一下整个设计过程中的一些要点: SpringMVC将Http处理流程抽象为一个又一个处理单元 SpringMVC定义了一系列组件(接口)与所有的处理单元对应起来 SpringMVC由DispatcherServlet贯穿始终,并将所有的组件串联起来

handlerMapping的初始化以及查找handler

前提:HttpServletBean初始化了一些servlet配置,接着FrameWorkServlet创建了WebApplicationContext,最后DispatcherServlet初始化一些解析器,mapping(九大组件). 一.从DispatcherServlet的doDispatch开始. 但WebApplicationContext加载完毕后FrameWorkdServlet调用DispatcherServlet的onRefresh方法 @Override protected

Springmvc借助SimpleUrlHandlerMapping实现接口开关功能

一.接口开关功能 1.可配置化,依赖配置中心 2.接口访问权限可控 3.springmvc不会扫描到,即不会直接的将接口暴露出去 二.接口开关使用场景 和业务没什么关系,主要方便查询系统中的一些状态信息.比如系统的配置信息,中间件的状态信息.这就需要写一些特定的接口,不能对外直接暴露出去(即不能被springmvc扫描到,不能被swagger扫描到). 三.SimpleUrlHandlerMapping官方解释 SimpleUrlHandlerMapping实现HandlerMapping接口以

Java的成员变量初始化

对于方法里面的成员变量,Java要求程序员强制提供一个初始化的值.比如下面这个方法就会出错: public class Breakyizhan{ public void Z(){ int z; z++; } public static void main(String[] args) { Breakyizhan B = new Breakyizhan(); B.Z(); } } /* (www.breakyizhan.com) 输出结果是: 编译会出错,方法变量没有初始化 */ 而对于类的数据,

快学Scala 第二十一课 (初始化trait的抽象字段)

初始化trait的抽象字段: trait Logged { println("Logged constructor") def log(msg: String){ println("Logged")} } trait FileLogger extends Logged { var filename: String override def log(msg: String) { println("filename:" + filename) } }

main.c 流程-buffer初始化

void buffer_init(long buffer_end)函数的理解: *   0         0x100000          0x400000                    0x10 00000(16M) *    ---------------------------------------------------------- *   |   kernel  | memery buffer   |   main memory              |      

AS3 Vecter初始化

var vec : Vecter.<Point> = new <Point>[     new Point(1,1),     new Point(1,2) ]; 类似于 Array的初始化的方法. var arr : Array = [1,2]; 当然Vecter的常规初始化: var vec : Vecter.<Point> = new Vecter.<Point>();//这样的话要赋值的话需要使用push等函数. 注意要: ① new <Poi

对象初始化

对象初始化过程 第一步:在创建之前,检查是否加载(检查硬盘上的class文件是否加载到内存中,如果没有加载,就先加载父类的文件) 在加载父类的文件,在加载本类的文件中java使用的加载的策略:懒惰式加载(按需加载)用到的时候,只加载一次. 第二步:分配对象的空间.递归分配所有父类和子类的属性空间,属性会自动初始化为"0"的值 第三步:给属性赋值 第四步:调用父类的构造方法(默认调用父类的无参构造方法) 第五步:调用本类的构造方法