由于Class Loader而在Tomcat Web应用程序中实现Singleton模式时出现问题

时间:2010-05-03 20:07:47

标签: java tomcat servlets singleton classloader

我正在尝试使用x86_64 OpenJDK 1.6在Linux上的Tomcat 6.24中实现Singleton。

我的应用程序只是一堆JSP和一些静态内容,而JSP则调用我的Java代码。目前web.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>

在我尝试加载我的Singleton之前,它被实例化了两次,因为类被两个不同的类加载器加载(我不知道为什么)并且每个加载器都会创建一个单例的实例,这是不可接受的为我的申请。我终于弄明白,如果我将我的代码导出为jar并将其放在$ CATALINA_HOME / lib中,那么只有一个实例,但这不是一个优雅的解决方案。

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

4 个答案:

答案 0 :(得分:2)

好的,我终于找到了问题。

我通过添加到server.xml并将路径设置为“”使我的应用程序成为服务器的默认应用程序。但是,当我通过网址http://localhost/somepage.jsp访问某些内容时,以及其他内容的网址http://localhost/appname/anotherpage.jsp

我将所有网址更改为使用http://localhost/而不是http://localhost/appname后问题得到解决。

答案 1 :(得分:1)

为确保正确初始化Singleton,您应该检查您是否使用默认的父级优先级类加载器,请参阅http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html

然后在方法中定义ServletContextListener并初始化您的Singleton:

contextInitialized(ServletContextEvent sce)  
保证在任何servlet或过滤器之前调用

  

所有ServletContextListeners都是   通知上下文初始化   在任何过滤器或servlet之前   Web应用程序已初始化。

在web.xml中定义ServletContextListener

答案 2 :(得分:0)

什么时候首先创建单身?您可以通过包含:

强制在加载index.jsp时创建它
<%! MySingleton instance = MySingleton.getInstance(); %>

线。

如果您预先编译jsp并将tomcat配置为永远不会自动重新加载类或jsp,则单例应保持单一: - )

答案 3 :(得分:0)

  

我将所有网址更改为使用http://localhost/而不是http://localhost/appname后问题得到解决。

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