$CATALINA_HOME/shared/lib 是 Tomcat 中的真正功能吗? [英] Is $CATALINA_HOME/shared/lib a real feature in Tomcat?

查看:65
本文介绍了$CATALINA_HOME/shared/lib 是 Tomcat 中的真正功能吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过编辑 catalina.properties 文件来告诉 Tomcat 使用该文件夹,为名为 shared.loader 的属性赋值.

共享类加载器

您指的是 Tomcat 的共享加载器功能.

正如您所提到的,不应在 Tomcat 实例中的多个 Web 应用程序之间单独复制某些具有 JDBC 驱动程序的 JAR.此主题已在 Stack Overflow 上多次讨论.

此类 JAR 应由共享的 Java 类加载器加载,而不是由每个网络应用类加载器.

几个类加载器

如上图所示,Tomcat 可以使用许多不同的类加载器,如 在文档中解释.

BootstrapSystem 类加载器与我们在这里的讨论无关.

Server 类加载器是 Tomcat 自己需要的.这可能包括代表您在数据库中查找与 Realm 相关的用户.在这种情况下,Tomcat 需要您选择的数据库的 JDBC 驱动程序.

Webapp1 的图表所示 &Webapp2,您的每个网络应用程序也都有一个类加载器.这使每个网络应用程序保持独立,防止它们相互影响.例如,每个 Web 应用程序可能使用不同版本的日志记录框架.

JDBC 驱动程序的诀窍在于它们在 JVM 范围的单例 DriveManager 对象中共享一个注册表.不幸的是,JDBC 团队的这种设计选择与使用各种类加载器的应用服务器(例如 Tomcat)的需求相冲突.这在问题中讨论,为什么必须将 JDBC 驱动程序放在 TOMCAT_HOME/lib 文件夹中?以及许多其他.

因此最好为 Tomcat 的类加载器中的每种 JDBC 驱动程序共享一个 JAR 文件.这确实意味着您的所有 Web 应用程序必须使用相同版本的每种 JDBC 驱动程序(Postgres、H2、Oracle 等).

  • 如果您在 Tomcat 中启用 Realm 用户查找功能,那么 Tomcat 可能无法使用自己的数据库.因此,您可以将 JDBC 驱动程序放在 Shared 类加载器中,以便在一个或多个 Web 应用程序中使用.
  • 如果您已经在 Tomcat 中启用了一些需要您的数据库的东西,那么将该 JDBC JAR 文件放在 Common 类加载器中,以便在 Tomcat 的内部您的一个或多个网络应用.

诀窍是,默认情况下,Tomcat 只专门定义了 Common 类加载器.Common 类加载器与 ServerShared 类加载器有双重作用.要为 Server 和/或 Shared 激活单独的类加载器,请编辑 catalina.properties 文件.寻找 server.loader &shared.loader 属性.

catalina.properties 文件

至于文档,请参阅手册中的此主页:类加载器操作方法.也在 wiki 页面中提及.

$CATALINA_HOME/conf/catalina.properties 文件中的注释中简要讨论了这个问题.根据他们的 Apache 许可 2 条款摘录:

<预><代码>## 定义共享"内容的逗号分隔路径列表# 类加载器.应该使用前缀来定义存储库类型.# 路径可能是相对于 CATALINA_BASE 路径或绝对路径.如果留空,# 通用"加载器将用作 Catalina 的共享"加载器.# 例子:# "foo": 将此文件夹添加为类存储库# "foo/*.jar": 将指定文件夹的所有jar包添加为class# 存储库# "foo/bar.jar": 添加 bar.jar 作为类库# 请注意,对于单个罐子,例如bar.jar,你需要 URL 形式# 以文件开头:.## 注意:值可以用双引号 ("...") 括起来,以防万一# ${catalina.base} 路径或 ${catalina.home} 路径包含逗号.# 因为双引号是用来引用的,所以双引号字符# 可能不会出现在路径中.shared.loader=

请注意 shared.loader 属性的默认值为空.正如评论所解释的那样,Tomcat 将回退到使用其通用加载器",该加载器从 Catalina Home 文件夹中的 lib 文件夹以及 Catalina 中的 lib 文件夹加载 JAR.基本文件夹(有些人将其定义为 Tomcat 文件夹之外的文件夹,以便于管理).

创建并指定您自己的 JAR 文件夹

您可以自由地指定任何文件夹来保存您的 JAR 文件,以便 Tomcat 通过其共享加载程序"访问(前提是您运行 Tomcat 的系统用户帐户具有 该文件夹的文件系统权限).AFAIK,创建嵌套的 shared/lib 文件夹只是约定.

Tomcat 文件夹内

如果您想将 Tomcat 文件夹用于诸如 $CATALINA_HOME/shared/lib 之类的内容:

  1. 创建一对shared &lib 文件夹(具有适当的文件系统权限).
  2. 编辑 $CATALINA_HOME/conf/catalina.properties 以将 shared.loader= 替换为:
    shared.loader="${catalina.home}/shared/lib","${catalina.home}/shared/lib/*.jar"

请注意我们如何按照上面引用的注释的说明使用双引号.我们只为类文件指定了 lib,为 JAR 文件指定了 lib/*.jar.

Tomcat 文件夹外

如果您是选择将 Web 应用程序保存在 Tomcat 文件夹外部的文件夹中的人之一,那么您将定义 catalina.base 为那个外面的文件夹.在这种情况下,您可能希望将共享的 JAR 文件也保存在那里,而不是保存在 Tomcat 文件夹中.所以你可能希望在那里创建你的 shared/lib.按照那些引用评论中的例子:

  1. 创建一对shared &lib 文件夹(具有适当的文件系统权限)在您的外部文件夹中.
  2. 编辑 $CATALINA_HOME/conf/catalina.properties 以将 shared.loader= 替换为:
    shared.loader="${catalina.base}/shared/lib","${catalina.base}/shared/lib/*.jar"

注意我们如何使用 catalina.base 而不是 catalina.home.

在Tomcat文件夹内.

您可以指定查看 Tomcat 文件夹(home")内和 Tomcat 文件夹外(base")的 /shared/lib 文件夹.

同时使用 .base &.home:

shared.loader="${catalina.base}/shared/lib","${catalina.base}/shared/lib/*.jar","${catalina.home}/shared/lib","${catalina.home}/shared/lib/*.jar"

<小时>

如果您使用 Maven 来驱动您的 Java 项目,您将需要编辑您的POM 文件为您的特定 JDBC 驱动程序设置依赖项.在该 元素中,您需要将 设置为值 provided 以避免捆绑您的副本Web 应用程序的 WAR 文件中的 JDBC 驱动程序.请参阅此答案.

<小时>

这个旧的 Tomcat wiki 页面简要提到了创建 shared/lib 文件夹的相同技术,然后编辑 catalina.properties 文件以定义名为 shared.loader 的属性的值.

In Apache Tomcat, I have seen some posts that refer to the path $CATALINA_HOME/shared/lib.

When I download Tomcat, I see no shared folder nested in the Tomcat home folder.

I do see a $CATALINA_HOME/lib path, a lib folder nested in the Tomcat home folder. I understand this is the proper place for JAR files that should not be copied across "contexts" (web apps) in Tomcat. JDBC drivers are one important example of such.

The problem is that Tomcat populates that $CATALINA_HOME/lib folder with many JARs for its own use. So for the sake of neatness and ease of administration, it would make sense to have another folder that held nothing but our added JARs, separate from Tomcat’s own JARs. So I can understand the need for something like $CATALINA_HOME/shared/lib.

The problem is that:

  • (a) I see no shared folder,
  • (b) I cannot find any documentation about such a folder.

➥ Is this shared/lib a real feature, and should I create this pair of folders nested within the Tomcat home folder?

➥ Is $CATALINA_HOME/shared/lib an undocumented feature, perhaps just a hack that might go away in future updates?

I am asking for Tomcat 9 specifically. But Tomcat 8 is still in common usage, so an answer there too would be of use to other folks.

解决方案

Caveat: I am not a Tomcat expert, this Answer is merely my cobbled-together understanding of how things work. I may well be wrong; please correct me.

tl;dr

Yes, this is a real feature.

You can create a folder most anywhere you want to collect the JAR files to be shared across one or more web apps within Tomcat.

Tell Tomcat to use that folder by editing catalina.properties file to assign a value to the property named shared.loader.

Shared class loader

You are referring to the shared loader feature of Tomcat.

As you mentioned, some JARs such has JDBC drivers should not be replicated separately across multiple web-apps within a Tomcat instance. This topic has been discussed many times on Stack Overflow.

Such JARs should be loaded by a shared Java Class Loader, rather than the per-web-app class loaders.

Several class loaders

As you can see in the diagram above, Tomcat can use many different class loaders, as explained in the doc.

The Bootstrap and System class loaders are irrelevant to our discussion here.

The Server class loader is used by Tomcat's own needs. This may include looking up Realm related users in a database on your behalf. In such a case, Tomcat needs a JDBC driver to your database of choice.

As seen in the diagram with Webapp1 & Webapp2, each of your web apps also get a class loader. This keeps each web-app separate, preventing them from stepping on each other’s toes. For example, each web app might use a different version of a logging framework.

The trick with JDBC drivers is that they share a registry in a JVM-wide singleton DriveManager object. This design choice by the JDBC team unfortunately conflicts with the needs of an app server such as Tomcat using various class loaders. This is discussed in Question, Why must the JDBC driver be put in TOMCAT_HOME/lib folder? and in many others.

So it is best to share a single JAR file for each kind of JDBC driver across Tomcat's class loaders. That does mean all your web-apps must use the same version of each kind of JDBC driver (Postgres, H2, Oracle, etc.).

  • If you have not enabled the Realm user lookup feature in Tomcat, then Tomcat may have no use of its own for your database. So you can put your JDBC driver in the Shared class loader, for use across one or more web apps.
  • If you have enabled something in Tomcat that needs your database, then put that JDBC JAR file in the Common class loader for use across both Tomcat’s internals and one or more of your web apps.

The trick is that by default, Tomcat only defines the Common class loader specifically. The Common class loader does double-duty as the Server and Shared class loaders. To activate separate class loaders for Server and/or Shared, edit the catalina.properties file. Look for the server.loader & shared.loader properties.

catalina.properties file

As for documentation, see this main page in the manual: Class Loader How-To. Also a mention in a wiki page.

This issue is briefly discussed in comments found within the $CATALINA_HOME/conf/catalina.properties file. Excerpting, per their Apache License 2 terms:

#
# List of comma-separated paths defining the contents of the "shared"
# classloader. Prefixes should be used to define what is the repository type.
# Path may be relative to the CATALINA_BASE path or absolute. If left as blank,
# the "common" loader will be used as Catalina's "shared" loader.
# Examples:
#     "foo": Add this folder as a class repository
#     "foo/*.jar": Add all the JARs of the specified folder as class
#                  repositories
#     "foo/bar.jar": Add bar.jar as a class repository
# Please note that for single jars, e.g. bar.jar, you need the URL form
# starting with file:.
#
# Note: Values may be enclosed in double quotes ("...") in case either the
#       ${catalina.base} path or the ${catalina.home} path contains a comma.
#       Because double quotes are used for quoting, the double quote character
#       may not appear in a path.
shared.loader=

Notice how the default value for that shared.loader property is blank. As the comments explain, Tomcat will fallback to using its "common loader" which loads JARs from a lib folder in the Catalina Home holder as well as a lib folder in the Catalina Base folder (which some folks define as being a folder outside of the Tomcat folder, for ease of administration).

Create and specify your own folder of JARs

You are free to designate any folder to hold your JAR files to be accessed by Tomcat via its "shared loader" (provided your system's user account running Tomcat has file system privileges to that folder). AFAIK, creating a nested shared/lib folder is just convention.

Inside the Tomcat folder

If you want to use the Tomcat folder for something like $CATALINA_HOME/shared/lib:

  1. Create the pair of shared & lib folders (with proper file system privileges).
  2. Edit the $CATALINA_HOME/conf/catalina.properties to replace shared.loader= with:
    shared.loader="${catalina.home}/shared/lib","${catalina.home}/shared/lib/*.jar"

Notice how we used double-quotes as instructed by the comments quoted above. And we specified with just lib for class files as well as lib/*.jar for JAR files.

Outside the Tomcat folder

If you are one of those people who elect to keep your web-apps in a folder outside of the Tomcat folder, you will have defined catalina.base to be that outside folder. In such a case, you will likely want to keep your shared JAR files there too, rather than inside the Tomcat folder. So you may want the create your shared/lib there. Following the example in those quoted comments:

  1. Create the pair of shared & lib folders (with proper file system privileges) in your outside folder.
  2. Edit the $CATALINA_HOME/conf/catalina.properties to replace shared.loader= with:
    shared.loader="${catalina.base}/shared/lib","${catalina.base}/shared/lib/*.jar"

Notice how we used catalina.base rather than catalina.home.

Both inside and outside Tomcat folder.

You could specify looking at /shared/lib folders both inside your Tomcat folder ("home") and also outside your Tomcat folder ("base").

Use both .base & .home:

shared.loader="${catalina.base}/shared/lib","${catalina.base}/shared/lib/*.jar","${catalina.home}/shared/lib","${catalina.home}/shared/lib/*.jar"


If you are using Maven to drive your Java project, you will want to edit your POM file to set a dependency for your particular JDBC driver. In that <dependency> element, you will want to set the <scope> to the value provided to avoid bundling a copy of your JDBC driver within your web-app’s WAR file. See this Answer.


This old Tomcat wiki page mentions briefly this same technique of creating your shared/lib folders, then editing catalina.properties file to define a value for property named shared.loader.

这篇关于$CATALINA_HOME/shared/lib 是 Tomcat 中的真正功能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆