如何在Servlet过滤器中执行昂贵的一次初始化?

时间:2014-03-21 19:42:01

标签: java java-ee tomcat servlets

以下是问题的要求:

  • 在Tomcat 7中运行的java Web应用程序
  • 初始化代码需要与外部数据库通信
  • 在启动应用程序期间,外部数据库可能不可用
  • 应用程序启动不会失败,否则tomcat会将应用程序标记为未运行,并且不会向应用程序发送任何请求。相反,应用程序应该启动接受请求,如果发现应用程序特定的初始化未完成,它应该尝试在请求处理期间完成它。

我正在尝试使用下面的servlet过滤器来解决问题。我有以下问题。

  • 这个Servlet过滤器线程是否安全,它只执行一次初始化代码吗?
  • 有没有办法在不使用servlet过滤器的情况下解决这个问题?
  • 有没有更好的方法来解决这个问题?
 package com.exmaple;
    @WebFilter("/*")

 public class InitFilter implements Filter 
 {
    private volatile boolean initialized = false;

    public void destroy() {
        System.out.println("InitFilter.destroy()");
    }

        // is this method thread safe and will only execute the init code once
        // and will cause all requests to wait until initialization code is executed
        // thread code
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            System.out.println("InitFilter.doFilter()");

            if (initialized == false) {
                synchronized (this) {
                    // do expensive initialization work here
                    initialized = true;
                }
            }
            chain.doFilter(request, response);
        }

        public void init(FilterConfig fConfig) throws ServletException {
            System.out.println("InitFilter.init()");
        }
      }

2 个答案:

答案 0 :(得分:1)

我会将其作为ServletContextListener处理并在contextInitialized方法中运行初始化,作为单独的线程,可能使用FutureTask作为@fge建议,或者{{1而不是一个游泳池。

也许有些事情......

newSingleThreadExecutor

这可以避免同步问题,只运行一次初始化。 (每个上下文一次)

无论如何,执行此操作或过滤器,程序的其余部分必须处理初始化不完整。

答案 1 :(得分:0)

我建议你把长时间运行的初始化放在一个线程中,比如:

public void init() throws ServletException {
    //Configure logging, app, pool ...
    MyAppStarter.getInstance().start();
}