DispatcherServlet在web.xml中的配置
<context-param><!--默认配置文件为/WEB-INF/[servlet名字]-servlet.xml--><param-name>contextConfigLocation</param-name><param-value>WebApplicationContext的上下文配置</param-value>
</context-param>
<!--在启动Web 容器时,自动装配Spring的配置信息-->
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet><servlet-name>SpringMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--此处没有配置contextConfigLocation,默认用WebApplicationContext的上下文配置--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:/spring/spring-mvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>SpringMVC</servlet-name><url-pattern>请求映射</url-pattern>
</servlet-mapping>
复制代码
- context-param中contextConfigLocation参数,指定用于加载Bean的配置文件,比如加载除Web层的DAO、Service等
- servlet的init-param中contextConfigLocation参数,指定用于初始化Spring Web MVC框架上下文的配置文件。如果没有配置,默认用context-param中contextConfigLocation参数配置文件
- ContextLoaderListener作用:在启动Web 容器时,自动装配Spring的配置信息。
- ContextLoaderListener初始化的上下文加载的Bean是对于整个应用程序共享的;
- DispatcherServlet初始化的上下文只加载Web相关组件,如Controller、HandlerMapping、HandlerAdapter等等
DispatcherServlet初始化顺序
继承体系:
DispatcherServlet->FrameworkServlet->HttpServletBean->HttpServlet
- 第一步:调用HttpServletBean的init()方法,将始化参数设置到该组件上
public abstract class HttpServletBean extends HttpServlet implements EnvironmentAware{@Overridepublic final void init() throws ServletException {//......//1、将配置文件中的contextConfigLocation初始化参数等设置到该组件,如设置FrameworkServlet的contextConfigLocation属性try {PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);// 扩展阅读BeanWrapperBeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));initBeanWrapper(bw);bw.setPropertyValues(pvs, true);}catch (BeansException ex) {//…………省略其他代码}//2、提供给子类初始化的扩展点,该方法由FrameworkServlet覆盖initServletBean();if (logger.isDebugEnabled()) {logger.debug("Servlet '" + getServletName() + "' configured successfully");}}//…………省略其他代码private static class ServletConfigPropertyValues extends MutablePropertyValues {public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties) throws ServletException {Set<String> missingProps = requiredProperties != null && !requiredProperties.isEmpty() ? new HashSet(requiredProperties) : null;// 读取servlet的init-param中contextConfigLocation参数Enumeration en = config.getInitParameterNames();while(en.hasMoreElements()) {String property = (String)en.nextElement();Object value = config.getInitParameter(property);this.addPropertyValue(new PropertyValue(property, value));if (missingProps != null) {missingProps.remove(property);}}}}
}
复制代码
扩展阅读BeanWrapper:[blog.csdn.net/u012410733/…]
- 第二步:FrameworkServlet通过initServletBean()进行Web上下文初始化
public abstract class FrameworkServlet extends HttpServletBean {private String contextConfigLocation;// servlet的init-param中contextConfigLocation参数@Overrideprotected final void initServletBean() throws ServletException {......try {//1、初始化Web上下文this.webApplicationContext = initWebApplicationContext();//2、提供给子类初始化的扩展点initFrameworkServlet();}......}protected WebApplicationContext initWebApplicationContext() {//ROOT上下文(ContextLoaderListener加载的)WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = null;if (this.webApplicationContext != null) {// 1、在创建该Servlet注入的上下文wac = this.webApplicationContext;if (wac instanceof ConfigurableWebApplicationContext) {ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;if (!cwac.isActive()) {if (cwac.getParent() == null) {cwac.setParent(rootContext);}configureAndRefreshWebApplicationContext(cwac);}}}if (wac == null) {//2、查找已经绑定的上下文wac = findWebApplicationContext();}if (wac == null) {//3、如果没有找到相应的上下文,并指定父亲为ContextLoaderListenerwac = createWebApplicationContext(rootContext);}if (!this.refreshEventReceived) {//4、刷新上下文(执行一些初始化)onRefresh(wac);}if (this.publishContext) {// Publish the context as a servlet context attribute.String attrName = getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);//省略部分代码}return wac;}
}
复制代码
- 第三步:FrameworkServlet通过onRefresh()方法配置前端控制器
public class DispatcherServlet extends FrameworkServlet {private static final Properties defaultStrategies;// 默认策略,具体见DispatcherServlet.propertiesprivate MultipartResolver multipartResolver;private LocaleResolver localeResolver;private ThemeResolver themeResolver;private List<HandlerMapping> handlerMappings;private List<HandlerAdapter> handlerAdapters;private List<HandlerExceptionResolver> handlerExceptionResolvers;private RequestToViewNameTranslator viewNameTranslator;private FlashMapManager flashMapManager;private List<ViewResolver> viewResolvers;//实现子类的onRefresh()方法,该方法委托为initStrategies()方法。@Overrideprotected void onRefresh(ApplicationContext context) {initStrategies(context);}//初始化默认的Spring Web MVC框架使用的策略(如HandlerMapping)protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);//文件上传解析initLocaleResolver(context);//本地化解析initThemeResolver(context);//主题解析initHandlerMappings(context);//请求到处理器的映射initHandlerAdapters(context);//处理器包装为适配器,从而支持多种类型的处理器initHandlerExceptionResolvers(context);//处理器异常解析initRequestToViewNameTranslator(context);//将请求URL映射为逻辑视图名initViewResolvers(context);//把逻辑视图名解析为具体的ViewinitFlashMapManager(context);// ???}/*** 文件上传解析器**/private void initMultipartResolver(ApplicationContext context){this.multipartResolver = (MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class);}/*** 本地化解析**/private void initLocaleResolver(ApplicationContext context){this.localeResolver = (LocaleResolver)context.getBean("localeResolver", LocaleResolver.class);}/*** 主题解析**/private void initThemeResolver(ApplicationContext context){this.themeResolver = (LocaleResolver)context.getBean("themeResolver", ThemeResolver.class);}/*** 处理器解析,比如BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping等**/private void initHandlerMappings(ApplicationContext context){this.handlerMappings = null;if (this.detectAllHandlerMappings) {// 获取IOC容器中实现了HandlerMapping接口的对象Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerMappings = new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.handlerMappings);}} else {HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);this.handlerMappings = Collections.singletonList(hm);}if (this.handlerMappings == null) {// 获取默认的处理解析器this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);}}/*** 初始化适配器**/private void initHandlerAdapters(ApplicationContext context) {this.handlerAdapters = null;if (this.detectAllHandlerAdapters) {// 获取IOC容器中实现了HandlerAdapter接口的对象Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerAdapters = new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.handlerAdapters);}} else {HandlerAdapter ha = (HandlerAdapter)context.getBean("handlerAdapter", HandlerAdapter.class);this.handlerAdapters = Collections.singletonList(ha);}if (this.handlerAdapters == null) {// 获取默认的适配器this.handlerAdapters = this.getDefaultStrategies(context, HandlerAdapter.class);}}/*** 初始化异常解析器**/private void initHandlerExceptionResolvers(ApplicationContext context) {this.handlerExceptionResolvers = null;if (this.detectAllHandlerExceptionResolvers) {Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerExceptionResolvers = new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);}} else {HandlerExceptionResolver her = (HandlerExceptionResolver)context.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);this.handlerExceptionResolvers = Collections.singletonList(her);}if (this.handlerExceptionResolvers == null) {// 获取默认的适配器this.handlerExceptionResolvers = this.getDefaultStrategies(context, HandlerExceptionResolver.class);}}/*** 将请求URL映射为逻辑视图名**/private void initRequestToViewNameTranslator(ApplicationContext context) {try {this.viewNameTranslator = (RequestToViewNameTranslator)context.getBean("viewNameTranslator", RequestToViewNameTranslator.class);} catch (NoSuchBeanDefinitionException var3) {this.viewNameTranslator = (RequestToViewNameTranslator)this.getDefaultStrategy(context, RequestToViewNameTranslator.class);}}/*** 初始化视图解析器**/private void initViewResolvers(ApplicationContext context) {this.viewResolvers = null;if (this.detectAllViewResolvers) {// 获取IOC容器中实现了ViewResolver接口的对象Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);if (!matchingBeans.isEmpty()) {this.viewResolvers = new ArrayList(matchingBeans.values());AnnotationAwareOrderComparator.sort(this.viewResolvers);}} else {ViewResolver vr = (ViewResolver)context.getBean("viewResolver", ViewResolver.class);this.viewResolvers = Collections.singletonList(vr);}if (this.viewResolvers == null) {// 获取默认的适配器this.viewResolvers = this.getDefaultStrategies(context, ViewResolver.class);}}
}
复制代码