- 浏览: 984873 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
前面我们讲解过DispatcherServlet:http://donald-draper.iteye.com/blog/2325394
Spring-DispatcherServlet请求处理:http://donald-draper.iteye.com/blog/2325415
下面我们来看看DispatcherServlet的handlerMappings初始化所做的事情
//Spring日志追踪我们可以发现,DispatcherServletd的控制器映射处理器为
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
//静态文件的映射js,css等
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
这里我们来讲默认注解控制器映射处理器DefaultAnnotationHandlerMapping
查看AbstractDetectingUrlHandlerMapping
查看AbstractUrlHandlerMapping
查看AbstractHandlerMapping
查看WebApplicationObjectSupport
查看ApplicationObjectSupport
好了,看到这里,我们知道一二,再看AbstractDetectingUrlHandlerMapping
查看DefaultAnnotationHandlerMapping
//RequestMapping
再来看registerHandler方法
//注册urls,与beanName的映射
registerHandler(urls, beanName);
//AbstractHandlerMapping
总结:
DefaultAnnotationHandlerMapping主要做的事情是,
将Controller的RequestMapping注解值(类路径及方法路径)与Controller实例映射起来
Spring-DispatcherServlet请求处理:http://donald-draper.iteye.com/blog/2325415
下面我们来看看DispatcherServlet的handlerMappings初始化所做的事情
public class DispatcherServlet extends FrameworkServlet { public DispatcherServlet(WebApplicationContext webApplicationContext) { super(webApplicationContext); detectAllHandlerMappings = true; detectAllHandlerAdapters = true; detectAllHandlerExceptionResolvers = true; detectAllViewResolvers = true; throwExceptionIfNoHandlerFound = false; cleanupAfterInclude = true; } //初始化控制器映射 private void initHandlerMappings(ApplicationContext context) { handlerMappings = null; if(detectAllHandlerMappings) { Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, org/springframework/web/servlet/HandlerMapping, true, false); if(!matchingBeans.isEmpty()) { //List<HashMap<String,HandlerMapping>>,Key为beanName,value值为HandlerMapping实例 handlerMappings = new ArrayList(matchingBeans.values()); OrderComparator.sort(handlerMappings); } } } //初始化控制器方法适配器 private void initHandlerAdapters(ApplicationContext context) { handlerAdapters = null; if(detectAllHandlerAdapters) { Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, org/springframework/web/servlet/HandlerAdapter, true, false); if(!matchingBeans.isEmpty()) { //List<HashMap<String,HandlerAdapter>>,Key为beanName,value值为HandlerAdapter实例 handlerAdapters = new ArrayList(matchingBeans.values()); OrderComparator.sort(handlerAdapters); } } } private List handlerMappings;//List<HashMap<String,HandlerMapping>>,Key为beanName,value值为HandlerMapping实例 private List handlerAdapters;//List<HashMap<String,HandlerAdapter>>,Key为beanName,value值为HandlerAdapter实例 private List handlerExceptionResolvers; private List viewResolvers; static { try { //加载默认配置文件 ClassPathResource resource = new ClassPathResource("DispatcherServlet.properties", org/springframework/web/servlet/DispatcherServlet); defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } } }
//Spring日志追踪我们可以发现,DispatcherServletd的控制器映射处理器为
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
//静态文件的映射js,css等
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
这里我们来讲默认注解控制器映射处理器DefaultAnnotationHandlerMapping
public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping { public DefaultAnnotationHandlerMapping() { useDefaultSuffixPattern = true; } public void setUseDefaultSuffixPattern(boolean useDefaultSuffixPattern) { this.useDefaultSuffixPattern = useDefaultSuffixPattern; } //这里我们找不到任何头绪 }
查看AbstractDetectingUrlHandlerMapping
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping { public AbstractDetectingUrlHandlerMapping() { detectHandlersInAncestorContexts = false; } public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts) { this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts; } //初始化应用上下文,这里好像有点头绪 public void initApplicationContext() throws ApplicationContextException { //查看父类 super.initApplicationContext(); detectHandlers(); } }
查看AbstractUrlHandlerMapping
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { //没有任何迹象 }
查看AbstractHandlerMapping
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered { //貌似有点头绪 protected void initApplicationContext() throws BeansException { extendInterceptors(interceptors); detectMappedInterceptors(mappedInterceptors); //初始化拦截器 initInterceptors(); } }
查看WebApplicationObjectSupport
public abstract class WebApplicationObjectSupport extends ApplicationObjectSupport implements ServletContextAware { //还是没看到怎么回事 protected void initApplicationContext(ApplicationContext context) { super.initApplicationContext(context); if(servletContext == null && (context instanceof WebApplicationContext)) { servletContext = ((WebApplicationContext)context).getServletContext(); if(servletContext != null) initServletContext(servletContext); } } protected void initServletContext(ServletContext servletcontext) { } }
查看ApplicationObjectSupport
public abstract class ApplicationObjectSupport implements ApplicationContextAware { public final void setApplicationContext(ApplicationContext context) throws BeansException { if(context == null && !isContextRequired()) { applicationContext = null; messageSourceAccessor = null; } else if(applicationContext == null) { //关键,是不是有点意思了 initApplicationContext(context); } } protected void initApplicationContext(ApplicationContext context) throws BeansException { initApplicationContext(); } //留给子类扩展 protected void initApplicationContext() throws BeansException { } }
好了,看到这里,我们知道一二,再看AbstractDetectingUrlHandlerMapping
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping { public AbstractDetectingUrlHandlerMapping() { detectHandlersInAncestorContexts = false; } public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts) { this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts; } //初始化应用上下文, public void initApplicationContext() throws ApplicationContextException { //初始化父类应用上下文 super.initApplicationContext(); //探测Handlers detectHandlers(); } protected void detectHandlers() throws BeansException { if(logger.isDebugEnabled()) logger.debug((new StringBuilder()).append("Looking for URL mappings in application context: ").append(getApplicationContext()).toString()); String beanNames[] = detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), java/lang/Object) : getApplicationContext().getBeanNamesForType(java/lang/Object); String as[] = beanNames; int i = as.length; for(int j = 0; j < i; j++) { String beanName = as[j]; //获取处理器的urls String urls[] = determineUrlsForHandler(beanName); if(!ObjectUtils.isEmpty(urls)) { //注册urls,与beanName的映射 registerHandler(urls, beanName); continue; } } } //获取处理器的urls,父类扩展 protected abstract String[] determineUrlsForHandler(String s); }
查看DefaultAnnotationHandlerMapping
public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping { protected String[] determineUrlsForHandler(String beanName) { ApplicationContext context = getApplicationContext(); Class handlerType = context.getType(beanName); //获取beanName的@RequestMapping RequestMapping mapping = (RequestMapping)context.findAnnotationOnBean(beanName, org/springframework/web/bind/annotation/RequestMapping); if(mapping != null) { cachedMappings.put(handlerType, mapping); Set urls = new LinkedHashSet(); String typeLevelPatterns[] = mapping.value(); if(typeLevelPatterns.length > 0) { //获取Controller方法urls String methodLevelPatterns[] = determineUrlsForHandlerMethods(handlerType, true); String as[] = typeLevelPatterns; int i = as.length; for(int j = 0; j < i; j++) { String typeLevelPattern = as[j]; //不以/开头,添加/ if(!typeLevelPattern.startsWith("/")) typeLevelPattern = (new StringBuilder()).append("/").append(typeLevelPattern).toString(); boolean hasEmptyMethodLevelMappings = false; String as1[] = methodLevelPatterns; int k = as1.length; for(int l = 0; l < k; l++) { String methodLevelPattern = as1[l]; if(methodLevelPattern == null) { hasEmptyMethodLevelMappings = true; } else { String combinedPattern = getPathMatcher().combine(typeLevelPattern, methodLevelPattern); addUrlsForPath(urls, combinedPattern); } } //bean带@Controller注解添加Path到urls if(hasEmptyMethodLevelMappings || org/springframework/web/servlet/mvc/Controller.isAssignableFrom(handlerType)) addUrlsForPath(urls, typeLevelPattern); } return StringUtils.toStringArray(urls); } else { return determineUrlsForHandlerMethods(handlerType, false); } } if(AnnotationUtils.findAnnotation(handlerType, org/springframework/stereotype/Controller) != null) return determineUrlsForHandlerMethods(handlerType, false); else return null; } //获取方法urls protected String[] determineUrlsForHandlerMethods(Class handlerType, final boolean hasTypeLevelMapping) { String subclassResult[] = determineUrlsForHandlerMethods(handlerType); if(subclassResult != null) return subclassResult; final Set urls = new LinkedHashSet(); Set handlerTypes = new LinkedHashSet(); handlerTypes.add(handlerType); handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces())); Class currentHandlerType; for(Iterator iterator = handlerTypes.iterator(); iterator.hasNext(); ReflectionUtils.doWithMethods(currentHandlerType, new org.springframework.util.ReflectionUtils.MethodCallback() { public void doWith(Method method) { //获取bean方法method的@RequestMapping RequestMapping mapping = (RequestMapping)AnnotationUtils.findAnnotation(method, org/springframework/web/bind/annotation/RequestMapping); if(mapping != null) { String mappedPatterns[] = mapping.value(); if(mappedPatterns.length > 0) { String as[] = mappedPatterns; int i = as.length; for(int j = 0; j < i; j++) { String mappedPattern = as[j]; //不以/开头,添加/ if(!hasTypeLevelMapping && !mappedPattern.startsWith("/")) mappedPattern = (new StringBuilder()).append("/").append(mappedPattern).toString(); //添加method的Path到urls addUrlsForPath(urls, mappedPattern); } } else if(hasTypeLevelMapping) urls.add(null); } } final boolean val$hasTypeLevelMapping; final Set val$urls; final DefaultAnnotationHandlerMapping this$0; { this.this$0 = DefaultAnnotationHandlerMapping.this; hasTypeLevelMapping = flag; urls = set; super(); } }, ReflectionUtils.USER_DECLARED_METHODS)) currentHandlerType = (Class)iterator.next(); return StringUtils.toStringArray(urls); } //默认返回的urls为null protected String[] determineUrlsForHandlerMethods(Class handlerType) { return null; } //添加path到urls-set protected void addUrlsForPath(Set urls, String path) { urls.add(path); if(useDefaultSuffixPattern && path.indexOf('.') == -1 && !path.endsWith("/")) { urls.add((new StringBuilder()).append(path).append(".*").toString()); urls.add((new StringBuilder()).append(path).append("/").toString()); } } private final Map cachedMappings = new HashMap();//HashMap<Class,RequestMapping>,key为Controller类,value为RequestMapping }
//RequestMapping
public interface RequestMapping extends Annotation { public abstract String[] value(); public abstract RequestMethod[] method(); public abstract String[] params(); public abstract String[] headers(); public abstract String[] consumes(); public abstract String[] produces(); }
再来看registerHandler方法
//注册urls,与beanName的映射
registerHandler(urls, beanName);
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping { //注册urlPaths,与beanName的映射 protected void registerHandler(String urlPaths[], String beanName) throws BeansException, IllegalStateException { Assert.notNull(urlPaths, "URL path array must not be null"); String as[] = urlPaths; int i = as.length; for(int j = 0; j < i; j++) { String urlPath = as[j]; registerHandler(urlPath, beanName); } } //注册urlPath,与beanName的映射 protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { Object resolvedHandler = handler; if(!lazyInitHandlers && (handler instanceof String)) { String handlerName = (String)handler; if(getApplicationContext().isSingleton(handlerName)) //获取bean实例,实际Controller实例 resolvedHandler = getApplicationContext().getBean(handlerName); } Object mappedHandler = handlerMap.get(urlPath); if(mappedHandler != null) { //如果urlPath已经存在,抛出异常 if(mappedHandler != resolvedHandler) throw new IllegalStateException((new StringBuilder()).append("Cannot map ").append(getHandlerDescription(handler)).append(" to URL path [").append(urlPath).append("]: There is already ").append(getHandlerDescription(mappedHandler)).append(" mapped.").toString()); } else if(urlPath.equals("/")) { if(logger.isInfoEnabled()) logger.info((new StringBuilder()).append("Root mapping to ").append(getHandlerDescription(handler)).toString()); //如果以/开头设为根处理器 setRootHandler(resolvedHandler); } else if(urlPath.equals("/*")) { if(logger.isInfoEnabled()) logger.info((new StringBuilder()).append("Default mapping to ").append(getHandlerDescription(handler)).toString()); //如果以/开头设为默认处理器 setDefaultHandler(resolvedHandler); } else { //添加url路径与Handler映射到handlerMap handlerMap.put(urlPath, resolvedHandler); if(logger.isInfoEnabled()) logger.info((new StringBuilder()).append("Mapped URL path [").append(urlPath).append("] onto ").append(getHandlerDescription(handler)).toString()); } } //设置根处理器 public void setRootHandler(Object rootHandler) { this.rootHandler = rootHandler; } //根据urlPath,寻找Handler protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { Object handler = handlerMap.get(urlPath); if(handler != null) { if(handler instanceof String) { String handlerName = (String)handler; handler = getApplicationContext().getBean(handlerName); } validateHandler(handler, request); return buildPathExposingHandler(handler, urlPath, urlPath, null); } List matchingPatterns = new ArrayList(); String bestPatternMatch = handlerMap.keySet().iterator(); do { if(!bestPatternMatch.hasNext()) break; String registeredPattern = (String)bestPatternMatch.next(); if(getPathMatcher().match(registeredPattern, urlPath)) matchingPatterns.add(registeredPattern); } while(true); bestPatternMatch = null; Comparator patternComparator = getPathMatcher().getPatternComparator(urlPath); if(!matchingPatterns.isEmpty()) { Collections.sort(matchingPatterns, patternComparator); if(logger.isDebugEnabled()) logger.debug((new StringBuilder()).append("Matching patterns for request [").append(urlPath).append("] are ").append(matchingPatterns).toString()); bestPatternMatch = (String)matchingPatterns.get(0); } if(bestPatternMatch != null) { handler = handlerMap.get(bestPatternMatch); if(handler instanceof String) { String handlerName = (String)handler; handler = getApplicationContext().getBean(handlerName); } validateHandler(handler, request); String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath); Map uriTemplateVariables = new LinkedHashMap(); Iterator iterator = matchingPatterns.iterator(); do { if(!iterator.hasNext()) break; String matchingPattern = (String)iterator.next(); if(patternComparator.compare(bestPatternMatch, matchingPattern) == 0) { Map vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); Map decodedVars = getUrlPathHelper().decodePathVariables(request, vars); uriTemplateVariables.putAll(decodedVars); } } while(true); if(logger.isDebugEnabled()) logger.debug((new StringBuilder()).append("URI Template variables for request [").append(urlPath).append("] are ").append(uriTemplateVariables).toString()); return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables); } else { return null; } } private Object rootHandler; private boolean lazyInitHandlers; private final Map handlerMap = new LinkedHashMap();//LinkedHashMap<String,Object>,key为urlPath,value为对应的handler }
//AbstractHandlerMapping
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered { //设置默认Handler public void setDefaultHandler(Object defaultHandler) { this.defaultHandler = defaultHandler; } private int order; private Object defaultHandler; private UrlPathHelper urlPathHelper; private PathMatcher pathMatcher; private final List interceptors = new ArrayList(); private final List adaptedInterceptors = new ArrayList(); private final List mappedInterceptors = new ArrayList(); }
总结:
DefaultAnnotationHandlerMapping主要做的事情是,
将Controller的RequestMapping注解值(类路径及方法路径)与Controller实例映射起来
发表评论
-
Spring的RequestMappingHandlerMapping详解
2016-09-23 08:40 4605深刻理解IdentityHashMap:http://dona ... -
Spring-RequestMappingHandlerAdapter初始化及请求处理
2016-09-22 11:50 10583看这篇文章之前,最好先看下面这篇,以便更好的理解handler ... -
Spring+Mybatis多数据源的实现
2016-09-21 18:15 3095浅谈Spring事务隔离级别:http://www.cnblo ... -
Spring-DispatcherServlet请求处理
2016-09-19 15:42 1690Spring-DispatcherServlet初始化详解:h ... -
Spring-DispatcherServlet初始化详解
2016-09-19 15:03 3700Spring-DispatcherServlet请求处理:ht ... -
Spring上下文加载监听器ContextLoaderListener--源码解析
2016-09-18 18:10 4672一般在web应用配置Spring上下文如下,那么Context ... -
JobDetailFactoryBean与MethodInvokingJobDetailFactoryBean源码分析
2016-09-13 16:07 4322Spring与Quartz集成详解:http://donald ... -
Spring与Quartz集成-源码分析
2016-09-13 11:50 2723在阅读以下文章之前,如果对Quartz任务调度不是很熟悉,请看 ... -
Spring与Quartz集成详解
2016-09-09 17:52 2824首先这个所有的依赖包就不需要多讲了,首先下载Quazrt发布包 ... -
Spring,ApplicationContextAware的作用
2016-08-24 17:38 7引用:http://blog.csdn.net/kaiwii/ ... -
Spring Interceptor
2016-05-31 17:12 579Spring Interceptor相关知识:http://h ... -
基于注解的Spring AOP
2016-05-31 16:05 927Spring AOP 基本概念:http://hotstron ... -
Spring的Task定时器
2016-05-31 10:34 7131.开启注解,定义扫描包 <mvc:annotation ...
相关推荐
Spring提供多种HandlerMapping实现,如BeanNameUrlHandlerMapping、DefaultAnnotationHandlerMapping等。 3. Controller:处理业务逻辑的组件,通常是一个实现了Controller接口或带有@Controller注解的类。...
Spring3MVC 注解详解 Spring3MVC 注解是基于 Java 的 Spring 框架中的一种编程模型,旨在简化 Web 应用程序的开发。下面将详细介绍 Spring3MVC 注解的概念、实现机制、配置方法和实践示例。 Spring3MVC 注解的...
### Spring MVC 教程知识点详解 #### 一、Spring MVC 概述 Spring MVC 是 Spring 框架的一部分,主要用于构建基于 Java 的 Web 应用程序。它是一种模型-视图-控制器(Model-View-Controller,MVC)设计模式的实现...
### Spring3.0MVC注解详解 #### 注解支持的Web应用程序示例 - **PetClinic**:这是一个随Spring发行版本一起提供的示例应用,主要展示了如何在简单的表单处理场景中运用注解来构建Web应用。PetClinic应用位于...
### Spring Web 3.0 MVC 注解详解及实例 #### 一、概述 Spring Web MVC 是 Spring Framework 的一部分,提供了一种强大而灵活的方式来构建基于 Web 的应用。随着 Spring 3.0 的发布,框架引入了一系列重要的改进,...
#### 三、Spring MVC 示例详解 根据题目提供的部分代码示例,我们可以进一步了解 Spring MVC 的基本使用方式。 ##### 1. HelloWorldController 类 ```java package org.spring.mvc; import org.slf4j.Logger; ...
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <!-- 2. 配置 AnnotationMethodHandlerAdapter --> <bean class="org.springframework.web.servlet.mvc....
### Spring MVC的核心概念与应用详解 #### 一、Spring MVC概述 **Spring MVC**是Spring框架的一个重要组成部分,它提供了一种实现Web MVC设计模式的轻量级解决方案。该框架旨在帮助开发者简化Web应用程序的开发...
《Spring 2.5.6:基础模板配置详解》 Spring 框架自诞生以来,就以其强大的依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)能力,成为了Java开发中的核心框架之一。在...
### Spring MVC 框架详解 #### 一、Spring MVC 的优势 Spring MVC 作为一款优秀的模型-视图-控制器(MVC)框架,在实际应用中展现出了诸多优点,尤其在其3.0版本之后,越来越多的开发团队选择采用 Spring MVC。 1...
### Spring框架的重要知识点详解 #### 1. **注解驱动** Spring 3.0对注解的支持进一步增强,使得开发者能够以更简洁的方式进行组件的定义和配置。例如: - **@Controller**:标记一个类作为Web层的控制器,通常...
`dispatcher.xml`是Spring MVC的配置文件,这里定义了扫描注解的包`<context:component-scan>`,默认注解处理器`DefaultAnnotationHandlerMapping`以及处理控制器的适配器`HandlerAdapter`。这些配置使得Spring MVC...
**Spring3 MVC 知识点详解** Spring3 MVC 是一款高度灵活、性能优秀的MVC框架,自3.0版本发布以来,受到了许多开发团队的青睐。它的简洁设计和强大的功能使其成为Java Web开发中的热门选择。相较于Struts2,Spring3...
#### 四、Spring MVC 配置详解 - **Spring MVC 配置文件**:通常包含在项目中的 `spring-mvc.xml` 文件里。该文件用于配置 DispatcherServlet 的行为,以及 HandlerMapping、HandlerAdapter 等组件。 - **视图解析...
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/> ``` 视图...
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> <!-- 处理器适配器 --> <bean class="org.springframework.web.servlet.mvc.annotation....