Tomcat - Servlet init() 在启动时调用两次

发布于 2024-12-03 01:34:27 字数 2220 浏览 1 评论 0原文

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

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

web.xml 片段(servlet 仅配置一次,并且仅在 web 应用程序 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 不会运行该 web 应用程序两次!

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

代码:

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);
  }
  // ...
}

I have an issue with a standalone Tomcat server (not linked with Apache).

When Tomcat starts up, the init() method of the servlet is getting called twice, i.e., two servlets are starting up. Even more worrying is that these appear to be loaded by different classloaders - there is only one Java process running on the command line so it's not multiple Tomcats.

web.xml snippet (the servlet is only configured once, and only configured in the 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>

I put some logging in the init method, and created a singleton class called RatesPoller that the init tries to get an instance of. From the logs we can see that the singleton instances are different:

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

So we have two distince servlets, and two distinct singleton pollers.

I suspect this means that Tomcat is launching two instances of the webapp that is stored in the Tomcat webapps folder. Obviously when you want to launch something that only one will be running, this is a problem, and I need to work out how to ensure that Tomcat doesn't run the webapp twice!

If anyone has any ideas ...

Code:

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!");
  }
}

and the init() method in LenderInterfaceServlet:

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);
  }
  // ...
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

愁杀 2024-12-10 01:34:27

Tomcat 会自动部署 webapp 中的任何内容,并且还会根据 server.xml 进行部署。只需从 Web 应用程序中删除您的 Web 应用程序即可避免双重加载。

Tomcat is autodeploying anything in webapps, and also deploying according to server.xml. Just remove your webapp from webapps to avoid double loading.

可可 2024-12-10 01:34:27

您的代码中有一个错误。你的单例不是线程安全的。 getInstance() 方法应该是同步的。否则您将有责任构造多个实例。

There is a bug in your code. Your singleton is not thread-safe. That getInstance() method should be synchronised. Otherwise you are liable to construct multiple instances.

月光色 2024-12-10 01:34:27

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

I would set a breakpoint in the init() method and then look at the stack to see where the calls are coming from.

开始看清了 2024-12-10 01:34:27

如果 init() 方法失败,则可能会在后续获取时再次调用它。您是否检查了 catalina.out 文件以确保 init() 调用不会因某种原因而中止?

If the init() method fails, it may be called again on a subsequent get. Did you check the catalina.out file to make sure that the init() call is not being aborted for some reason?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文