Tomcat对Servlet规范的Filter及Listener实现(下)

简介: Tomcat对Servlet规范的Filter及Listener实现

internalDoFilter里会做个判断:


  • 若当前Filter位置 < Filter数组长度,即Filter还没调完,就从Filter数组取下一个Filter,调用其doFilter
  • 否则,说明已调用完所有Filter,该调用Servlet#service了。service方法是留给程序员实现业务逻辑的,比如CRUD
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain){
          ...
          //调用Filter的方法
          chain.doFilter(request, response);
      }

Filter#doFilter的FilterChain参数,就是Filter链。每个Filter#doFilter里必须调用Filter链的doFilter,而Filter链中保存当前Filter位置,会调用下一个Filter的doFilter方法,这样就能完成链式调用。


对应的filter是怎么注册到Servlet的呢?

filter是注册到Servlet容器中,Tomcat的StandardContext类中维护了一个Filter列表,所谓注册就是把你写的filter类实例加到这个列表。

Listener管理


Listener可以监听容器内部发生的事件:

  • 生命状态的变化
    比如Context容器启动和停止、Session的创建和销毁。
  • 属性变化
    比如Context容器某个属性值变了、Session的某个属性值变了以及新的请求来了


怎么添加监听器


在web.xml配置或注解添加,在监听器里实现业务逻辑。

Tomcat需读取配置文件,拿到监听器的类名,将它们实例化,并适时调用这些监听器方法。


Tomcat是通过Context容器来管理这些监听器的。Context容器将两类事件分开来管理,分别用不同的集合来存放不同类型事件的监听器:

//监听属性值变化的监听器
private List<Object> applicationEventListenersList = new CopyOnWriteArrayList<>();
//监听生命事件的监听器
private Object applicationLifecycleListenersObjects[] = new Object[0];
剩下的事情就是触发监听器了,比如在Context容器的启动方法里,就触发了所有的ServletContextListener:
// 1 拿到所有生命周期监听器
Object instances[] = getApplicationLifecycleListeners();
for (int i = 0; i < instances.length; i++) {
   // 2 判断Listener的类型是否为ServletContextListener
   if (!(instances[i] instanceof ServletContextListener))
      continue;
   // 3 触发Listener方法
   ServletContextListener lr = (ServletContextListener) instances[i];
   lr.contextInitialized(event);
}

这里的ServletContextListener接口是留给用户的扩展机制,用户可以实现该接口定义自己的监听器,监听Context容器的启停事件。

ServletContextListener跟Tomcat自己的生命周期事件LifecycleListener是不同的。LifecycleListener定义在生命周期管理组件中,由基类LifecycleBase统一管理。


可定制监听器监听Tomcat内部发生的各种事件:比如Web应用、Session级别或请求级别的。Tomcat中的Context容器统一维护了这些监听器,并负责触发。


Context组件通过自定义类加载器来加载Web应用,并实现了Servlet规范,直接跟Web应用打交道。


FAQ

Context容器分别用了CopyOnWriteArrayList和对象数组来存储两种不同的监听器,为什么要这样设计呢?

因为:


  • 属性值变化listener能动态配置,所以用CopyOnWriteArray
    写不会那么频繁,读取比较频繁
  • 生命周期事件listener,不能动态改变,无线程安全问题
    生命周期相关的类比如session一个用户分配一个,用完了就会销毁,用对象数组,可以适应增删改操作
目录
相关文章
|
6月前
|
前端开发 JavaScript Java
Web.xml - Servlet与Filter的url-pattern
Web.xml - Servlet与Filter的url-pattern
64 8
|
6天前
|
JSON Java 应用服务中间件
|
19天前
|
Java
springboot项目出现Exception in thread “main“ java.lang.NoClassDefFoundError: javax/servlet/Filter
springboot项目出现Exception in thread “main“ java.lang.NoClassDefFoundError: javax/servlet/Filter
20 0
|
19天前
|
XML 前端开发 Java
Tomcat和Servlet
Tomcat和Servlet
11 0
|
19天前
|
前端开发 Java 应用服务中间件
HTTP&Tomcat&Servlet
HTTP&Tomcat&Servlet
61 0
|
19天前
|
前端开发 Java 容器
SpringBoot中注册Servlet、Filter和Listener(代码和注解两种方式)
SpringBoot中注册Servlet、Filter和Listener(代码和注解两种方式)
70 0
|
19天前
Servlet3.0+环境下使用注解注册Servlet、Filter和Listener组件
Servlet3.0+环境下使用注解注册Servlet、Filter和Listener组件
44 2
|
19天前
|
缓存 Java Spring
servlet/filter/listener/interceptor区别与联系
servlet/filter/listener/interceptor区别与联系
45 0
|
8月前
|
Java 应用服务中间件 Linux
HTTPS && Tomcat && Servlet && 博客系统 && 软件测试的概念 && Linux
HTTPS && Tomcat && Servlet && 博客系统 && 软件测试的概念 && Linux
34 0
|
Java 应用服务中间件 容器
Tomcat对Servlet规范的Filter及Listener实现(上)
Tomcat对Servlet规范的Filter及Listener实现
167 0
Tomcat对Servlet规范的Filter及Listener实现(上)