Spring已经有点历史了,不过从来没有认真的看过。
最近比较闲,便瞄了两眼Spring,用一个东西工作,自然是要先看看这东西内部是怎么构成的,否则用的时候,踩在坑里,也不知道如何跳出来。
了解Spring最快的方法,当然是从启动开始。
Spring和Struts一样,是通过一个Servlet来接管web服务的,首先看一下web.xml的定义
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- Spring The definition of the Root Spring Container shared by all Servlets and Filters --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <filter> <filter-name>SetCharacterEncoding</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>false</param-value> </init-param> </filter> <filter-mapping> <filter-name>SetCharacterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
很简单,用一个上下文参数指定了根容器的配置文件路径,定义了一个监听器,用来初始化根容器,
然后定义了一个servlet,用来接管所有的请求,也通过参数形式指定了配置文件路径。
最后通过一个过滤器来指定请求的编码(这个不是必须的,并且也可以指定其他的过滤器类)
根容器的定义是为了给所有servlets和filters来提供服务,如果服务只有一个servlet的话,其实定义在servlet容器里也没啥问题。
其实根据wizard创建的spring mvc project里,默认root-context.xml就是空的。
另外,我们先看一下servlet容器的定义文件,先记住两个关键定义。
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven /> <context:component-scan base-package="jp.co.wqf" /> </beans:beans>
其中的意义,后面再解释。
我们先看看根容器的初始化,打开类[org.springframework.web.context.ContextLoaderListener],根据以下调用途径,看看根上下文是怎么创建的。
protected Class<?> determineContextClass(ServletContext servletContext) { String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM); if (contextClassName != null) { try { return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader()); } catch (ClassNotFoundException ex) { throw new ApplicationContextException( "Failed to load custom context class [" + contextClassName + "]", ex); } } else { contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName()); try { return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader()); } catch (ClassNotFoundException ex) { throw new ApplicationContextException( "Failed to load default context class [" + contextClassName + "]", ex); } } }
如果web.xml里没有用参数[contextClass]对上下文类进行定义的话,那么会用默认的上下文类,其实这个默认的类是定义在一个properties文件的,
看一下defaultStrategies的创建过程
private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties"; 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 { ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class); defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } catch (IOException ex) { throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage()); } }
再看看[ContextLoader.properties]定义文件的内容
# Default WebApplicationContext implementation class for ContextLoader. # Used as fallback when no explicit context implementation has been specified as context-param. # Not meant to be customized by application developers. org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
使用的是上下文类[XmlWebApplicationContext]
然后在方法[protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc)]里设定了根据参数[contextConfigLocation]设定的配置文件路径,对根上下文进行了初始化处理
wac.refresh();
最后,把这个跟上下文保存在了ServletContext的属性里
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
监听器执行完,就该初始化servlet了,打开[],根据一下调用,看一下servlet的初始化
org.springframework.web.servlet.HttpServletBean.init()->
org.springframework.web.servlet.FrameworkServlet.initServletBean()->
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext()
protected WebApplicationContext initWebApplicationContext() { WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { // No context instance was injected at construction time -> see if one // has been registered in the servlet context. If one exists, it is assumed // that the parent context (if any) has already been set and that the // user has performed any initialization such as setting the context id wac = findWebApplicationContext(); } if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext); } if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. onRefresh(wac); } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); if (this.logger.isDebugEnabled()) { this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + "' as ServletContext attribute with name [" + attrName + "]"); } } return wac; }
先取出保存在ServletContext里的根上下文,目的是把它作为servlet上下文的父上下文。
根据source追踪,最终发现servlet默认使用的上下文类和根上下文使用的是一样的,只不过这次是直接定义在source里的。
public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
onRefresh方法里,会对一些后续需要的类进行扫描分类,存在类的属性变量里,如果想改变这些类的话,可以从这个地方入手
/** MultipartResolver used by this servlet */ private MultipartResolver multipartResolver; /** LocaleResolver used by this servlet */ private LocaleResolver localeResolver; /** ThemeResolver used by this servlet */ private ThemeResolver themeResolver; /** List of HandlerMappings used by this servlet */ private List<HandlerMapping> handlerMappings; /** List of HandlerAdapters used by this servlet */ private List<HandlerAdapter> handlerAdapters; /** List of HandlerExceptionResolvers used by this servlet */ private List<HandlerExceptionResolver> handlerExceptionResolvers; /** RequestToViewNameTranslator used by this servlet */ private RequestToViewNameTranslator viewNameTranslator; /** FlashMapManager used by this servlet */ private FlashMapManager flashMapManager; /** List of ViewResolvers used by this servlet */ private List<ViewResolver> viewResolvers; protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
大致的初始化过程就是这样的,初始化的过程,也同样是读取配置文件[root-context.xml,servlet-context.xml]的过程。
这个过程以后再描述。
相关推荐
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。Spring MVC4是当前zuixin的版本,在众多特性上有了进一步的提升。, 在精通Spring...
1. **Spring MVC**: - **基本概念**:Spring MVC提供了一个灵活的MVC实现,包括请求映射、视图解析、模型绑定等功能。它通过DispatcherServlet作为前端控制器,负责接收请求并分发到相应的处理器。 - **组件**:...
- **Spring MVC配置**:在Spring MVC中,我们需要配置一个适配器,以便Netty服务器能够理解Spring MVC的控制器。 - **消息编码解码器**:Netty需要消息编码解码器来将HTTP请求转换为Spring MVC可以处理的形式,...
SPRING MVC 配置过程 SPRING MVC 是一个基于 DispatcherServlet 的 MVC 框架,每一个请求最先访问的都是 DispatcherServlet,DispatcherServlet 负责转发每一个 Request 请求给相应的 Handler,Handler 处理以后再...
Spring MVC 是一款强大的Java Web开发框架,用于构建高效、可维护和模块化的Web应用程序。它作为Spring框架的一部分,提供了一种优雅的方式来处理HTTP请求和响应,使得开发者可以专注于业务逻辑而不是底层实现。在这...
此外,配合Spring Boot,可以进一步简化Spring MVC应用的启动和配置。 总的来说,Spring MVC 4.2.3版本为开发者提供了强大且灵活的Web开发工具,帮助他们构建高效、可扩展的Web应用。它的特性涵盖了从请求处理到...
1. **依赖注入**:Spring MVC 4.0继续支持Spring框架的核心功能,依赖注入(DI),允许开发者通过配置来管理对象及其依赖关系,降低了代码耦合度,提高了可测试性。 2. **ModelAndView对象**:在处理完请求后,控制...
Spring MVC 是一个基于Java的轻量级Web应用框架,它是Spring框架的重要组成部分,主要用于构建Web应用程序的后端控制器。这个教程“Spring MVC - A Tutorial”旨在帮助开发者深入理解和掌握Spring MVC的核心概念和...
Spring MVC 是一个强大的Java Web开发框架,它是Spring框架的一部分,专为构建高度可扩展和模块化的Web应用程序而设计。在2015年的版本中,Spring MVC 4已经相当成熟,提供了许多特性来简化开发流程并提高开发效率。...
Spring MVC是一种基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,使用了IoC容器,支持RESTful风格的应用程序开发。Spring MVC通过分离模型(Model)、视图(View)和控制器(Controller)来简化Web开发...
Spring MVC是Spring框架的一个核心模块...总之,"Spring MVC使用Demo"是一个很好的学习资源,涵盖了从环境搭建到实际编码的全过程。通过学习和实践,开发者能够熟练掌握Spring MVC,从而高效地开发出高质量的Web应用。
这是一个基于Spring MVC、Mybatis和Spring框架实现的个人博客系统,涵盖了Web开发中的后端架构设计、数据库管理和前端展示等多个方面。以下将详细介绍这个系统的关键知识点: **1. Spring MVC** Spring MVC是Spring...
本篇文章将深入探讨Spring MVC启动时初始化的几个常用方法,并解释它们在实际开发中的作用。 首先,我们从核心组件`DispatcherServlet`开始。`DispatcherServlet`是Spring MVC的前端控制器,它是整个流程的起点。当...
1. **Spring MVC 概述** - Spring MVC是基于Model-View-Controller(MVC)设计模式的Web应用框架,提供了一种组织和处理请求的机制。 - 它的核心组件包括DispatcherServlet、HandlerMapping、HandlerAdapter、...
spring mvc maven项目,导入IDEA后无报错,需要在IDEA中配置Tomcat并将项目添加到tomcat才能运行。 可用于分析spring mvc源码、spring mvc父子容器初始化流程、session和cookie机制、spring session等,也可以用于...
1. **Spring MVC**: - **核心组件**:DispatcherServlet负责接收请求并分发到相应的控制器(Controller),ModelAndView用于封装模型数据和视图,ViewResolver解析视图。 - **配置**:通常通过Java配置或XML配置...
Spring Boot简化了这一过程,通过自动配置和@SpringBootApplication注解可以快速启动一个包含Spring MVC的应用。 3. **请求处理:Controller** Controller类使用@Controller和@RequestMapping注解来定义处理HTTP...