一、SpringMVC对ServletContainerInitializer 类的实现
配置信息:
查看SpringServletContainerInitializer
//感兴趣的类为WebApplicationInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
//webAppInitializerClasses:所有WebApplicationInitializer 类型的Class
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// 如果该Class 不是接口,不是抽象类,并且是WebApplicationInitializer类型的类
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
//实例化该类,并加入到initializers集合中
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
//遍历initializers集合中的类
for (WebApplicationInitializer initializer : initializers) {
//调用其onStartup方法
initializer.onStartup(servletContext);
}
}
}
二、WebApplicationInitializer 相关类详解
1、继承关系如下
2、AbstractContextLoaderInitializer
public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//注册容器监听
registerContextLoaderListener(servletContext);
}
protected void registerContextLoaderListener(ServletContext servletContext) {
//创建根容器
WebApplicationContext rootAppContext = createRootApplicationContext();
if (rootAppContext != null) {
//根据根容器,创建容器监听,相当于以前在xml文件里配置ContextLoaderListener
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");
}
}
//创建根容器方法是个抽象方法,留给子类实现
protected abstract WebApplicationContext createRootApplicationContext();
}
3、AbstractDispatcherServletInitializer
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
//注册一个DispatcherServlet
registerDispatcherServlet(servletContext);
}
protected void registerDispatcherServlet(ServletContext servletContext) {
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return null or empty");
//创建一个servlet容器
WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext, "createServletApplicationContext() must not return null");
//创建一个dispatcherServlet
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
Assert.notNull(dispatcherServlet, "createDispatcherServlet(WebApplicationContext) must not return null");
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
//给servlet容器 添加dispatcherServlet 得到一个注册器
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
if (registration == null) {
throw new IllegalStateException("Failed to register servlet with name '" + servletName + "'. " +
"Check if there is another servlet registered under the same name.");
}
//在容器启动时就加载
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);
}
// 这是一个抽象方法,留给子类实现的
protected abstract String[] getServletMappings();
}
4、AbstractAnnotationConfigDispatcherServletInitializer
public abstract class AbstractAnnotationConfigDispatcherServletInitializer
extends AbstractDispatcherServletInitializer {
//覆盖了AbstractContextLoaderInitializer的createRootApplicationContext方法,
//用于创建根容器
@Override
protected WebApplicationContext createRootApplicationContext() {
//得到根容器的Class
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
//创建一个web容器
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
//注册配置类
context.register(configClasses);
return context;
}
else {
return null;
}
}
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
servletAppContext.register(configClasses);
}
return servletAppContext;
}
//得到根容器配置类,这是一个抽象方法,留给子类实现,覆盖了AbstractContextLoaderInitializer
protected abstract Class<?>[] getRootConfigClasses();
//得到Servlet容器配置类,覆盖了AbstractDispatcherServletInitializer 的方法
protected abstract Class<?>[] getServletConfigClasses();
}
所以我们在用配置类创建springmvc应用时,只需继承AbstractAnnotationConfigDispatcherServletInitializer,覆写其对应方法即可
三、Servlet3.0 整合 SpringMVC
1、创建父容器配置类
//Spring的容器不扫描controller;父容器
@ComponentScan(value="com.njf", excludeFilters={
@ComponentScan.Filter(type= FilterType.ANNOTATION,classes={Controller.class})
})
public class RootConfig {}
2、创建子容器配置类
//SpringMVC只扫描Controller;子容器
//useDefaultFilters=false 禁用默认的过滤规则;
@ComponentScan(value="com.njf", includeFilters={
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes={Controller.class})
}, useDefaultFilters=false)
public class AppConfig {}
3、自定义初始化器,并指定配置类
//web容器启动的时候创建对象;调用方法来初始化容器以前前端控制器
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//获取根容器的配置类;(Spring的配置文件) 父容器;
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{RootConfig.class};
}
//获取web容器的配置类(SpringMVC配置文件) 子容器;
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{AppConfig.class};
}
//获取DispatcherServlet的映射信息
// /:拦截所有请求(包括静态资源(xx.js,xx.png)),但是不包括*.jsp;
// /*:拦截所有请求;连*.jsp页面都拦截;jsp页面是tomcat的jsp引擎解析的;
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
4、创建一个 Controller
@Controller
public class HelloController {
@Autowired
HelloService helloService;
@ResponseBody
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
String result = helloService.sayHello("Tomcat...");
return result;
}
}
5、创建一个 Service
@Service
public class HelloService {
public String sayHello(String word) {
System.out.println("Hello," + word);
return "Hello" + word;
}
}
6、测试正常运行。