WEB三大组件:servlet、filter、listener。以前经常在web.xml配置使用。
ServletContainerInitializer
——初始化web容器
在web容器启动时为提供给第三方组件机会做一些初始化的工作。每个框架要使用ServletContainerInitializer
就必须在对应的jar包的META-INF/services
目录创建一个名为javax.servlet.ServletContainerInitializer
的文件,文件内容指定具体的ServletContainerInitializer
实现类——全类名。那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。
ServletContainerInitializer
接口:
public interface ServletContainerInitializer {
// 通过 @HandlesTypes(WebApplicationInitializer.class) 注解指定 c 入参。
// 继承了 WebApplicationInitializer 的类
// ServletContext 代表当前的 web 应用。
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException;
}
比如SpringServletContainerInitializer
:
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
List<WebApplicationInitializer> initializers = Collections.emptyList();
if (webAppInitializerClasses != null) {
initializers = new ArrayList<>(webAppInitializerClasses.size());
// 挨个实例化并放入 initializers list
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer) ReflectionUtils.accessibleConstructor(waiClass).newInstance());
} // catch ...
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
// 排序并挨个执行实现了 WebApplicationInitializer 的类的 onStartup 方法。
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
WebApplicationInitializer
的实现类:
AbstractContextLoaderInitializer
——注册监听器ContextLoaderListener
。
public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerContextLoaderListener(servletContext);
}
protected void registerContextLoaderListener(ServletContext servletContext) {
// 创建 IOC 容器
WebApplicationContext rootAppContext = createRootApplicationContext();
if (rootAppContext != null) {
// 添加监听器
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
listener.setContextInitializers(getRootApplicationContextInitializers());
servletContext.addListener(listener);
} // else log ...
}
}
createRootApplicationContext()
子类实现创建IOC容器——WebApplicationContext
AbstractDispatcherServletInitializer
——注册DispatcherServlet
和过滤器
public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
this.registerDispatcherServlet(servletContext);
}
protected void registerDispatcherServlet(ServletContext servletContext) {
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return null or empty");
WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext, "createServletApplicationContext() must not return null");
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
Assert.notNull(dispatcherServlet, "createDispatcherServlet(WebApplicationContext) must not return null");
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
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);
}
}
AbstractAnnotationConfigDispatcherServletInitializer
——创建Servlet和Root的IOC容器
继承了AbstractDispatcherServletInitializer
,提供了创建两种IOC容器的实现方法。
public abstract class AbstractAnnotationConfigDispatcherServletInitializer extends AbstractDispatcherServletInitializer {
protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(configClasses);
return context;
}
else {
return null;
}
}
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
context.register(configClasses);
}
return context;
}
// 根容器配置,子类实现
protected abstract Class<?>[] getRootConfigClasses();
// 子容器配置,子类实现
protected abstract Class<?>[] getServletConfigClasses();
}
DispatcherServlet中两类容器的区别
- Servlet WebApplicationContext
- Controllers
- ViewResolver
- HandlerMapping
- other web-related beans
- Root WebApplicationContext
- Services
- Repositories
这些都是抽象类,需要自己实现,继承了以后自动处理,因为它一定继承了WebApplicationInitializer
,不需要额外操作。
Filter
——过滤器
需要添加到 ServletContext
中。
public interface Filter {
default public void init(FilterConfig filterConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
default public void destroy() {}
}
ServletContextListener
——监听器
监听项目的启动或停止,需要添加到 ServletContext
中。
public interface ServletContextListener extends EventListener {
default public void contextInitialized(ServletContextEvent sce) {}
default public void contextDestroyed(ServletContextEvent sce) {}
}
HttpServlet
——定制web应用
web应用继承该类,需要添加到 ServletContext
中。或直接使用 @WebServlet
注解。
比如SpringMVC
中的DispatcherServlet
:
@EnableWebMvc
页面请求定制,静态资源托管给tomcat,注解版自定义拦截器。
需要继承WebMvcConfigurer
接口
public interface WebMvcConfigurer {
default void configurePathMatch(PathMatchConfigurer configurer) {
}
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
default void addFormatters(FormatterRegistry registry) {
}
default void addInterceptors(InterceptorRegistry registry) {
}
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
default void addCorsMappings(CorsRegistry registry) {
}
default void addViewControllers(ViewControllerRegistry registry) {
}
default void configureViewResolvers(ViewResolverRegistry registry) {
}
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
default Validator getValidator() {
return null;
}
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
WebMvcConfigurerComposite
继承了WebMvcConfigurer
接口,可以直接继承它:
class WebMvcConfigurerComposite implements WebMvcConfigurer {
private final List<WebMvcConfigurer> delegates = new ArrayList<>();
public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.delegates.addAll(configurers);
}
}
public void configurePathMatch(PathMatchConfigurer configurer) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configurePathMatch(configurer);
}
}
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureContentNegotiation(configurer);
}
}
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureAsyncSupport(configurer);
}
}
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureDefaultServletHandling(configurer);
}
}
public void addFormatters(FormatterRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addFormatters(registry);
}
}
public void addInterceptors(InterceptorRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addInterceptors(registry);
}
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addResourceHandlers(registry);
}
}
public void addCorsMappings(CorsRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addCorsMappings(registry);
}
}
public void addViewControllers(ViewControllerRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addViewControllers(registry);
}
}
public void configureViewResolvers(ViewResolverRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureViewResolvers(registry);
}
}
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addArgumentResolvers(argumentResolvers);
}
}
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addReturnValueHandlers(returnValueHandlers);
}
}
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureMessageConverters(converters);
}
}
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.extendMessageConverters(converters);
}
}
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureHandlerExceptionResolvers(exceptionResolvers);
}
}
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.extendHandlerExceptionResolvers(exceptionResolvers);
}
}
public Validator getValidator() {
Validator selected = null;
for (WebMvcConfigurer configurer : this.delegates) {
Validator validator = configurer.getValidator();
if (validator != null) {
if (selected != null) {
throw new IllegalStateException("No unique Validator found: {" +
selected + ", " + validator + "}");
}
selected = validator;
}
}
return selected;
}
public MessageCodesResolver getMessageCodesResolver() {
MessageCodesResolver selected = null;
for (WebMvcConfigurer configurer : this.delegates) {
MessageCodesResolver messageCodesResolver = configurer.getMessageCodesResolver();
if (messageCodesResolver != null) {
if (selected != null) {
throw new IllegalStateException("No unique MessageCodesResolver found: {" +
selected + ", " + messageCodesResolver + "}");
}
selected = messageCodesResolver;
}
}
return selected;
}
}
WebMvcConfigurerAdapter
也继承了WebMvcConfigurer
接口,但是已经被弃用了,因为里面都是空方法,接口可以默认实现空方法,所以还不如直接继承WebMvcConfigurer
接口。
HandlerInterceptor
——SpringMVC拦截器
public interface HandlerInterceptor {
// 在目标方法执行之前调用
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
// 在目标方法执行之后调用
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
// 页面响应之后执行
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}