spring boot中如何加载servlet和filter

  • Post author:
  • Post category:其他




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;
}
  1. 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);
	}
}
  1. 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);
}
  1. 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中流程

  1. context启动时,调用ServletContainerInitializers添加filter,调用AbstractFilterRegistrationBean类的addRegistration方法向context添加filter
  2. context中不存在FilterDef则创建对应FilterDef
  3. AbstractFilterRegistrationBean中configure方法添加匹配filter的uri,默认为/*
  4. context启动时,调用filterStart方法配置初始化ApplicationFilterConfig
  5. 调用filter的init方法
  6. 对每次到达的请求在StandardWrapperVavel的invoke方法中创建过滤器链
  7. 根据名称获得ApplicationFilterConfig添加到过滤器链,通过ApplicationFilterConfig来获取filter执行



版权声明:本文为wq5350原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。