【问题标题】:Tomcat - Servlet init() called twice upon startupTomcat - Servlet init() 在启动时调用了两次
【发布时间】:2011-09-04 17:54:33
【问题描述】:

我对独立的 Tomcat 服务器(未与 Apache 链接)有疑问。

当 Tomcat 启动时,servlet 的 init() 方法被调用了两次,即两个 servlet 正在启动。更令人担忧的是,这些似乎是由不同的类加载器加载的——命令行上只有一个 Java 进程在运行,所以它不是多个 Tomcat。

web.xml sn -p(servlet只配置一次,只在webapp web.xml中配置):

<servlet>
  <servlet-name>LenderInterfaceServlet</servlet-name>
  <display-name>Lender Interface Servlet</display-name>
  <servlet-class>com.foobar.lender.webservice.server.LenderInterfaceServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

我在 init 方法中添加了一些日志记录,并创建了一个名为 RatesPoller 的单例类,init 尝试获取该类的实例。从日志中我们可以看到单例实例是不同的:

LenderInterfaceServlet - [init] Start: com.foobar.lender.webservice.server.LenderInterfaceServlet@56d90453
LenderInterfaceServlet - [init] Starting up the Rates pollers.
LenderInterfaceServlet - [init] Got com.foobar.lender.framework.rates.RatesPoller@ae0e515
LenderInterfaceServlet - [init] Start: com.foobar.lender.webservice.server.LenderInterfaceServlet@1b0c6cfc
LenderInterfaceServlet - [init] Starting up the Rates pollers.
LenderInterfaceServlet - [init] Got com.foobar.lender.framework.rates.RatesPoller@5759780d

所以我们有两个不同的 servlet 和两个不同的单例轮询器。

我怀疑这意味着 Tomcat 正在启动存储在 Tomcat webapps 文件夹中的两个 webapp 实例。显然,当你想启动一个只有一个会运行的东西时,这是一个问题,我需要弄清楚如何确保 Tomcat 不会运行 webapp 两次!

如果有人有任何想法...

代码:

public class RatesPoller {

  private static RatesPoller instance;

  private RatesPoller() {}

  public static RatesPoller getInstance() {
    if (instance == null) {
        instance = new RatesPoller();
    }
    return instance;
  }

  public RatesPoller clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException("Singleton. Tsk!");
  }
}

和 LenderInterfaceServlet 中的 init() 方法:

public class LenderInterfaceServlet extends AxisServlet {
  // ...
  @Override
  public void init() throws ServletException {
    logger.info("[init] Start: " + this);
    super.init();
    logger.info("[init] Starting up the Rates pollers.");
    RatesPoller rp = RatesPoller.getInstance();
    logger.info("[init] Got " + rp);
  }
  // ...
}

【问题讨论】:

  • "Singleton. Tsk!" 让我开心:)

标签: tomcat servlets init


【解决方案1】:

Tomcat 会自动部署 webapps 中的任何内容,并根据 server.xml 进行部署。只需从 webapps 中删除您的 webapp 即可避免重复加载。

【讨论】:

    【解决方案2】:

    您的代码中存在错误。你的单例不是线程安全的。该 getInstance() 方法应该是同步的。否则你可能会构建多个实例。

    【讨论】:

    • 是的。我想这些天我会使用 Spring 或 Guice 来管理这些事情。
    【解决方案3】:

    我会在 init() 方法中设置一个断点,然后查看堆栈以查看调用的来源。

    【讨论】:

    • 它们都来自 deployDirectory,所以可能是因为 Tomcat 正在查看 webapp 并自动部署它,并且还看到 web.xml 并使用它进行部署,因为启动时贷款已设置...
    【解决方案4】:

    如果 init() 方法失败,它可能会在随后的 get 中再次调用。您是否检查了 catalina.out 文件以确保 init() 调用没有因某种原因中止?

    【讨论】:

    • 不,不会的。 Servlet 未加载,因此不会再次执行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 2011-07-17
    • 2021-06-23
    相关资源
    最近更新 更多