国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

SpringMVC源碼解讀之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化

2019-11-26 14:32:40
字體:
來源:轉載
供稿:網友

 AbstractDetectingUrlHandlerMapping是通過掃描方式注冊Handler,收到請求時由AbstractUrlHandlerMapping的getHandlerInternal進行分發.

共有5個子類,一個抽象類.

與SimpleUrlHandlerMapping類似,通過覆寫initApplicationContext,然后調用detectHandlers進行初始化.

detectHandlers通過BeanFactoryUtils掃描應用下的Object,然后預留determineUrlsForHandler給子類根據Handler生成對應的url.

注冊使用的registerHandler依然由AbstractUrlHandlerMapping提供.

// AbstractDetectingUrlHandlerMapping/*** Calls the {@link #detectHandlers()} method in addition to the* superclass's initialization.*/@Overridepublic void initApplicationContext() throws ApplicationContextException {super.initApplicationContext();detectHandlers();}

這邊一樣是調用AbstractHandlerMapping的initApplicationContext初始化攔截器.

主角上場,detectHandlers,掃描Handlers

// AbstractDetectingUrlHandlerMapping/*** Register all handlers found in the current ApplicationContext.* <p>The actual URL determination for a handler is up to the concrete* {@link #determineUrlsForHandler(String)} implementation. A bean for* which no such URLs could be determined is simply not considered a handler.* @throws org.springframework.beans.BeansException if the handler couldn't be registered* @see #determineUrlsForHandler(String)*/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");}}}}

這邊預留的模板方法定義如下:

/*** Determine the URLs for the given handler bean.* @param beanName the name of the candidate bean* @return the URLs determined for the bean,* or {@code null} or an empty array if none*/protected abstract String[] determineUrlsForHandler(String beanName); 我們再來看看模板方法在BeanNameUrlHandlerMapping和AbstractControllerUrlHandlerMapping中的實現吧.BeanNameUrlHandlerMapping非常簡單,就實現了determineUrlsForHandler.其中的alias應該是應該就是通過beanName在配置文件中配置的.// BeanNameUrlHandlerMapping/*** Checks name and aliases of the given bean for URLs, starting with "/".*/@Overrideprotected 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);}

再來看看AbstractControllerUrlHandlerMapping中的實現

  isEligibleForMapping判斷controller是否被排除在外(通過包package排除或類class排除).

  buildUrlsForHandler由子類實現具體的url生成規則

  isControllerType判斷是否Controller的子類

  buildUrlsForHandler預留給子類生產url的模板方法.

// AbstractControllerUrlHandlerMapping/*** This implementation delegates to {@link #buildUrlsForHandler},* provided that {@link #isEligibleForMapping} returns {@code true}.*/@Overrideprotected String[] determineUrlsForHandler(String beanName) {Class beanClass = getApplicationContext().getType(beanName);if (isEligibleForMapping(beanName, beanClass)) {return buildUrlsForHandler(beanName, beanClass);}else {return null;}} // AbstractControllerUrlHandlerMapping/**判斷controller是否被排除在外(通過包package排除或類class排除).* Determine whether the specified controller is excluded from this mapping.* @param beanName the name of the controller bean* @param beanClass the concrete class of the controller bean* @return whether the specified class is excluded* @see #setExcludedPackages* @see #setExcludedClasses*/protected boolean isEligibleForMapping(String beanName, Class beanClass) {if (beanClass == null) {if (logger.isDebugEnabled()) {logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " +"because its bean type could not be determined");}return false;}if (this.excludedClasses.contains(beanClass)) {if (logger.isDebugEnabled()) {logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " +"because its bean class is explicitly excluded: " + beanClass.getName());}return false;}String beanClassName = beanClass.getName();for (String packageName : this.excludedPackages) {if (beanClassName.startsWith(packageName)) {if (logger.isDebugEnabled()) {logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " +"because its bean class is defined in an excluded package: " + beanClass.getName());}return false;}}return isControllerType(beanClass);} // AbstractControllerUrlHandlerMapping/*** Determine whether the given bean class indicates a controller type* that is supported by this mapping strategy.* @param beanClass the class to introspect*/protected boolean isControllerType(Class beanClass) {return this.predicate.isControllerType(beanClass);} // ControllerTypePredicate這邊提供2個api,分別判斷是Controller的子類還是MultiActionController的子類./*** Internal helper class that identifies controller types.** @author Juergen Hoeller* @since ..*/class ControllerTypePredicate {public boolean isControllerType(Class beanClass) {return Controller.class.isAssignableFrom(beanClass);}public boolean isMultiActionControllerType(Class beanClass) {return MultiActionController.class.isAssignableFrom(beanClass);}}

預留生成url的模板方法

// AbstractControllerUrlHandlerMapping/*** Abstract template method to be implemented by subclasses.* @param beanName the name of the bean* @param beanClass the type of the bean* @return the URLs determined for the bean*/protected abstract String[] buildUrlsForHandler(String beanName, Class beanClass); 

再來看看AbstractControllerUrlHandlerMapping的2個實現ControllerBeanNameUrlHandlerMapping和ControllerClassNameUrlHandlerMapping.

其實這兩個,很簡單,一個是根據beanName來生產url,一個是根據className來生產url.

// ControllerBeanNameUrlHandlerMapping@Overrideprotected String[] buildUrlsForHandler(String beanName, Class beanClass) {List<String> urls = new ArrayList<String>();urls.add(generatePathMapping(beanName));String[] aliases = getApplicationContext().getAliases(beanName);// 也獲取配置的別名for (String alias : aliases) {urls.add(generatePathMapping(alias));}return StringUtils.toStringArray(urls);} // ControllerBeanNameUrlHandlerMapping/**對path添加前后綴,還有/* Prepends a '/' if required and appends the URL suffix to the name.*/protected String generatePathMapping(String beanName) {String name = (beanName.startsWith("/") ? beanName : "/" + beanName);StringBuilder path = new StringBuilder();if (!name.startsWith(this.urlPrefix)) {path.append(this.urlPrefix);}path.append(name);if (!name.endsWith(this.urlSuffix)) {path.append(this.urlSuffix);}return path.toString();} // ControllerClassNameUrlHandlerMapping

直接委托給generatePathMappings實現

@Overrideprotected String[] buildUrlsForHandler(String beanName, Class beanClass) {return generatePathMappings(beanClass);} // ControllerClassNameUrlHandlerMapping

  通過buildPathPrefix獲取path的前綴

  通過ClassUtils獲取className,如BookController(不帶包名),同時使用cglib代理的問題一并解決

  根據大小寫是否敏感,轉換className(默認caseSensitive = false;)

  isMultiActionControllerType判斷Controller是否MultiActionController的子類,就是controller是否包含多個handler

/*** Generate the actual URL paths for the given controller class.* <p>Subclasses may choose to customize the paths that are generated* by overriding this method.* @param beanClass the controller bean class to generate a mapping for* @return the URL path mappings for the given controller*/protected String[] generatePathMappings(Class beanClass) {StringBuilder pathMapping = buildPathPrefix(beanClass);String className = ClassUtils.getShortName(beanClass);String path = (className.endsWith(CONTROLLER_SUFFIX) ?className.substring(, className.lastIndexOf(CONTROLLER_SUFFIX)) : className);if (path.length() > ) {if (this.caseSensitive) {pathMapping.append(path.substring(, ).toLowerCase()).append(path.substring());}else {pathMapping.append(path.toLowerCase());}}if (isMultiActionControllerType(beanClass)) {return new String[] {pathMapping.toString(), pathMapping.toString() + "/*"};}else {return new String[] {pathMapping.toString() + "*"};}} // ControllerClassNameUrlHandlerMapping/*** Build a path prefix for the given controller bean class.* @param beanClass the controller bean class to generate a mapping for* @return the path prefix, potentially including subpackage names as path elements*/private StringBuilder buildPathPrefix(Class beanClass) {StringBuilder pathMapping = new StringBuilder();if (this.pathPrefix != null) {pathMapping.append(this.pathPrefix);pathMapping.append("/");}else {pathMapping.append("/");}if (this.basePackage != null) {String packageName = ClassUtils.getPackageName(beanClass);if (packageName.startsWith(this.basePackage)) {String subPackage = packageName.substring(this.basePackage.length()).replace('.', '/');pathMapping.append(this.caseSensitive ? subPackage : subPackage.toLowerCase());pathMapping.append("/");}}return pathMapping;} // AbstractControllerUrlHandlerMapping

predicate.isMultiActionControllerType具體實現看上面的ControllerTypePredicate

/*** Determine whether the given bean class indicates a controller type* that dispatches to multiple action methods.* @param beanClass the class to introspect*/protected boolean isMultiActionControllerType(Class beanClass) {return this.predicate.isMultiActionControllerType(beanClass);}

以上所述是小編給大家介紹的SpringMVC源碼解讀之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化的相關知識,希望對大家有所幫助!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 资中县| 昌宁县| 皮山县| 靖江市| 昌江| 阳信县| 仪征市| 青龙| 开化县| 容城县| 光山县| 奉新县| 嫩江县| 呼图壁县| 聂拉木县| 长葛市| 望江县| 板桥市| 田东县| 分宜县| 醴陵市| 遵化市| 庄河市| 通海县| 沿河| 怀宁县| 神农架林区| 淅川县| 华坪县| 黄龙县| 裕民县| 疏勒县| 洛扎县| 宜州市| 龙南县| 浦县| 武川县| 济宁市| 普兰店市| 江津市| 青铜峡市|