ServletContextInitializer
用于程序化配置ServletContext的接口,用于往ServletContext容器中注册servlets, filters, listeners,context-params and attributes
初始化tomcat服务器时,会初始TomcatStarter(实现ServletContainerInitializer接口)并在其中存放当前系统存在的ServletContextInitializer,在StandardContext的start启动时调用TomcatStarter的startup方法
public interface ServletContextInitializer {
void onStartup(ServletContext servletContext) throws ServletException;
}
- onStartup方法
为当前IOC容器设置servletContext
注册ServletContext的作用域和环境变量
寻找当前系统
private void selfInitialize(ServletContext servletContext) throws ServletException {
// 为当前应用上下文设置servletContext
prepareWebApplicationContext(servletContext);
// 注册ServletContext的作用域
registerApplicationScope(servletContext);
// 向给定的BeanFactory注册特定于web的环境bean->("contextParameters", "contextAttributes")
WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
// 获得ServletContextInitializerBeans类,遍历其中ServletContextInitializer
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}
}
- ServletContextInitializerBeans的构造方法,在创建webServer时调用
从当前IOC容器中寻找实现了ServletContextInitializer接口的类,添加到当前initializers中,如dispatcherServletRegistration、securityFilterChainRegistration
添加当前容器中存在的Servlet、Filter和EventListener类,并使用适配器模式将其转换为RegistrationBean类型
对初始化器排序
public ServletContextInitializerBeans(ListableBeanFactory beanFactory,
Class<? extends ServletContextInitializer>... initializerTypes) {
this.initializers = new LinkedMultiValueMap<>();
this.initializerTypes = (initializerTypes.length != 0) ? Arrays.asList(initializerTypes)
: Collections.singletonList(ServletContextInitializer.class);
// 从当前IOC容器中寻找实现了ServletContextInitializer接口的类,添加到当前initializers中(Servlet.class,Filter.class,EventListener.class)
addServletContextInitializerBeans(beanFactory);
// 添加当前容器中存在的Servlet、Filter和EventListener类,并使用适配器模式将其转换为RegistrationBean类型
addAdaptableBeans(beanFactory);
// 对初始化器排序
List<ServletContextInitializer> sortedInitializers = this.initializers.values().stream()
.flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE))
.collect(Collectors.toList());
this.sortedList = Collections.unmodifiableList(sortedInitializers);
logMappings(this.initializers);
}
- ServletRegistrationBean向StandardContext中注册Servlet
public final void onStartup(ServletContext servletContext) throws ServletException {
String description = getDescription();
···日志
register(description, servletContext);
}
protected final void register(String description, ServletContext servletContext) {
// 注册Servlet对象
D registration = addRegistration(description, servletContext);
···日志
// 配置映射 / -> servlet
configure(registration);
}
filter的执行
组件
FilterChain
用于管理特定请求的一组过滤器的执行
public interface FilterChain {
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException;
}
ApplicationFilterChain
Tomcat中的过滤器链实现
public final class ApplicationFilterChain implements FilterChain {
// 持有的过滤器,从StandardContext中获取
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
// 过滤后调用的Servlet
private Servlet servlet = null;
// 当前过滤器在过滤器链中的位置
private int pos = 0;
// 总个数,根据pos和n来判断是否过滤完成
private int n = 0;
}
FilterDef
过滤器的定义
public class FilterDef implements Serializable {
// 过滤器描述
private String description = null;
private String displayName = null;
// 过滤器实例
private transient Filter filter = null;
// 过滤器全限制名称
private String filterClass = null;
// 过滤器名称
private String filterName = null;
}
FilterMap
保存filter名称与url的映射
ApplicationFilterConfig
一个过滤器配置对象,由servlet容器在初始化期间将信息传递给过滤器
public final class ApplicationFilterConfig implements FilterConfig, Serializable {
private final transient Context context;
private final FilterDef filterDef;
}
StandardContext中与filter关联的字段
private Map<String, FilterDef> filterDefs = new HashMap<>();
private final ContextFilterMaps filterMaps = new ContextFilterMaps();
private Map<String, ApplicationFilterConfig> filterConfigs = new HashMap<>();
Spring Boot中流程
- context启动时,调用ServletContainerInitializers添加filter,调用AbstractFilterRegistrationBean类的addRegistration方法向context添加filter
- context中不存在FilterDef则创建对应FilterDef
- AbstractFilterRegistrationBean中configure方法添加匹配filter的uri,默认为/*
- context启动时,调用filterStart方法配置初始化ApplicationFilterConfig
- 调用filter的init方法
- 对每次到达的请求在StandardWrapperVavel的invoke方法中创建过滤器链
- 根据名称获得ApplicationFilterConfig添加到过滤器链,通过ApplicationFilterConfig来获取filter执行