判断 webapp 启动成功

背景

web 容器是 jettymvc 框架是 springmvc

webapp 启动比较耗时:连接数据库,加载数据到本地缓存;连接 zookeeper 获取配置,根据配置连接到各中间件,那么问题来了,如何知道 webapp 已经启动成功呢?

三种方案

实现 ApplicationListener<ContextRefreshedEvent>

这个算是网上介绍最多的方法了,若 onApplicationEvent 方法被调用,就意味着 webapp 启动成功,代码如下

@Component
public class Welcome implements ApplicationListener<ContextRefreshedEvent> {

    private static final Logger log = LoggerFactory.getLogger(Welcome.class);
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().getParent() != null) {
            log.info("webapp started");
        }
    }
}

使用 Listener

一般使用到 springmvcwebapp,都会配置 ContextLoaderListener,这个监听器会加载配置文件,完成 spring 容器初始化的工作,可以在它后面配置一个监听器,这个监听器的监听事件被调用,就意味着 webapp 启动成功

web.xml 配置如下

代码如下

继承 DispatcherServlet

基于 springmvcwebapp 都会配置 DispatcherServlet,那么我们可以继承它,并重载其 init 方法,这个方法执行完成,就意味着 webapp 启动成功,代码如下

区别

上述三种方案实际上是有区别的,真正的 webapp 启动成功应该是第三种方案 ,即继承 DispatcherServlet,要说清楚这个问题,我们可以从一个典型的 web.xml 文件开始

为了说明问题,我们这个 web.xml 是极简的,它的执行顺序如下

  1. 加载监听器,这个加载顺序是按 web.xml 里出现的顺序,并且是同步的

    1. ContextLoaderListener

    2. LastListener

  2. 加载 MyDispatcherServlet

ContextLoaderListener 加载完成,触发第一次的 onApplicationEvent,这时候所有 spring 管理的 bean 都已经是就绪状态了,这意味着数据库已经连接上了,数据也已经加载到缓存;各个中间件诸如 redis/mq/dfs 等也是可以访问的状态,但是这个时候 webapp 还没有真正完成启动,因为这个时候 DispatcherServlet 还没有加载

接下来加载 LastListener,如果要求不那么严格的话,可以近似的认为此时 webapp 已启动成功了

接下来是 MyDispatcherServlet,在其 init 方法执行中,会触发第二次的 onApplicationEvent,只有完成 init 后,webapp 才算是真正的启动完成

Last updated