mvc:annotation-driven

<mvc:annotation-driven />这个标签注册了Spring MVC分发请求到Controller控制器所必须的HandlerMapping和HandlerAdapter实例。

Spring 3.1 之前:

  1. DefaultAnnotationHandlerMapping
  2. AnnotationMethodHandlerAdapter
  3. AnnotationMethodHandlerExceptionResolver

Spring 3.1+ :

  1. RequestMappingHandlerMapping
  2. RequestMappingHandlerAdapter
  3. ExceptionHandlerExceptionResolver

DefaultAnnotationHandlerMapping 根据url决定使用哪个controllerAnnotationMethodHandlerAdapter 选择处理请求的实际方法。RequestMappingHandlerMapping包涵上面2个作用,所以将请求直接映射到方法。

源码分析

DispatcherServlet初始化的时候,会调用一个方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
//初始化一些HandlerMapping
initHandlerMappings(context);
//初始化一些HandlerAdapter
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}

它会初始化一些HandlerMappingHandlerAdapter,这两个方法非常重要

  • 初始化HandlerMapping
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
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
OrderComparator.sort(this.handlerMappings);
}
}
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}

detectAllHandlerMappingsDispatcherServlet的一个属性,可以在web.xml中配置,默认是true,如果为true,则会去从本工程mvc-servlet.xml文件中去探测所有实现了HandlerMapping的bean,如果有,则加入DispatcherServlethandlerMappings中。如果detectAllHandlerMappings为false,则直接去容器中找id="handlerMapping"且实现了HandlerMapping的bean.如果以上都没找到,则会去加载默认的HandlerMapping

1
2
/** Detect all HandlerMappings or just expect "handlerMapping" bean? */
private boolean detectAllHandlerMappings = true;

如果没有配置HandlerMapping,所以它会去加载默认的,默认的配置如下:

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
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
String key = strategyInterface.getName();
//defaultStrategies存储了默认的配置
String value = defaultStrategies.getProperty(key);
if (value != null) {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<T>(classNames.length);
for (String className : classNames) {
try {
Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
catch (ClassNotFoundException ex) {
throw new BeanInitializationException(
"Could not find DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]", ex);
}
catch (LinkageError err) {
throw new BeanInitializationException(
"Error loading DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]: problem with class file or dependent class", err);
}
}
return strategies;
}
else {
return new LinkedList<T>();
}
}

看看defaultStrategies是如何初始化的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static final Properties defaultStrategies;
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
try {
//这里的DEFAULT_STRATEGIES_PATH就是DispatcherServlet.properties
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
}
}

这里使用静态代码块来加载配置文件DispatcherServlet.properties,它所在位置就是和DispatcherServlet同一目录下面。默认的配置文件的内容如下:

1
2
3
4
5
6
7
8
9
10
11
#这里就是默认的HandlerMapping的配置
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
#这里就是默认的HandlerAdapter的配置
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

也就是说,当你什么都没有配置时,默认会加载以上的配置

默认HandlerMapping:

1
2
BeanNameUrlHandlerMapping
DefaultAnnotationHandlerMapping

默认HandlerAdapter:

1
2
3
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapter
AnnotationMethodHandlerAdapter

参考:

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

http://shouce.jb51.net/spring/mvc.html

热评文章