log4j的替换方案
去年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.Logger
- System.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实现系统日志功能。
log4j的替换方案的更多相关文章
- Google Earth API 替换方案
众所周知,GE API将会在15年12月25日结束服务,对于众多采用该API的软件,需要一些替换方案. 例如google map或者cesiumjs http://cesiumjs.org/ 或者尝试 ...
- Microsoft.AspNet.Web.Optimization.Bundle的完美替换方案
Web应用程序中包含大量的样式(css)和脚本(js)文件,这些文件的引用.管理和发布有很多解决方案.在Asp.Net MVC应用程序中,大家最熟悉的解决方案应属Microsoft.AspNet.We ...
- arguments.callee的作用及替换方案
arguments.callee的作用 arguments 的主要用途是保存函数参数, 但这个对象还有一个名叫 callee 的属性,返回正被执行的 Function 对象,也就是所指定的 Funct ...
- UIActionSheet上加入UIPickerView iOS8替换方案
此套替换方案採用"UIView+动画"方式实现(将UIActionSheet替换为UIView) 界面层级例如以下: 第一层:view(这一层充满整个屏幕,初始化时颜色为透明.us ...
- switch...case...之替换方案一
很多时候,当switch中有N个分支,且分支数已达10+,每个分支都是一个不小的方法体,那我们是不是应该考虑换一种方式来实现这个分支. 而我目前所能想到的是会用到如下几种方法. 1.Action 2. ...
- spring boot拦截器WebMvcConfigurerAdapter,以及高版本的替换方案(转)
文章转自 http://blog.51cto.com/12066352/2093750 最近项目采用spring icloud,用的spring boot版本是1.5.x的,spring boot 2 ...
- JAVA字符配置替换方案
在JAVA中,很多时候,我们后台要对数据进行变量配置,希望可以在运行时再进行变量替换.我们今天给大空提供的是org.apache.commons.text方案. 1.首先,引用org.apache.c ...
- EF架构~为导航属性赋值时ToList()的替换方案
回到目录 今天在进行EF开发时,遇到一个问题,在进行join查询时,类中的一个集合类型的导航属性,在给它赋值时,将查询出来的结果ToList()后,出错了,linq to entity不支持这种操作, ...
- regexp_substr在oracle9i的替换方案
regexp_substr()方法在oracle9i尚不存在,是从oracle10g开始新增,如下为替换解决方法. SELECT regexp_substr('|83~GT67XVFU0RCVIV|6 ...
随机推荐
- IDEA导入Web项目配置Tomcat启动
1.导入项目 2.配置project 3.导入项目模块 配置Models 4.配置Libraries 5. 6. 7.配置tomcat
- 谱分解(SD)
前提:矩阵A必须可相似对角化! 充分条件: $A$ 是实对称矩阵 $A$ 有 $n$ 个互异特征值 $A^{\wedge} 2=A $ $\mathrm{A}^{\wedge} 2=\mathrm{E ...
- day 20 C语言顺序结构基础3
(1).若有定义:int a=100:则语句printf("%d%d%d\n",sizeof("a"),sizeof(a),sizeof(3.14)); 则输出 ...
- JUC并发编程与高性能内存队列disruptor实战-下
并发理论 JMM 概述 Java Memory Model缩写为JMM,直译为Java内存模型,定义了一套在多线程读写共享数据时(成员变量.数组)时,对数据的可见性.有序性和原子性的规则和保障:JMM ...
- VictoriaMerics学习笔记(2):核心组件
核心组件 1. 单机版 victoria-metrics-prod 单一二进制文件 读写都在一个节点上 作者推荐单机版 特性 merge方式配置 通过HTTP协议提供服务 内存限制(防止OOM) 使用 ...
- MySql服务器逻辑架构
一.MySql服务器逻辑架构图 每个虚线框都是一层: 第一层:最上层的服务器不是MySql所独有的,大多数基于网络的客户端/服务器工具或者服务都有类似的系统.比如链接处理,授权认证,安 ...
- Sentry 开发者贡献指南 - 什么是 Scope, 什么是 Hub?
当一个事件被捕获并发送到 Sentry 时,SDK 会将该事件数据与来自当前 scope 的额外信息合并.SDK 通常会在框架集成中为您自动管理 scope,您无需考虑它们.但是,您应该知道 scop ...
- java匿名内部类概述
1 package face_09; 2 /* 3 * 匿名内部类.就是内部类的简写格式. 4 * 必须有前提: 5 * 内部类必须继承或者实现一个外部类或者接口. 6 * 匿名内部类:其实就是一个匿 ...
- 【webpack4.0】---webpack的基本使用(三)
一.webpack-dev-server 1.安装 cnpm install webpack-dev-server -D 2.作用 开启一个web服务,监听文件的变化并自动刷新网页,做到实时预 ...
- 关于spring MVC 绑定json字符串与实体类绑定
1 如果前台传json字符串,后台用@RequestBody 接收 前端 "content-Type":"application/json", 2 前台用fo ...