- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章SpringMVC源码解读之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
AbstractDetectingUrlHandlerMapping是通过扫描方式注册Handler,收到请求时由AbstractUrlHandlerMapping的getHandlerInternal进行分发. 。
共有5个子类,一个抽象类. 。
与SimpleUrlHandlerMapping类似,通过覆写initApplicationContext,然后调用detectHandlers进行初始化. 。
detectHandlers通过BeanFactoryUtils扫描应用下的Object,然后预留determineUrlsForHandler给子类根据Handler生成对应的url. 。
注册使用的registerHandler依然由AbstractUrlHandlerMapping提供. 。
1
2
3
4
5
6
7
8
9
10
|
// 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 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
// 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"
);
}
}
}
}
|
这边预留的模板方法定义如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/**
* 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的模板方法. 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
// 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的模板方法 。
1
2
3
4
5
6
7
8
|
// 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. 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
// 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实现 。
1
2
3
4
5
|
@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 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
/**
* 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 。
1
2
3
4
5
6
7
8
|
/**
* 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系列初始化的相关知识,希望对大家有所帮助! 。
最后此篇关于SpringMVC源码解读之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化的文章就讲到这里了,如果你想了解更多关于SpringMVC源码解读之 HandlerMapping - AbstractDetectingUrlHandlerMapping系列初始化的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是 Spring 新手,这就是我想要做的事情: 我正在使用一个基于 Maven 的库,它有自己的 Spring 上下文和 Autowiring 字段。 它的bean配置文件是src/test/res
我在我的测试脚本中有以下列表初始化: newSequenceCore=["ls", "ns", "*", "cm", "*", "ov", "ov", "ov", "ov", "kd"] (代表要在控
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Class construction with initial values 当我查看 http://en.
我得到了成员变量“objectCount”的限定错误。编译器还返回“ISO C++ 禁止非常量静态成员的类内初始化”。这是主类: #include #include "Tree.h" using n
我有如下所示的a.h class A { public: void doSomething()=0; }; 然后我有如下所示的b.h #include "a.h" class b: publi
我需要解析 Firebase DataSnapshot (一个 JSON 对象)转换成一个数据类,其属性包括 enum 和 list。所以我更喜欢通过传递 DataSnapshot 来手动解析它进入二
我使用 JQuery 一段时间了,我总是使用以下代码来初始化我的 javascript: $(document).ready( function() { // Initalisation logic
这里是 Objective-C 菜鸟。 为什么会这样: NSString *myString = [NSString alloc]; [myString initWithFormat:@"%f", s
我无法让核心数据支持的 NSArrayController 在我的代码中正常工作。下面是我的代码: pageArrayController = [[NSArrayController alloc] i
我对这一切都很陌生,并且无法将其安装到我的后端代码中。它去哪里?在我的页脚下面有我所有的 JS? 比如,这是什么意思: Popup initialization code should be exec
这可能是一个简单的问题,但是嘿,我是初学者。 所以我创建了一个程序来计算一些东西,它目前正在控制台中运行。我决定向其中添加一个用户界面,因此我使用 NetBeans IDE 中的内置功能创建了一个 J
我有 2 个 Controller ,TEST1Controller 和 TEST2Controller 在TEST2Controller中,我有一个initialize()函数设置属性值。 如果我尝
据我所知, dependentObservable 在声明时会进行计算。但如果某些值尚不存在怎么办? 例如: var viewModel ={}; var dependentObservable1 =
我正在阅读 POODR 这本书,它使用旧语法进行默认值初始化。我想用新语法实现相同的功能。 class Gear attr_reader :chainring, :cog, :wheel de
我按照 polymer 教程的说明进行操作: https://www.polymer-project.org/3.0/start/install-3-0 (我跳过了可选部分) 但是,在我执行命令“po
很抱歉问到一个非常新手的Kotlin问题,但是我正在努力理解与构造函数和初始化有关的一些东西。 我有这个类和构造函数: class TestCaseBuilder constructor(
假设我们有一个包含 30 列和 30 行的网格。 生命游戏规则简而言之: 一个小区有八个相邻小区 当一个细胞拥有三个存活的相邻细胞时,该细胞就会存活 如果一个细胞恰好有两个或三个活的相邻细胞,那么它就
我是 MQTT 和 Android 开放附件“AOA” 的新手。在阅读教程时,我意识到,在尝试写入 ByteArrayOutputStream 类型的变量之前,应该写入 0 或 0x00首先到该变量。
我有 2 个 Controller ,TEST1Controller 和 TEST2Controller 在TEST2Controller中,我有一个initialize()函数设置属性值。 如果我尝
我有一个inotify /内核问题。我正在使用“inotify” Python项目进行观察,但是,我的问题仍然是固有的关于inotify内核实现的核心。 Python inotify项目处理递归ino
我是一名优秀的程序员,十分优秀!