irpas技术客

log4j的替换方案,你知道吗?_Micro Stone_log4j 替换

网络 1312

去年12月份,随着log4j暴露出高危漏洞,对于 Java 开发人员来说不是一个好消息,对于 Ops 来说更是如此。前者必须使用固定的 Log4J 版本重新打包他们的应用程序,而后者必须重新部署。但对于程序log来说,并不只是。今天让我们来了解一下java系统自带的log机制

简而言之,System.Logger它是日志引擎的一个API。与其使用 SFL4J 的 API 和想要的实现,不如使用System.Logger。Java 9 开始java就已经开放了System.Logger,但我最近才知道它,这真是令人遗憾。

System.Logger API

该 API 与其他日志记录 API 有点不同:它避免了不同的日志记录方法,例如debug(),支持传递日志记录参数info()的单一方法。log()``Level``

?

如果您没有在类路径上提供任何相应的实现,则System.Logger默认为JUL。

public class LoggerExample { private static final System.Logger LOGGER = System.getLogger("c.f.b.DefaultLogger"); // 1 public static void main(String[] args) { LOGGER.log(DEBUG, "A debug message"); LOGGER.log(INFO, "Hello world!"); } } 获取记录器。

运行上面的代码段会输出以下内容:

Dec 24, 2021 10:38:15 AM c.f.b.DefaultLogger main INFO: Hello world! 广泛兼容其他日志系统

大多数应用程序当前使用Log4J2或SLF4J。两者都提供了兼容的System.Logger实现。

对于 Log4J,我们需要添加两个依赖项:

<dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <!-- 1 --> <version>2.17.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <!-- 2 --> <artifactId>log4j-jpl</artifactId> <version>2.17.0</version> </dependency> </dependencies> Log4J 实现System.LoggerSystem.Logger从到 Log4J 的支持。

与上面相同的日志记录片段现在输出以下内容:

11:00:07.373 [main] INFO c.f.b.DefaultLogger - Hello world!

要改用 SLF4J,需要添加以下依赖项:

<dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <!-- 1 --> <version>2.0.0-alpha5</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk-platform-logging</artifactId> <!-- 2 --> <version>2.0.0-alpha5</version> </dependency> </dependencies> **基本的 SLF4J 实现。任何其他实现都可以,*****例如***Logback。System.Logger从到 SLF4J 的支持。 [main] INFO c.f.b.DefaultLogger - Hello world! 你自己的System.Logger实现

System.Logger依赖于 Java 的ServiceLoader机制。两者log4j-jpl包含slf4j-jdk-platform-logging一个META-INF/services/java.lang.System$LoggerFinder指向LoggerFinder实现的文件。

?我们可以基于System.out目的创建我们自己的日志系统。 第一步是实现日志本身。

public class ConsoleLogger implements System.Logger { private final String name; public ConsoleLogger(String name) { this.name = name; } @Override public String getName() { return name; } @Override public boolean isLoggable(Level level) { return level.getSeverity() >= Level.INFO.getSeverity(); } @Override public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) { if (isLoggable(level)) { System.out.println(msg); thrown.printStackTrace(); } } @Override public void log(Level level, ResourceBundle bundle, String format, Object... params) { if (isLoggable(level)) { System.out.println(MessageFormat.format(format, params)); } } }

然后,我们需要编写代码System.LoggerFinder:

public class ConsoleLoggerFinder extends System.LoggerFinder { private static final Map<String, ConsoleLogger> LOGGERS = new HashMap<>(); // 1 @Override public System.Logger getLogger(String name, Module module) { return LOGGERS.computeIfAbsent(name, ConsoleLogger::new); // 2 } }

保留所有现有日志的路径:

如果它不存在,则创建一个记录器并存储它。

最后,我们创建一个服务文件:

ch.frankel.blog.ConsoleLoggerFinder

现在,运行相同的代码片段输出:

Hello world! 结论

虽然 API 比起其他更成熟的日志系统 API 更受限制,但这System.Logger是一个好选择。它提供了作为 JDK 一部分的api。因此,它避免了其他第三方api的漏洞风险,例如SLF4J 到 Log4J2。

出于这个原因,后期可基于System.Logger实现系统日志功能。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #log4j #替换 #JAVA #开发人员来说不是一个好消息对于 #Ops #来说更是如此 #前者必须使用固定的