程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> SpringMVC源碼解讀之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化

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

編輯:關於JAVA

SpringMVC源碼解讀之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化。本站提示廣大學習愛好者:(SpringMVC源碼解讀之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化)文章只能為提供參考,不一定能成為您想要的結果。以下是SpringMVC源碼解讀之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化正文


 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.
*/
@Override
public 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 "/".
*/
@Override
protected 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}.
*/
@Override
protected 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
@Override
protected 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完成

@Override
protected 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系列初始化的相干常識,願望對年夜家有所贊助!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved