在tomcat lib文件夹中的Spring jar

sid*_*ate 11 java spring tomcat classloader

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

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

我首先将spring依赖关系标记为,provided然后将这些jar复制到tomcat lib.但是,在服务器启动时,我开始越来越多ClassNotFoundErrors,像commons-logging,commons-fileupload,jackson,所以我必须将这些罐子以及到Tomcat的lib.

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

我试图按照这个链接,将spring-context和spring-web带回应用程序之战.但它没有用,在WebApplicationIntializer初始化期间在某些类上得到了ClassNotFound .我试图理解在tomcat中加载的顺序,但是不太了解.

然后我找到了一个完全不同的JDBC驱动程序加载解释,这与所有其他解释相矛盾,让我完全糊涂了.



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

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

小智 5

我将尝试解释我所知道的。

当您在 tomcat 上部署 WAR 时,类加载将以这种方式发生:

  1. 查找要在 WAR 类加载器中加载的类
  2. 如果未找到,则移至父级(tomcat /lib 文件夹)

在你的情况下,spring也有很多依赖项,如果你将它打包到你的war中,它的依赖项也会被打包,一切都会正常工作。但是,由于您将 spring 定义为提供的,因此它的所有依赖项也被视为提供,并且当您将其放入 /lib 文件夹时,spring 是可访问的,但其依赖项则不可访问。

您需要做的是将所有 spring 依赖项以及依赖项的依赖项(等)也放入 lib 文件夹中。另一个解决方案是在类加载层次结构中定义一个中间 WAR,其中包含所有公共库。