一、Servlet3.0+的容器啟動過程:
(一)、原理級啟動模式:
- Servlet3.0+ 的容器啟動時,會掃描項目中的所有庫的META-INF/services/javax.servlet.ServletContainerInitializer文件的內(nèi)容
- 在spring-web.jar下有此文件,文件內(nèi)容:
org.springframework.web.SpringServletContainerInitializer
此類為Spring的實現(xiàn),是實現(xiàn)了ServletContainerInitializer的子類,類的聲明如下:
@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {...
- @HandlesTypes指明了此class要處理的目標(biāo)class是:WebApplicationInitializer.class,即以下方法中的set中的class類型
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
- onStartup方法的處理邏輯如下:
(1)掃描classpath中的WebApplicationInitializer實現(xiàn)類
(2)將其反射生成對象,調(diào)用其方法public void onStartup(ServletContext servletCxt),并將ServletContext對象傳入到其實現(xiàn)方法中。
(3)而onStartup方法,即為SpringMVC提供給開發(fā)者的API部分。 - 一個具體的實現(xiàn):
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletCxt) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
//自定義的配置類,與SpringFramework的結(jié)合點
ac.register(AppConfig.class);
//完成一些Bean的自動化裝配,但會覆蓋@EnableMVC,所以盡量不要使用
// ac.refresh();
//自定義的配置文件,與SpringFramework的結(jié)合點(與配置類二選一)
// XmlWebApplicationContext ac = new XmlWebApplicationContext();
//ac.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(ac);
ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
以上代碼如何添加Filter?
//OpenSessionInViewFilter
OpenSessionInViewFilter hibernateSessionInViewFilter = new OpenSessionInViewFilter();
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter(
"hibernateFilter", hibernateSessionInViewFilter);
filterRegistration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/");
AppConfig.java
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "cn.johnyu.otherweb.controller")
public class AppConfig implements WebMvcConfigurer {
}
(二)、父子容器(Context Hierarchy)的啟動模式:
- 需求是什么?
簡單應(yīng)用,只需要由啟動一個WebApplicationContext就可足夠了,但如果需要多個WebApplicationContext就難以應(yīng)付共享bean的需要了,此時可以采用Context Hierarchy的方式:
Context Hierarchy - 實現(xiàn)手段:
利用一個由Spring提供的WebApplicationInitializer模板完成此機制。
使用ConfigClass時:
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { App1Config.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/app1/*" };
}
/*
* 注冊過濾器,映射路徑與DispatcherServlet一致,路徑不一致的過濾器需要注冊到另外的WebApplicationInitializer中
*/
@Override
protected Filter[] getServletFilters() {
return new Filter[] {
new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
}
}
}
使用ConfigXML時
public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
@Override
protected WebApplicationContext createServletApplicationContext() {
XmlWebApplicationContext cxt = new XmlWebApplicationContext();
cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
return cxt;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
/*
* 注冊過濾器,映射路徑與DispatcherServlet一致,路徑不一致的過濾器需要注冊到另外的WebApplicationInitializer中
*/
@Override
protected Filter[] getServletFilters() {
return new Filter[] {
new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
}
}
二、經(jīng)典的Servlet2.X方式
在WEB-INF/web.xml中
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
