Tomcat:如何以编程方式在 GlobalNamingResources 中定义数据源资源并将其 link 应用程序
Tomcat: How to programmatically define a Datasource Resource in GlobalNamingResources and link it to apps
我正在使用 Tomcat9 部署共享相同数据源连接池的多个应用程序。我通过以下方式达到了目的:
- 在 conf/server.xml,
中将数据源添加为 GlobalNamingResources 下的 Resource 元素
- 将 conf/context.xml 中的 ResourceLink 元素用于 link 全局 JNDI 资源,使其可用于所有 Web 应用程序,并且
- 从 Web 应用程序使用 JNDI 访问数据源。
它按预期工作。
但是,我得到了避免编辑任何 xml(server.xml 或 conf/context.xml 或应用特定 context.xml)的要求,并尝试以编程方式实现第 1 步和第 2 步。如果是这样,优点是,只需要修改一个需要添加到 /lib 中的 jar 以支持新数据源,而绝对不需要对任何 xml 进行修改(或者可以在 [=31= 中进行最小配置) ]).
是否有任何方法可以实现将资源定义为 GlobalNamingResources 并通过 ResourceLink link 将其定义为 Web 应用程序的要求,全部通过 Java?
通过 tomcat java 文档后,我已经达到了我的要求。详情如下:
1.将数据源添加为 GlobalNamingResource
为此,创建一个服务器生命周期侦听器,创建一个数据源并将其添加到 JNDI GlobalNamingContext。
public class GlobalDatasourceCreator implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getSource() instanceof Server) {
Context namingContext = ((Server) event.getSource()).getGlobalNamingContext();
if (Lifecycle.START_EVENT.equals(event.getType())) {
bindDatasources(namingContext);
} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
unbindDatasources(namingContext);
}
}
}
private void bindDatasources(Context namingContext) {
if (createSubContext(namingContext)) {
try {
DataSource ds = getDatasource(); //TODO: Implement it
namingContext.rebind("jdbc/myds_global", ds);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private boolean createSubContext(Context namingContext) {
try {
namingContext.createSubcontext("jdbc");
} catch (NameAlreadyBoundException e) {
} catch (NamingException e) {
return false;
}
return true;
}
private void unbindDatasources(Context namingContext) {
try {
namingContext.unbind("jdbc/myds_global");
} catch (NamingException e) {
e.printStackTrace();
}
}
然后将这个class添加到conf/server。xml作为监听器
<Listener className="com.test.GlobalDatasourceCreator" />
2。通过 ResourceLink
向所有 Web 应用程序公开数据源
创建上下文 LifecycleListener。在 START 事件中,创建 ResourceLink 并将其附加到上下文。
注意:由于这是上下文级别的侦听器,因此将为所有应用程序创建 ResourceLink。我的要求是将它暴露给所有应用程序,因为它是一个受控环境。如果只需要为选定的应用程序创建 ResourceLink,则可以应用基于上下文名称的过滤。
public class AppDatasourceLinkCreator implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getSource() instanceof Context) {
Context ctx = (Context) event.getSource();
if (Lifecycle.START_EVENT.equals(event.getType())) {
addResourceLink(ctx);
} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
removeResourceLink(ctx);
}
}
}
private void removeResourceLink(Context ctx) {
ctx.getNamingResources().removeResourceLink("jdbc/myds");
}
private void addResourceLink(Context ctx) {
ContextResourceLink resourceLink = new ContextResourceLink();
resourceLink.setGlobal("jdbc/myds_global");
resourceLink.setName("jdbc/myds");
resourceLink.setType("javax.sql.DataSource");
ctx.getNamingResources().addResourceLink(resourceLink);
}
}
然后将这个class添加到conf/context。xml作为监听器
<Listener className="com.test.AppDatasourceLinkCreator" />
创建一个包含这两个 class 的 jar 并将其放在 /lib 文件夹中。
优点:无需进一步 xml 修改即可添加任意数量的数据源。只需修改 java 代码添加新数据源,更新 lib 文件夹中的 jar 并重新启动服务器,这完全符合我的项目要求。这也解决了 xml 中以纯文本形式公开数据源凭据的问题(尽管不是 100% 的风险证明)。
我正在使用 Tomcat9 部署共享相同数据源连接池的多个应用程序。我通过以下方式达到了目的:
- 在 conf/server.xml, 中将数据源添加为 GlobalNamingResources 下的 Resource 元素
- 将 conf/context.xml 中的 ResourceLink 元素用于 link 全局 JNDI 资源,使其可用于所有 Web 应用程序,并且
- 从 Web 应用程序使用 JNDI 访问数据源。
它按预期工作。
但是,我得到了避免编辑任何 xml(server.xml 或 conf/context.xml 或应用特定 context.xml)的要求,并尝试以编程方式实现第 1 步和第 2 步。如果是这样,优点是,只需要修改一个需要添加到 /lib 中的 jar 以支持新数据源,而绝对不需要对任何 xml 进行修改(或者可以在 [=31= 中进行最小配置) ]).
是否有任何方法可以实现将资源定义为 GlobalNamingResources 并通过 ResourceLink link 将其定义为 Web 应用程序的要求,全部通过 Java?
通过 tomcat java 文档后,我已经达到了我的要求。详情如下:
1.将数据源添加为 GlobalNamingResource
为此,创建一个服务器生命周期侦听器,创建一个数据源并将其添加到 JNDI GlobalNamingContext。
public class GlobalDatasourceCreator implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getSource() instanceof Server) {
Context namingContext = ((Server) event.getSource()).getGlobalNamingContext();
if (Lifecycle.START_EVENT.equals(event.getType())) {
bindDatasources(namingContext);
} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
unbindDatasources(namingContext);
}
}
}
private void bindDatasources(Context namingContext) {
if (createSubContext(namingContext)) {
try {
DataSource ds = getDatasource(); //TODO: Implement it
namingContext.rebind("jdbc/myds_global", ds);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private boolean createSubContext(Context namingContext) {
try {
namingContext.createSubcontext("jdbc");
} catch (NameAlreadyBoundException e) {
} catch (NamingException e) {
return false;
}
return true;
}
private void unbindDatasources(Context namingContext) {
try {
namingContext.unbind("jdbc/myds_global");
} catch (NamingException e) {
e.printStackTrace();
}
}
然后将这个class添加到conf/server。xml作为监听器
<Listener className="com.test.GlobalDatasourceCreator" />
2。通过 ResourceLink
向所有 Web 应用程序公开数据源创建上下文 LifecycleListener。在 START 事件中,创建 ResourceLink 并将其附加到上下文。
注意:由于这是上下文级别的侦听器,因此将为所有应用程序创建 ResourceLink。我的要求是将它暴露给所有应用程序,因为它是一个受控环境。如果只需要为选定的应用程序创建 ResourceLink,则可以应用基于上下文名称的过滤。
public class AppDatasourceLinkCreator implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getSource() instanceof Context) {
Context ctx = (Context) event.getSource();
if (Lifecycle.START_EVENT.equals(event.getType())) {
addResourceLink(ctx);
} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
removeResourceLink(ctx);
}
}
}
private void removeResourceLink(Context ctx) {
ctx.getNamingResources().removeResourceLink("jdbc/myds");
}
private void addResourceLink(Context ctx) {
ContextResourceLink resourceLink = new ContextResourceLink();
resourceLink.setGlobal("jdbc/myds_global");
resourceLink.setName("jdbc/myds");
resourceLink.setType("javax.sql.DataSource");
ctx.getNamingResources().addResourceLink(resourceLink);
}
}
然后将这个class添加到conf/context。xml作为监听器
<Listener className="com.test.AppDatasourceLinkCreator" />
创建一个包含这两个 class 的 jar 并将其放在 /lib 文件夹中。
优点:无需进一步 xml 修改即可添加任意数量的数据源。只需修改 java 代码添加新数据源,更新 lib 文件夹中的 jar 并重新启动服务器,这完全符合我的项目要求。这也解决了 xml 中以纯文本形式公开数据源凭据的问题(尽管不是 100% 的风险证明)。