欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2016年02月25日 09:46:07   作者:出門向左  
這篇文章主要介紹了SpringMVC源碼解讀之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化的相關(guān)資料,需要的朋友可以參考下

 AbstractDetectingUrlHandlerMapping是通過掃描方式注冊(cè)Handler,收到請(qǐng)求時(shí)由AbstractUrlHandlerMapping的getHandlerInternal進(jìn)行分發(fā).

共有5個(gè)子類,一個(gè)抽象類.

與SimpleUrlHandlerMapping類似,通過覆寫initApplicationContext,然后調(diào)用detectHandlers進(jìn)行初始化.

detectHandlers通過BeanFactoryUtils掃描應(yīng)用下的Object,然后預(yù)留determineUrlsForHandler給子類根據(jù)Handler生成對(duì)應(yīng)的url.

注冊(cè)使用的registerHandler依然由AbstractUrlHandlerMapping提供.

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

這邊一樣是調(diào)用AbstractHandlerMapping的initApplicationContext初始化攔截器.

主角上場(chǎng),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");
}
}
}
}

這邊預(yù)留的模板方法定義如下:

/**
* 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); 

我們?cè)賮砜纯茨0宸椒ㄔ贐eanNameUrlHandlerMapping和AbstractControllerUrlHandlerMapping中的實(shí)現(xiàn)吧.

BeanNameUrlHandlerMapping非常簡(jiǎn)單,就實(shí)現(xiàn)了determineUrlsForHandler.

其中的alias應(yīng)該是應(yīng)該就是通過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中的實(shí)現(xiàn)

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

  buildUrlsForHandler由子類實(shí)現(xiàn)具體的url生成規(guī)則

  isControllerType判斷是否Controller的子類

  buildUrlsForHandler預(yù)留給子類生產(chǎn)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個(gè)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);
}
}

預(yù)留生成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個(gè)實(shí)現(xiàn)ControllerBeanNameUrlHandlerMapping和ControllerClassNameUrlHandlerMapping.

其實(shí)這兩個(gè),很簡(jiǎn)單,一個(gè)是根據(jù)beanName來生產(chǎn)url,一個(gè)是根據(jù)className來生產(chǎn)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
/**對(duì)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實(shí)現(xiàn)

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

  通過buildPathPrefix獲取path的前綴

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

  根據(jù)大小寫是否敏感,轉(zhuǎn)換className(默認(rèn)caseSensitive = false;)

  isMultiActionControllerType判斷Controller是否MultiActionController的子類,就是controller是否包含多個(gè)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具體實(shí)現(xiàn)看上面的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系列初始化的相關(guān)知識(shí),希望對(duì)大家有所幫助!

相關(guān)文章

  • Netty學(xué)習(xí)教程之Netty與Marshalling結(jié)合發(fā)送對(duì)象

    Netty學(xué)習(xí)教程之Netty與Marshalling結(jié)合發(fā)送對(duì)象

    Netty是由JBOSS提供的一個(gè)Java開源框架,之前已經(jīng)給大家簡(jiǎn)單介紹了一些基礎(chǔ)與使用,下面這篇文章主要給大家介紹了關(guān)于Netty與Marshalling結(jié)合發(fā)送對(duì)象的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-05-05
  • IntelliJ IDEA中Scala、sbt、maven配置教程

    IntelliJ IDEA中Scala、sbt、maven配置教程

    這篇文章主要介紹了IntelliJ IDEA中Scala、sbt、maven配置教程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 一文帶你了解Java中的ForkJoin

    一文帶你了解Java中的ForkJoin

    這篇文章主要介紹了一文帶你了解Java中的ForkJoin,F(xiàn)orkJoinTask本身的依賴關(guān)系并不復(fù)雜,它與異步任務(wù)計(jì)算FutureTask一樣均實(shí)現(xiàn)了Future接口,下文更多相關(guān)資料,需要的小伙伴可以參考一下
    2022-04-04
  • springboot使用JdbcTemplate完成對(duì)數(shù)據(jù)庫的增刪改查功能

    springboot使用JdbcTemplate完成對(duì)數(shù)據(jù)庫的增刪改查功能

    這篇文章主要介紹了springboot使用JdbcTemplate完成對(duì)數(shù)據(jù)庫的增刪改查功能,需要的朋友可以參考下
    2017-12-12
  • Mybatis結(jié)果集映射與生命周期詳細(xì)介紹

    Mybatis結(jié)果集映射與生命周期詳細(xì)介紹

    結(jié)果集映射指的是將數(shù)據(jù)表中的字段與實(shí)體類中的屬性關(guān)聯(lián)起來,這樣 MyBatis 就可以根據(jù)查詢到的數(shù)據(jù)來填充實(shí)體對(duì)象的屬性,幫助我們完成賦值操作
    2022-10-10
  • 詳解Spring bean的注解注入之@Autowired的原理及使用

    詳解Spring bean的注解注入之@Autowired的原理及使用

    之前講過bean注入是什么,也使用了xml的配置文件進(jìn)行bean注入,這也是Spring的最原始的注入方式(xml注入).本文主要講解的注解有以下幾個(gè):@Autowired、 @Service、@Repository、@Controller 、@Component、@Bean、@Configuration、@Resource ,需要的朋友可以參考下
    2021-06-06
  • java引用jpython的方法示例

    java引用jpython的方法示例

    這篇文章主要介紹了java引用jpython的方法,結(jié)合實(shí)例形式分析了java引用jpython及相關(guān)使用技巧,需要的朋友可以參考下
    2016-11-11
  • java?百度手寫文字識(shí)別接口配置代碼

    java?百度手寫文字識(shí)別接口配置代碼

    本文通過實(shí)例代碼給大家介紹了java?百度手寫文字識(shí)別接口配置方法,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2022-01-01
  • java去除中文括號(hào)小括號(hào),或者英文括號(hào)的實(shí)例代碼

    java去除中文括號(hào)小括號(hào),或者英文括號(hào)的實(shí)例代碼

    這篇文章主要介紹了java去除中文括號(hào)小括號(hào),或者英文括號(hào)的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Springboot敏感字段脫敏的實(shí)現(xiàn)思路

    Springboot敏感字段脫敏的實(shí)現(xiàn)思路

    這篇文章主要介紹了Springboot敏感字段脫敏的實(shí)現(xiàn)思路,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09

最新評(píng)論