在tomcat lib文件夹中的Spring jar

时间:2015-10-08 12:29:43

标签: java spring tomcat classloader

我对如何在tomcat中发生类加载感到困惑。如果我的问题听起来很愚蠢,请耐心等待。

我们在单个tomcat服务器上部署多个spring webapps。为了减少内存占用,我们考虑在tomcat lib文件夹中安装spring,hibernate和数据库驱动程序jar,以便所有webapp共享。

我首先将spring依赖项标记为provided并将这些jar复制到tomcat lib。但是在服务器启动时,我开始获得多个ClassNotFoundErrors,例如commons-loggingcommons-fileuploadjackson,所以我不得不将这些jar移到tomcat lib。

然而,这开始感觉很可疑。如果将来我在项目中添加另一个spring依赖项,比如spring-data-cassandra。我是否还需要移动它依赖的罐子?这可能是无止境的。我也可能在运行时遇到CNF错误。

我尝试关注this链接,并将spring-context和spring-web带回应用程序之战。但它没有工作,在WebApplicationIntializer初始化期间在某些类上获得了ClassNotFound。我试图理解classes getting loaded in tomcat的顺序,但不太了解。

然后我找到了JDBC driver loading的完全不同的解释,这与所有其他解释相矛盾,让我完全糊涂了。



当我读到更多内容时,我认为将弹簧罐移到tomcat lib并不是一个正确的方法,但仍然没有一个好的推理。然后为什么JDBC驱动程序有效?有人可以解释一下吗?每个webapp的classloader也会创建每个类的副本吗?

编辑1:我开始知道春季罐中的少数依赖项是optional,如果在我的webapp中使用,则需要它们。所以spring-web依赖于jackson库,但对于我的应用程序是可选的。因此,我需要找出我的项目所需的所有罐子,并且春天也需要这些罐子,这些罐子需要移动到tomcat lib。

2 个答案:

答案 0 :(得分:2)

我会尝试解释我所知道的事情。

在tomcat上部署WAR时,类加载将以这种方式进行:

  1. 查找要在WAR classLoader中加载的类
  2. 如果没有找到移动到父(tomcat / lib文件夹)
  3. 在你的情况下发生的事情是spring也有很多依赖关系,如果你把它打包在你的战争中,它的依赖关系也会被打包,一切都会好起来的。但是由于你将spring定义为提供的,所以它的所有依赖关系都被认为是提供的,当你把它放在/ lib文件夹中时,spring是可访问的,但它的依赖关系不是。

    您需要做的是将所有spring依赖项和依赖项的依赖项(等)放在lib文件夹中。另一种解决方案是在类加载层次结构中定义一个中间WAR,它将包含所有常用的库。

答案 1 :(得分:0)

如果您想创建这种类型的瘦WAR,一种解决方案是首先收集所有运行时/提供的依赖项,然后将其显式复制到Tomcat的公共(或共享)库目录下:

如果在Maven项目下,请收集target/dependency下的所有内容(包括传递依赖项):

mvn dependency:copy-dependencies -DincludeScope=runtime
mvn dependency:copy-dependencies -DincludeScope=provided

然后,复制到库。例如:

cp target/dependency/*.jar /usr/local/tomcat/lib/