使用Spring MVC 时,需要在web.xml中配置DispatchServlet,这个DispatchServlet可以看成一个控制器的具体实现。作为一个控制器所有的请求都要通过它来处理,进行转发、匹配、数据处理后并转由页面进行展示。因此DispatchServlet是Spring MVC的核心部分。
在完成ContextLoaderListener的初始化后,Web容器开始初始化DispatcherServlet,这个初始化的启动与在web.xml中对载入次序的定义有关。DispathcerServlet会建立自己的上下文来持有Spring MVC的Bean,在建立这个自己的IOC容器时,会从ServletContext中得到根上下文作为自己持有上下文的双亲上下文。有了这个根上下文再对自己持有的上下文进行初始化,最后将自己持有的上下文保存到ServletContext中。
首先看看DispatcherSerlvet的继承关系:DispatcherServlet继承自FrameworkServlet,而FrameworkServet继承自HttpServletBean.HttpServletBean有继承了HttpServlet.
DispatcherServlet动作大致可以分为两个部分:初始化部分由initServletBean()启动,通过initWebApplicationContext()方法调用DispatcherServlet的initStrategies方法。在这个方法里,DispatcherServlet对MVC的其他部分进行了初始化,比如handlerMapping,ViewResolver;另一个部分是对Http的请求进行响应,作为一个Servlet,web容器会调用Servlet的doGet()和doPost()方法,在经过FrameServlet的processRequest()简单处理后,会调用DispatcherServlet的doService()方法,在这个方法中封装了doDispatch().
在这里主要介绍初始化部分。
作为Servlet, DispatcherServlet的启动过程和Servlet启动过程是相联系的。在Servlet的初始化过程中,Servlet的init方法被调用,已进行初始化。
HttppServletBean.init()->FrameworkServlet.initWebApplicationContext()->DispatcherServlet.onRefresh().
onRefresh 的源码是:
/** * This implementation calls {@link #initStrategies}. */ @Override protected void onRefresh(ApplicationContext context) { initStrategies(context); }
而initStrategies(context)的源码如下:
protected void initStrategies(ApplicationContext context) { //初始化多媒体解析器 initMultipartResolver(context); //初始化位置解析器 initLocaleResolver(context); //初始化主题解析器 initThemeResolver(context); //初始化HandlerMappings initHandlerMappings(context); // 初始化HandlerAdapters initHandlerAdapters(context); //初始化异常解析器 initHandlerExceptionResolvers(context); //初始化请求到视图名转换器 initRequestToViewNameTranslator(context); //初始化视图解析器 initViewResolvers(context); //初始化FlashMapManager initFlashMapManager(context); }
通过initMultipartResover进行初始化多媒体解析器,如果在配置文件中没有配置id为multipartResolver的bean则没有提供多媒体处理器。
/** * Initialize the MultipartResolver used by this class. * <p>If no bean is defined with the given name in the BeanFactory for this namespace, * no multipart handling is provided. */ private void initMultipartResolver(ApplicationContext context) { try { this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class); if (logger.isDebugEnabled()) { logger.debug("Using MultipartResolver [" + this.multipartResolver + "]"); } } catch (NoSuchBeanDefinitionException ex) { // Default is no multipart resolver. this.multipartResolver = null; if (logger.isDebugEnabled()) { logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME + "': no multipart request handling provided"); } } }
通过initLocaleResolver方法进行localeResolver的初始化,如果没有配置指定id为localeResolver的bean则使用AcceptHeaderLocaleResolver的位置解析器。
* Initialize the LocaleResolver used by this class. * <p>If no bean is defined with the given name in the BeanFactory for this namespace, * we default to AcceptHeaderLocaleResolver. */ private void initLocaleResolver(ApplicationContext context) { try { this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class); if (logger.isDebugEnabled()) { logger.debug("Using LocaleResolver [" + this.localeResolver + "]"); } } catch (NoSuchBeanDefinitionException ex) { // We need to use the default. this.localeResolver = getDefaultStrategy(context, LocaleResolver.class); if (logger.isDebugEnabled()) { logger.debug("Unable to locate LocaleResolver with name '" + LOCALE_RESOLVER_BEAN_NAME + "': using default [" + this.localeResolver + "]"); } } }
initThemeResolver初始化主题解析器,如果没有配置指定id的为themeResolver的bean 则使用FixedThemeResolver主题解析器
/** * Initialize the ThemeResolver used by this class. * <p>If no bean is defined with the given name in the BeanFactory for this namespace, * we default to a FixedThemeResolver. */ private void initThemeResolver(ApplicationContext context) { try { this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class); if (logger.isDebugEnabled()) { logger.debug("Using ThemeResolver [" + this.themeResolver + "]"); } } catch (NoSuchBeanDefinitionException ex) { // We need to use the default. this.themeResolver = getDefaultStrategy(context, ThemeResolver.class); if (logger.isDebugEnabled()) { logger.debug( "Unable to locate ThemeResolver with name '" + THEME_RESOLVER_BEAN_NAME + "': using default [" + this.themeResolver + "]"); } } }
初始化HandlerMapping,这个handlerMapping的作用是为Http请求找到相应的控制器,从而利用这些控制器去完成http请求的数据处理工作。这些控制器和http的请求时对应的。DispatcherServlet中handlerMapping的初始化过程中的具体实现如下。在HandlerMapping的初始化过程中,把Bean配置文件中配置好的handlerMapping从IOC容器中取出。
/** * Initialize the HandlerMappings used by this class. * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace, * we default to BeanNameUrlHandlerMapping. */ private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // 在应用上下文包括其祖先上下文中查找所有HandlerMappings Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); //如果matchingBeans这个map是不为空,则创建一个新的ArrayList if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values()); //并对其进行排序 OrderComparator.sort(this.handlerMappings); } } else { try { //从应用上下文中查找所有的HandlerMapping 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) { // 如果没有配置HandlerMapping 则使用默认的HandlerMapping 策略 this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default"); } } }
进过上述的处理过程,handlerMapping已经初始化完成,handlerMapping中就已经获取了在BeanDefinition中配置的映射关系。
通过initHandlerAdapters进行初始化HandlerAdapter,如果没有配置HandlerAdapter则使用SimpleControllerHandlerAdapter
/** * Initialize the HandlerAdapters used by this class. * <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace, * we default to SimpleControllerHandlerAdapter. */ private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; if (this.detectAllHandlerAdapters) { // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts. Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values()); // We keep HandlerAdapters in sorted order. OrderComparator.sort(this.handlerAdapters); } } else { try { HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerAdapter later. } } // Ensure we have at least some HandlerAdapters, by registering // default HandlerAdapters if no other adapters are found. if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default"); } } }
初始化异常处理器,如果没有配置指定Id为handlerExceptionResolver的Bean,默认是没有异常处理器
/** * Initialize the HandlerExceptionResolver used by this class. * <p>If no bean is defined with the given name in the BeanFactory for this namespace, * we default to no exception resolver. */ private void initHandlerExceptionResolvers(ApplicationContext context) { this.handlerExceptionResolvers = null; if (this.detectAllHandlerExceptionResolvers) { // Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts. Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils .beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values()); // We keep HandlerExceptionResolvers in sorted order. OrderComparator.sort(this.handlerExceptionResolvers); } } else { try { HandlerExceptionResolver her = context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class); this.handlerExceptionResolvers = Collections.singletonList(her); } catch (NoSuchBeanDefinitionException ex) { // Ignore, no HandlerExceptionResolver is fine too. } } // Ensure we have at least some HandlerExceptionResolvers, by registering // default HandlerExceptionResolvers if no other resolvers are found. if (this.handlerExceptionResolvers == null) { this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerExceptionResolvers found in servlet '" + getServletName() + "': using default"); } } }
初始化请求到视图名称的转换器,如果不配置则使用默认的转换器。
/** * Initialize the RequestToViewNameTranslator used by this servlet instance. * <p>If no implementation is configured then we default to DefaultRequestToViewNameTranslator. */ private void initRequestToViewNameTranslator(ApplicationContext context) { try { this.viewNameTranslator = context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class); if (logger.isDebugEnabled()) { logger.debug("Using RequestToViewNameTranslator [" + this.viewNameTranslator + "]"); } } catch (NoSuchBeanDefinitionException ex) { // We need to use the default. this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class); if (logger.isDebugEnabled()) { logger.debug("Unable to locate RequestToViewNameTranslator with name '" + REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME + "': using default [" + this.viewNameTranslator + "]"); } } }
初始化视图解析器,如果没有配置视图解析器则使用默认的InternalResourceViewResolver视图解析器
/** * Initialize the ViewResolvers used by this class. * <p>If no ViewResolver beans are defined in the BeanFactory for this * namespace, we default to InternalResourceViewResolver. */ private void initViewResolvers(ApplicationContext context) { this.viewResolvers = null; if (this.detectAllViewResolvers) { // Find all ViewResolvers in the ApplicationContext, including ancestor contexts. Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false); if (!matchingBeans.isEmpty()) { this.viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values()); // We keep ViewResolvers in sorted order. OrderComparator.sort(this.viewResolvers); } } else { try { ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class); this.viewResolvers = Collections.singletonList(vr); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default ViewResolver later. } } // Ensure we have at least one ViewResolver, by registering // a default ViewResolver if no other resolvers are found. if (this.viewResolvers == null) { this.viewResolvers = getDefaultStrategies(context, ViewResolver.class); if (logger.isDebugEnabled()) { logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default"); } } }
获取默认设置,首先获取接口的名称,然后从DispatcherServlert.properties的配置文件中读取value,然后将其分割为字符串数组。
/** * Create a List of default strategy objects for the given strategy interface. * <p>The default implementation uses the "DispatcherServlet.properties" file (in the same * package as the DispatcherServlet class) to determine the class names. It instantiates * the strategy objects through the context's BeanFactory. * @param context the current WebApplicationContext * @param strategyInterface the strategy interface * @return the List of corresponding strategy objects */ @SuppressWarnings("unchecked") protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) { String key = strategyInterface.getName(); 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>(); } }
DispatcherSerlvet.properties
# Default implementation classes for DispatcherServlet's strategy interfaces. # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping 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 org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
相关推荐
在Spring MVC框架中,应用程序启动时会执行一系列初始化操作,这些操作对于理解Spring MVC的工作原理至关重要。本篇文章将深入探讨Spring MVC启动时初始化的几个常用方法,并解释它们在实际开发中的作用。 首先,...
Spring源码学习九:DispatcherServlet初始化源码分析1 DispatcherServlet是SpringMVC的核心分发器,它实现了请求分发,是处理请求的入口,本篇将深入源码分析它的初始化过程。 首先,从DispatcherServlet的名称上...
`<init-param>`可以用来设置DispatcherServlet的初始化参数,如`contextConfigLocation`用于指定Spring MVC的配置文件位置,可以是类路径下的路径(如`classpath:spring-servlet-config.xml`),而不是默认的`/WEB-...
14. **性能优化**:Spring MVC 4.0在内部做了许多性能优化,包括更快的DispatcherServlet初始化、更高效的HTTP方法映射等。 15. **兼容性与兼容性测试**:Spring MVC 4.0确保与各种Web容器的兼容性,如Tomcat、...
wpblog.sql可能是数据库的初始化脚本,用于创建这些表结构并可能包含一些初始数据。MySQL是常用的开源关系型数据库管理系统,适用于中小型Web应用,具有良好的性能和稳定性。 **5. 文件结构** - `wpblog.sql`: 这个...
DispatcherServlet通过`web.xml`配置文件或Java配置类进行初始化配置。 2. **Controller**: 控制器是实现业务逻辑的类,通常由开发者编写。它们处理HTTP请求,调用业务服务,然后返回一个模型(Model)和视图(View...
- 配置Web.xml文件,设置DispatcherServlet的初始化参数和监听器,以便加载Spring上下文。 - 编写Controller,处理HTTP请求,并调用Service完成业务逻辑。 5. **项目源码分析**:在压缩包中的项目源码,我们可以...
1. **web.xml**:这是部署描述符,定义了DispatcherServlet的配置,包括Servlet的映射路径和初始化参数。例如,配置DispatcherServlet的servlet-name、url-pattern以及加载Spring MVC的配置文件。 2. **spring-mvc-...
DispatcherServlet 是 Spring MVC 的核心组件之一,负责接收请求并分发给合适的控制器进行处理。其启动流程大致如下: 1. **类的继承关系**:`DispatcherServlet` 继承自 `FrameworkServlet`,而 `FrameworkServlet...
数据库脚本(可能是.sql文件)用于创建和初始化MySQL的表结构;还有可能包含Java源代码,包括Controller、Service、DAO层的实现,以及实体类等。 学习和掌握这三大技术,对于Java Web开发者来说至关重要,不仅能够...
- 配置Spring MVC的DispatcherServlet在web.xml中,设置其初始化参数和映射路径。 - 创建Spring MVC的配置文件,例如`servlet-context.xml`,配置HandlerMapping、HandlerAdapter、ViewResolver等组件。 - 在配置...
1. Spring框架的配置和使用,包括IoC容器的初始化、bean的定义和依赖注入。 2. Spring MVC的控制器定义、模型绑定、视图解析,以及处理HTTP请求的方法。 3. MyBatis的配置,SQL映射文件的编写,以及如何通过MyBatis...
- **web.xml**:配置DispatcherServlet,定义Spring MVC的初始化参数。 - **servlet-context.xml**:Spring MVC的核心配置文件,声明拦截器、视图解析器、bean等。 3. **处理器映射器与适配器** - **...
- `web.xml`:配置DispatcherServlet和ContextLoaderListener,前者处理HTTP请求,后者初始化Spring的ApplicationContext。 - `spring-mvc.xml`:配置ViewResolver,比如InternalResourceViewResolver,用于解析...
然后,配置Spring的IoC容器,包括定义bean的实例化方式、初始化参数等。接着,设置Spring MVC的配置,如处理器映射器、视图解析器等。最后,配置Hibernate连接数据库的相关信息,包括数据源、实体类、映射文件等。 ...
2. 配置 Spring:创建 Spring 配置文件(如:applicationContext.xml),配置 DataSource、SqlSessionFactoryBean、MapperScannerConfigurer 等,以便 Spring 可以管理和初始化这些组件。 3. 配置 Mybatis:编写 ...
以上配置显示了如何在web.xml中注册和初始化DispatcherServlet,配置文件为springmvc.properties。启动时,DispatcherServlet将加载配置文件中定义的bean以及其它各种组件。 在Spring MVC的源码深度剖析中,会涉及...
在实际项目中,我们还需要考虑其他因素,比如事务管理、数据初始化和清理等。Spring Test提供了`@Transactional`注解来自动回滚事务,避免测试之间的影响。此外,可以使用`@Before`和`@After`方法来自定义测试前后的...
- **初始化**:读取配置文件并初始化 Spring 容器。 - **请求处理**:处理所有进入系统的 HTTP 请求。 - **响应生成**:根据处理结果生成最终的 HTTP 响应。 #### 五、Spring MVC 双亲上下文说明 在 Spring MVC 中...