java⽇志体系

⽇志体系

  • 1.体系概述
  • 2.日志的使用
    • 1.上古时代的sout
    • 2.开创先驱的log4j
    • 3.搞事情的JUL
    • 4.应运⽽⽣的JCL
    • 5.再起波澜的logback
    • 6.再度⻘春的log4j2

本篇在jdk21下测试通过

1.体系概述

在这里插入图片描述
1.日志接口

  • JCL:Apache基⾦会所属的项⽬,是⼀套Java⽇志接⼝,之前叫Jakarta Commons Logging,后更名为Commons Logging,简称JCL
  • SLF4J:Simple Logging Facade for Java,缩写Slf4j,是⼀套简易Java⽇志⻔⾯,只提供相关接⼝,和其他⽇志⼯具之间需要桥接

2.⽇志实现

  • JUL:JDK中的⽇志⼯具,也称为jdklog、jdk-logging,⾃Java1.4以来sun的官⽅提供
  • Log4j:⾪属于Apache基⾦会的⼀套⽇志框架,现已不再维护
  • Log4j2:Log4j的升级版本,与Log4j变化很⼤,不兼容
  • Logback:⼀个具体的⽇志实现框架,和Slf4j是同⼀个作者,性能很好

2.日志的使用

1.上古时代的sout

在JDK 1.3及以前,Java打⽇志依赖System.out.println(), System.err.println()或者
e.printStackTrace(),Debug⽇志被写到STDOUT流,错误⽇志被写到STDERR流。这样打⽇志有⼀个⾮常⼤的缺陷,⾮常机械,⽆法定制,且⽇志粒度不够细分

System.out.println("123");
System.err.println("456");

2.开创先驱的log4j

注意了:这里案例采用的是log4j2的写法

2001年发布了Log4j,并将其捐献给了Apache软件基⾦会,成为Apache 基⾦会的顶级项⽬。Log4j 在设计上⾮常优秀,它定义的Logger、Appender、Level等概念对后续的 Java Log 框架有深远的影响,如今的很多⽇志框架基本沿⽤了这种思想

1.导入坐标

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.22.1</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.22.1</version>
</dependency>

2.编写配置文件 log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <File name="MyFile" fileName="logs/app.log">
            <PatternLayout>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %c{1} - %msg%n</pattern>
            </PatternLayout>
        </File>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="MyFile"/>
        </Root>
    </Loggers>
</Configuration>

3.测试类

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class MyLog4j {
    private static final Logger logger = LogManager.getLogger(MyLog4j.class);

    public static void main(String[] args) {
        int i = 1;
        String msg = "测试";
        String s = null;
        // 记录不同级别的日志
        logger.debug("Debug message:{},{},{}", i, msg, s);
        logger.info("Info message:{},{},{}", i, msg, s);
        logger.warn("Warning message:{},{},{}", i, msg, s);
        logger.error("Error message:{},{},{}", i, msg, s);
        logger.fatal("Fatal error message:{},{},{}", i, msg, s);
    }
}

3.搞事情的JUL

sun公司对于log4j的出现内⼼隐隐表示嫉妒。于是在jdk1.4版本后,开始搞事情,增加了⼀个包为java.util.logging,简称为JUL,⽤以对抗log4j ,但是却给开发造成了麻烦。相互引⽤的项⽬之间可能使⽤了不同的⽇志框架,经常将代码搞得⼀⽚混乱

import java.util.logging.Logger;

public class MyJul {
    static Logger logger = Logger.getLogger(MyJul.class.getName());

    public static void main(String[] args) {
        int i = 1;
        String msg = "测试";
        String s = null;
        logger.info( "Info message  :"  + i + " " + "s" + " " + msg);  
    }
}

4.应运⽽⽣的JCL

从上⾯可以看出,JUL的api与log4j是完全不同的(参数只接受String)。由于⽇志系统互相没有关联,彼此没有约定,不同⼈的代码使⽤不同⽇志,替换和统⼀也就变成了⽐较棘⼿的⼀件事。假如你的应⽤使⽤log4j,然后项⽬引⽤了⼀个其他团队的库,他们使⽤了JUL,你的应⽤就得使⽤两个⽇志系统了,然后其他团队⼜使⽤了simplelog……这个时候如果要调整⽇志的输出级别,⽤于跟踪某个信息,简直就是⼀场灾难
  那这个状况该如何解决呢?答案就是进⾏抽象,抽象出⼀个接⼝层,对每个⽇志实现都适配或者转接,这样这些提供给别⼈的库都直接使⽤抽象层即可 ,以后调⽤的时候,就调⽤这些接⼝。(⾯向接⼝思想)
  于是,JCL(Jakarta Commons Logging)应运⽽⽣,也就是commons-logging-xx.jar组件。JCL 只提供 log 接⼝,具体的实现则在运⾏时动态寻找。这样⼀来组件开发者只需要针对 JCL 接⼝开发,⽽调⽤组件的应⽤程序则可以在运⾏时搭配⾃⼰喜好的⽇志实践⼯具

1.导入坐标

<dependency>
   <groupId>commons-logging</groupId>
   <artifactId>commons-logging</artifactId>
   <version>1.3.0</version>
</dependency>

2.测试代码

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MyJul {
    private  static Log logger = LogFactory.getLog(MyJul.class);

    public static void main(String[] args) {
        int i = 1;
        String msg = "测试";
        String s = null;
        logger.info( "Info message  :" + i + " " + "s" + " " + msg);
        logger.debug("Debug message :" + i + " " + "s" + " " + msg);
        logger.fatal("Fatal message :" + i + " " + "s" + " " + msg);
        logger.error("Error message :" + i + " " + "s" + " " + msg);
    }

}

5.再起波澜的logback

针对以上情况,log4j的作者再次出⼿,他觉得JCL不好⽤,⾃⼰⼜写了⼀个新的接⼝api,就是slf4j,并且为了追求更极致的性能,新增了⼀套⽇志的实现,就是logback,⼀时间烽烟⼜起……

1.导入坐标

 <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>2.0.10</version>
 </dependency>

 <dependency>
     <groupId>ch.qos.logback</groupId>
     <artifactId>logback-core</artifactId>
     <version>1.4.14</version>
 </dependency>
 <dependency>
     <groupId>ch.qos.logback</groupId>
     <artifactId>logback-classic</artifactId>
     <version>1.4.14</version>
 </dependency>

2.编写配置文件logback.xml

<configuration>

    <!-- 定义日志输出格式 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{96} [%line] [%thread]- %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 定义日志文件输出 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/app.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天滚动,每天生成一个新的日志文件 -->
            <fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 文件保留策略,只保留最近30天的日志文件 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 设置全局日志级别 -->
    <root level="debug">
        <!-- 将控制台和文件Appender关联到根Logger -->
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </root>

    <!-- 针对特定包或类设置不同的日志级别 -->
    <!-- <logger name="com.andy.log.logback.*" level="debug" /> -->

</configuration>

3.测试代码

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyLogback {

    static final  Logger logger = LoggerFactory.getLogger(MyLogback.class);

    public static void main(String[] args) {
        int i = 1;
        String msg = "测试";
        String s = null;
        // 记录不同级别的日志
        logger.debug("Debug message:{}:{}:{}", i, msg, s);
        logger.info("Info message:{}:{}:{}", i, msg, s);
        logger.warn("Warning message:{},{},{}", i, msg, s);
        logger.error("Error message:{}:{}:{}", i, msg, s);
    }
}

6.再度⻘春的log4j2

请参考 “开创先驱的log4j” 的写法

log4j2以性能著称,它⽐其前身Log4j 1.x提供了重⼤改进,同时类⽐logback,它提供了Logback中可⽤的许多改进,同时修复了Logback架构中的⼀些固有问题。功能上,它有着和Logback相同的基本操作,同时⼜有⾃⼰独特的部分,⽐如:插件式结构、配置⽂件优化、异步⽇志等


到log4j2,轰轰烈烈的java log战役基本就结束了


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/305183.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python基础练习之—Series

Series介绍&#xff1a; Pandas Series 类似表格中的一个列&#xff08;column&#xff09;&#xff0c;类似于一维数组&#xff0c;可以保存任何数据类型。Series 由索引&#xff08;index&#xff09;和列组成&#xff0c;可以通过列表&#xff0c;元组&#xff0c;数组&…

qss设置某一个widget下的Checkbox的样式

#ObjectName 控件名称{属性&#xff1a;值&#xff1b;属性1&#xff1a;值1} 如下&#xff1a; 效果&#xff1a;

【QT-UI】

1.使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), …

K2P路由器刷OpenWrt官方最新版本固件OpenWrt 23.05.2方法 其他型号的智能路由器OpenWrt固件刷入方法也基本上适用

最近路由器在开机时总出问题,于是就那他来开刀,直接刷一个OpenWrt官方最新版本的固件, 刷其他第三方的固件总是觉得不安全, 而且很多第三方固件都带了些小工具,始终会有安全隐患, 而且占用内存空间太多,本来这个东西就没有多少内存,于是就干脆刷一个官方的原始固件(才6.3M, 相…

分析一个项目(微信小程序篇)一

分析一个项目讲究的是如何进行对项目的解析分解&#xff0c;进一步了解项目的整体结构&#xff0c;熟悉项目的结构&#xff0c;能够知道每个组件所处在哪个位置&#xff0c;发挥什么作用。 本次所介绍的是微信小程序项目&#xff08;甑选商场&#xff09;&#xff1a; 其首页…

论文阅读 BERT GPT - transformer在NLP领域的延伸

文章目录 不会写的很详细&#xff0c;只是为了帮助我理解在CV领域transformer的拓展1 摘要1.1 BERT - 核心1.2 GPT - 核心 2 模型架构2.1 概览 3 区别3.1 finetune和prompt 3.2 transformer及训练总结 不会写的很详细&#xff0c;只是为了帮助我理解在CV领域transformer的拓展 …

js(JavaScript)数据结构之数组(Array)

什么是数据结构&#xff1f; 下面是维基百科的解释&#xff1a; 数据结构是计算机存储、组织数据的方式。数据结构意味着接口或封装&#xff1a;一个数据结构可被视为两个函数之间的接口&#xff0c;或者是由数据类型联合组成的存储内容的访问方法封装。 我们每天的编码中都会…

Qt QLabel标签控件

文章目录 1 属性和方法1.1 文本1.2 对齐方式1.3 换行1.4 图像 2. 实例2.1 布局2.2 为标签添加背景色2.3 为标签添加图片2.4 代码实现 QLabeI是Qt中的标签类&#xff0c;通常用于显示提示性的文本&#xff0c;也可以显示图像 1 属性和方法 QLabel有很多属性&#xff0c;完整的可…

鸿鹄电子招投标系统源码实现与立项流程:基于Spring Boot、Mybatis、Redis和Layui的企业电子招采平台

随着企业的快速发展&#xff0c;招采管理逐渐成为企业运营中的重要环节。为了满足公司对内部招采管理提升的要求&#xff0c;建立一个公平、公开、公正的采购环境至关重要。在这个背景下&#xff0c;我们开发了一款电子招标采购软件&#xff0c;以最大限度地控制采购成本&#…

Spring MVC学习之——入门

Spring MVC 介绍 Spring MVC 是Spring框架的一个模块&#xff0c;是一个基于 MVC 设计模式的轻量级 Web 开发框架&#xff0c;本质上相当于 Servlet。 SpringMVC 是 Spring 为表示层开发提供的一整套完备的解决方案。在表述层框架历经 Strust、WebWork、Strust2 等诸多产品的…

作业--day43

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数&#xff0c;将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c…

图像分割实战-系列教程12:deeplab系列算法概述

&#x1f341;&#x1f341;&#x1f341;图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 1、空洞卷积 图像分割中的传统做法&#xff1a;为了增大感受野&#xff0c;通常都会选择pooling操…

centos7 yum添加源或换源

yum添加源或换源 一般来说yum源是我们需要下载的软件的远程仓库地址(当然也可以配置本地源)&#xff0c;centos系统带有几个官方源&#xff0c;默认启用的仅有base,updates和extras三个。有时我们需要的软件在官方源中没有&#xff0c;这时我们就需要添加第三方源或换默认源。…

Halcon根据灰度特征值选择区域select_gray

Halcon根据灰度特征值选择区域 与select_shape算子类似&#xff0c;灰度值图像也可以快捷地根据特征值选择符合设定条件的区域。select_gray算子用于实现这一功能&#xff0c;该算子能接受一组区域作为输入&#xff0c;然后根据选定的特征计算其是否满足特定的条件。当所有区域…

1.5号io网络

僵尸进程和孤儿进程 僵尸进程 孤儿进程 守护进程 1.守护进程相当于一个服务&#xff0c;不依赖于终端而存在 2.守护进程随着系统的启动而启动&#xff0c;关闭而关闭 3.守护进程创建流程 1、创建一个孤儿进程 2、重设守护进程的会话id和组id 3、修改守护进程的操作目录为…

指定linux文件夹下所有文件赋权命令“chmod -R 755”

仓库&#xff1a;Ai-trainee/GPT-Prompts-Hub 下面我们假设要为&#xff1a;/opt/robot/lib/robot_control/下所有子文件赋权 如果要为 robot_control 目录中的所有文件分配权限&#xff08;在 Linux 术语中也称为“更改文件权限”或“chmod”&#xff09;&#xff0c;则可以…

【从零开始学技术】Fiddler 抓取 https 请求大全

1.Fiddler代理浏览器设置 注意浏览器代理区别 Chrome/IE浏览器使用的都是系统代理设置 在chrome浏览器的设置中搜索代理&#xff0c;可以看到 打开IE浏览器&#xff0c;选择设置->Internet选项 Firefox浏览器使用的是单独的一套代理系统 在Firefox的代理设置中&#xff0c;我…

锂电池放电结束后电压回升,充电结束后电压下降

放电时&#xff0c;撤去负载&#xff0c;开路电压会上升&#xff1b;充电时&#xff0c;撤去电源&#xff0c;开路电压会下降。 一、极化 极化是指事物在一定条件下发生两极分化&#xff0c;使其性质相对于原来状态有所偏离的现象。 二、电化学极化 对于任何电化学体系中&am…

java注解学习

java注解 Annotation 为什么要学注解&#xff1f; 在日常开发中&#xff0c;基本都是在使用别人定义或是各种框架的注解&#xff0c;比如Spring框架中常用的一些注解&#xff1a;Controller、Service、RequestMapping&#xff0c;以此来实现某些功能&#xff0c;但是却不知道如…

玩转硬件之C51的玩法(二)——模拟按键模块

模拟按键模块是一种常见的电子元件&#xff0c;它具有简单、易用、可靠的特点&#xff0c;被广泛应用于各种电子设备中。它的工作原理是通过按下按钮&#xff0c;使开关接通或断开电路&#xff0c;从而实现控制电子设备的功能。 AD Keyboard模块可以适用Arduino和C51&#xff…