摘要:express
SimpleUrlHandlerMapping只是參與Handler的註冊,請求映射時由AbstractUrlHandlerMapping搞定.api
初始化時,經過setMappings(Properties mappings)或者setUrlMap(Map<String, ?> urlMap)設置映射關係,而後經過WebApplicationObjectSupport的initApplicationContext調用registerHandlers進行註冊.緩存
覆寫initApplicationContext方法時,先調用父類實現,而後才調用registerHandlers進行註冊.其中最終的註冊registerHandler實現是由AbstractUrlHandlerMapping實現的.mvc
父類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 }