1. 启动类
Web容器在启动时,会去扫描每个 jar 包 META-INF/services下的javax.servlet.ServletContainerInitializer
文件。在spring-web的jar包中,可以看到类似的结构:
![](https://img.haomeiwen.com/i11674238/1de65322df0f9311.png)
在该文件里引入了SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
...
}
从@HandlesTypes可以看出,在web容器初始化的时候,会去自动扫描WebApplicationInitializer接口下的所有子类(AbstractContextLoaderInitializer,AbstractDispatcherServletInitializer,AbstractAnnotationConfigDispatcherServletInitializer)
- AbstractContextLoaderInitializer 中引入了 ContextLoaderListener
protected void registerContextLoaderListener(ServletContext servletContext) {
WebApplicationContext rootAppContext = createRootApplicationContext();
if (rootAppContext != null) {
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
listener.setContextInitializers(getRootApplicationContextInitializers());
servletContext.addListener(listener);
}
else {
logger.debug("No ContextLoaderListener registered, as " +
"createRootApplicationContext() did not return an application context");
}
}
- AbstractDispatcherServletInitializer:创建WebApplicationContext(将实现方法开放给继承),并为webContext添加servlet和filter
protected void registerDispatcherServlet(ServletContext servletContext) {
String servletName = getServletName();
// 创建WebApplicationContext,由子类实现
WebApplicationContext servletAppContext = createServletApplicationContext();
//创建DispatcherServlet
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
registration.setLoadOnStartup(1);
registration.addMapping(getServletMappings());
registration.setAsyncSupported(isAsyncSupported());
Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter : filters) {
registerServletFilter(servletContext, filter);
}
}
customizeRegistration(registration);
}
- AbstractAnnotationConfigDispatcherServletInitializer 定义了servlet容器和根容器的创建方法,但是开放出配置类,让子类去实现,从而实现自定义config类。
- 创建根容器
@Override
protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
rootAppContext.register(configClasses);
return rootAppContext;
}
else {
return null;
}
}
- 创建web容器
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
servletAppContext.register(configClasses);
}
return servletAppContext;
}
2. 实现
- 实现AbstractAnnotationConfigDispatcherServletInitializer
public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//获取根容器的配置类
protected Class<?>[] getRootConfigClasses() {
return new Class[]{com.test.tournesol.mvc.RootConfig.class};
}
//web 容器的配置类,MVC的配置类
protected Class<?>[] getServletConfigClasses() {
return new Class[]{com.test.tournesol.mvc.AppConfig.class};
}
//获取DispatcherServlet的映射信息
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
- 定义根容器配置类
@ComponentScan(value = "com.test.tournesol.mvc", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
public class RootConfig {
}
- 定义web容器配置类
@ComponentScan(value = "com.test.tournesol.mvc", includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
}, useDefaultFilters = false)
@EnableWebMvc
public class AppConfig {
}
- 定义与业务相关的Controller 类和 Service类
网友评论