让 SLF4J 运行而无需将任何内容处理到 WebLogic 库目录中

Posted

技术标签:

【中文标题】让 SLF4J 运行而无需将任何内容处理到 WebLogic 库目录中【英文标题】:Get SLF4J running without coping anything into WebLogic lib-directory 【发布时间】:2022-01-23 17:32:28 【问题描述】:

我需要让 SLF4J 在 WebLogic 应用程序中工作。根据 Buttso [1] 和 Oracle [2],需要将文件复制到 domain/lib 目录:

slf4j-api slf4j-jdk14-1.6.0.jar

然后在logging.property文件中定义如下处理程序:

 handlers = weblogic.logging.ServerLoggingHandler

并附加以下参数启动 WebLogic。

-Djava.util.logging.config.file=C:\tmp\logging.properties

我理解为什么必须全局定义属性文件。但我不明白,为什么必须将 JAR 复制到 WebLogic 的 domain/lib 目录中。 我试图将它们留在我的 WAR 文件中,但它不起作用。

有没有办法将日志库保留在应用程序的控制之下?这个限制是从哪里来的?可以直接从应用程序中使用 Weblogic 的 JDK14 日志记录基础设施:

java.util.logging.Logger LOGGER = java.util.logging.Logger.getLogger("my.logger.Name");
LOGGER.info("JDK14 Anonymous info");

它按预期工作。处理程序weblogic.logging.ServerLoggingHandler 能够成功拦截消息并将其转发到 WSL 日志文件中。为什么 SLF4J 桥不能做同样的事情?


[1] 将 SLF4J 与 WebLogic Server 日志记录一起使用 http://buttso.blogspot.com/2011/06/using-slf4j-with-weblogic-server.html

[2] 如何将 SLF4J 重定向到 WebLogic 日志系统? https://support.oracle.com/epmos/faces/DocumentDisplay?id=1507456.1(需要 Oracle 订阅)

【问题讨论】:

【参考方案1】:

镜头说明:

它与应用程序打包的 SLF4J 完美配合。重要的是 API slf4j-api 和实现 slf4j-jdk14 必须由同一个类加载器加载。

详细说明:

默认情况下,Weblogic 类加载器具有优先级。如果两个库(slf4j-apislf4j-jdk14)都位于 domain/lib 目录中,则不会出错。

如果 slf4j-api 位于应用程序类路径中但不在 Weblogic 类路径中,则可能发生两种情况:

SLF4J 发现一些与应用程序打包在一起的错误实现。例如,它可能是作为某些第三方库的强制依赖项的 logback。在这种情况下,消息将被转发到错误的实现中,并且不会到达 WebLogic 日志基础架构。

SLF4J 在 WebLogic 类路径中找到了一些实现。在这种情况下,应用程序很可能会因为ClassCastException而无法部署。

正如我所说,可以在应用程序中包含所有 SLF4J 日志库。例如,如果 WebLogic 服务器是共享实例并且不受您的控制,则需要它。需要做两件事:

确保只有一个 SLF4J 实现与应用程序打包在一起。在我们的例子中是slf4j-jdk14。确保maven clean 确保之前尝试的所有剩余都从 WAR 文件中删除!

强制使用应用程序类加载器来加载 SLF4J 库。由WEB-INF/weblogic.xml 完成,如下所示:

<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" 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_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.9/weblogic-web-app.xsd">
    <wls:weblogic-version>14.1.1.0</wls:weblogic-version>
    <wls:context-root>test-oauth</wls:context-root>
    <wls:container-descriptor>
        <wls:prefer-application-packages>
            <wls:package-name>org.slf4j.*</wls:package-name>
        </wls:prefer-application-packages>
    </wls:container-descriptor>
</wls:weblogic-web-app>

这是一个有用的示例,如何找出哪个类加载器负责给定的类或实例。

Which classloader loaded a class of the provided instance

【讨论】:

以上是关于让 SLF4J 运行而无需将任何内容处理到 WebLogic 库目录中的主要内容,如果未能解决你的问题,请参考以下文章

为啥要使用SLF4J而不是Log4J

为啥使用 SLF4J 而不是 Log4J 来做 Java 日志

根据输入到单元格中的数字为单元格分配颜色和值,而无需点击运行按钮

将数据从片段发送到活动,无需任何事件处理或侦听器

如何让 Slim 框架工作而无需将 /index.php 放入 URL?

我可以使用 301 重定向来允许现有的 .Net Web 服务继续运行而无需客户端更新吗?