有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

由于类加载器,java在Tomcat web应用程序中实现单例模式时遇到问题

我试图在Linux上用x86_64 OpenJDK 1.6在Tomcat 6.24中实现一个单例

我的应用程序只是一堆JSP和一些静态内容,JSP调用我的Java代码。目前在网上。xml就像这样:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

<description>
    App Name
</description>
<display-name>App Name</display-name>

<!-- The Usual Welcome File List -->
<welcome-file-list>
    <welcome-file>pages/index.jsp</welcome-file>
 </welcome-file-list>

</web-app>

以前,当我尝试加载我的单例时,它被实例化了两次,因为类被两个不同的类加载器加载(我不知道为什么),每个加载器都会创建一个单例实例,这对于我的应用程序来说是不可接受的。我最终发现,如果我将代码导出为jar并将其放入$CATALINA_HOME/lib中,那么只有一个实例,但这不是一个优雅的解决方案

我在谷歌上搜索了几个小时,但还没有找到任何东西。我想知道是否还有其他解决办法。目前我没有预编译JSP,这可能是问题的一部分吗?我可以编写一个servlet来确保创建单例吗?如果是,我该怎么做


共 (4) 个答案

  1. # 1 楼答案

    第一次创建单例是什么时候?您可以通过包含以下命令来强制在加载index.jsp时创建它:

    <%! MySingleton instance = MySingleton.getInstance(); %>
    

    线路

    如果预编译jsp并将tomcat配置为从不自动重新加载类或jsp,则singleton应保持为single:-)

  2. # 2 楼答案

    Once I changed all the URLs to use http://localhost/ instead of http://localhost/appname the problem was fixed.

    这意味着您已经部署了2个Web应用程序,并期望它们使用相同的类加载器。这是不真实的。如果您想要一个所有Web应用程序都使用的共享库,那么应该将它放在由“Tomcat shared”表示的路径中(可通过catalina.properties文件中的shared.loader进行配置)。您只需确保在webapp自己的库或Tomcat/lib中没有此库

  3. # 4 楼答案

    为了确保单例的正确初始化,您应该检查您使用的是默认的父类第一类加载器,请参见http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html

    然后定义一个ServletContextListener并在方法中初始化您的单例:

    contextInitialized(ServletContextEvent sce)  
    

    它保证在任何servlet或过滤器之前被调用

    All ServletContextListeners are notified of context initialization before any filter or servlet in the web application is initialized.

    在web中定义ServletContextListener。xml