云南网站建设专业品牌/百度视频推广
一,我们采用硬编码体验一下几个使用比较多的日志
分别导入几种日志的 jar 包
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.fll</groupId><artifactId>log-system-study</artifactId><version>1.0-SNAPSHOT</version><name>log-system-study</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><!-- === log4j1 相关jar包 ==== --><!-- 单独导入 log4j1 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- === log4j2 相关jar包 === --><!-- 单独导入 log4j2 --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.13.3</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.13.3</version></dependency><!-- === logback 相关jar包 ==== --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.4</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.4</version></dependency></dependencies><build></build></project>
package com.fll;import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.joran.spi.JoranException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.junit.Test;import java.net.URL;
import java.util.logging.Logger;public class LoggerTest {/*** java自带的日志工具 * java.util.logging.Logger*/@Testpublic void julLogger() {Logger logger = Logger.getLogger("julLogger");//System.setProperty("-Djava.util.logging.config.file", "classpath:/logging.properties");//logger.setLevel(Level.FINE);logger.info("julLogger Hello World!");
//运行结果 显示红色
//七月 30, 2024 10:51:38 上午 com.fll.LoggerTest julLogger
//信息: julLogger Hello World!}/*** log4j1*/@Testpublic void log4JLogger(){org.apache.log4j.Logger log4JLogger = org.apache.log4j.Logger.getLogger("log4JLogger");log4JLogger.info("log4J_1_Logger Hello World!");
//运行结果
//[log4j_1] 2024-07-30 10:55:29,017 INFO [log4J_1_Logger] - log4J_1_Logger Hello World!}/*** log4j2*/@Testpublic void log4J_2_Logger(){ExtendedLogger logger= LogManager.getContext().getLogger("log4J_2_Logger");logger.info("log4J_2_Logger Hello World!");
//运行结果
//[log4j_2] line=41 10:55:50.050 [main]INFO - log4J_2_Logger Hello World!}/*** logback*/@Testpublic void logBackLogger(){// Here we create contextLoggerContext loggerContext = new LoggerContext();//创建一个LoggerContext的初始化器,该初始化器可以通过configureByResource()方法,//使用指定的配置(xml,或者 properties)对LoggerContext实例进行初始化// Initializer is used to enrich context with detailsContextInitializer contextInitializer = new ContextInitializer(loggerContext);try {//获取我们的配置文件// Get a configuration file from classpathURL configurationUrl = Thread.currentThread().getContextClassLoader().getResource("logback.xml");if (configurationUrl == null) {throw new IllegalStateException("Unable to find custom logback configuration file");}// 解析配置文件,将解析到的配置设置给 LoggerContext// Ask context initializer to load configuration into contextcontextInitializer.configureByResource(configurationUrl);// Here we get logger from contextch.qos.logback.classic.Logger logger = loggerContext.getLogger("logBackLogger");logger.info("logBackLogger Hello World!");
//运行结果
//[logback] 2024-07-30 10:57:03 [main] INFO logBackLogger - logBackLogger Hello World!} catch (JoranException e) {throw new RuntimeException("Unable to configure logger", e);}}@Testpublic void logBackLogger1(){// Here we create contextLoggerContext loggerContext = new LoggerContext();// Initializer is used to enrich context with detailsContextInitializer contextInitializer = new ContextInitializer(loggerContext);try {//autoConfig 方法中 会先调用 findURLOfDefaultConfigurationFile()//获取一个默认的配置文件,// 然后调用configureByResource 对 loggerContext进行初始化// findURLOfDefaultConfigurationFile 逻辑是先获取环境变量 //logback.configurationFile// 配置的文件,找不到再找 logback-test.xml ,logback.groovy , logback.xmlcontextInitializer.autoConfig();// Here we get logger from contextch.qos.logback.classic.Logger logger = loggerContext.getLogger("logBackLogger");logger.info("logBackLogger Hello World!");//运行结果
//[logback] 2024-07-30 10:57:51 [main] INFO logBackLogger - logBackLogger Hello World!} catch (JoranException e) {throw new RuntimeException("Unable to configure logger", e);}}}
log4j的配置文件 log4j.properties
log4j.rootLogger=info, stdoutlog4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[log4j_1] %d %p [%c] - %m%n
log4j2的配置文件 log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration><appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="[log4j_2] line=%L %d{HH:mm:ss.sss} [%t]%highlight{%-5level} - %msg%n"/></Console><!-- <Console name="Console" target="SYSTEM_0UT"> --><!-- <PatternLayout pattern="file=%c line=%L %dHH:mm:ss.sss}[%t]%highlight{%-5level} %logger{36}-%msg%n"/> --><!-- </Console> --></appenders><loggers><root level="debug"><appender-ref ref="Console"/></root></loggers></configuration>
java.util.logging.Logger 配置文件 logging.properties
.level=WARNINGhandlers=java.util.logging.ConsoleHandlerjava.util.logging.ConsoleHandler.level=WARNING
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
logback的配置文件 logback.xml
<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>[logback] %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><root level="debug"><appender-ref ref="STDOUT" /></root></configuration>
二、采用 commons-logging 动态选用日志
<!-- === commons-logging 相关jar包 == -->
<dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version>
</dependency>
先只导入commons-logging.jar不导入其他的日志包
package com.fll;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;public class CommonLoggingTest {@Testpublic void commonLogging(){Log logger = LogFactory.getLog("commonLogging");logger.info("commonLogging Hello World!");}}
可以看到运行结果:日志打印采用的是
class org.apache.commons.logging.impl.Jdk14Logger
内部封装的是 java.util.logging.Logger
除了commons-logging之外再导入 log4j1的 jar 包
<!-- === commons-logging 相关jar包 == -->
<dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version>
</dependency><!-- 单独导入 log4j1 -->
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
可以看到运行结果:日志打印采用的是
class org.apache.commons.logging.impl.Log4JLogger
public static Log getLog(String name) throws LogConfigurationException {return getFactory().getInstance(name);
}
可以看到 LogFactory 只有一个实现类
org.apache.commons.logging.impl.LogFactoryImpl
org.apache.commons.logging.impl.LogFactoryImpl#getInstance(java.lang.String)
public Log getInstance(String name) throws LogConfigurationException {Log instance = (Log) instances.get(name);if (instance == null) {instance = newInstance(name);instances.put(name, instance);}return instance;
}protected Log newInstance(String name) throws LogConfigurationException {Log instance;try {if (logConstructor == null) {// 关键的方法,根据环境和配置获取要实例化的日志对象instance = discoverLogImplementation(name);}else {Object params[] = { name };instance = (Log) logConstructor.newInstance(params);}if (logMethod != null) {Object params[] = { this };logMethod.invoke(instance, params);}return instance;//省略不重要代码
}/*** The names of classes that will be tried (in order) as logging* adapters. Each class is expected to implement the Log interface,* and to throw NoClassDefFound or ExceptionInInitializerError when* loaded if the underlying logging library is not available. Any* other error indicates that the underlying logging library is available* but broken/unusable for some reason.*/
private static final String[] classesToDiscover = {LOGGING_IMPL_LOG4J_LOGGER,"org.apache.commons.logging.impl.Jdk14Logger","org.apache.commons.logging.impl.Jdk13LumberjackLogger","org.apache.commons.logging.impl.SimpleLog"
};/**
* 根据环境和配置获取要实例化的日志对象
*
*/
private Log discoverLogImplementation(String logCategory)throws LogConfigurationException {if (isDiagnosticsEnabled()) {logDiagnostic("Discovering a Log implementation...");}initConfiguration();Log result = null;//先看用户有没有指定的 Log 的实现
//LOG_PROPERTY = "org.apache.commons.logging.Log";
//LOG_PROPERTY_OLD = "org.apache.commons.logging.log";
//从attributes中获取
//先从 String specifiedClass = (String) getAttribute(LOG_PROPERTY);
//再从 specifiedClass = (String) getAttribute(LOG_PROPERTY_OLD);//从环境变量中获取
//先找 specifiedClass = getSystemProperty(LOG_PROPERTY, null);
//再找 specifiedClass = getSystemProperty(LOG_PROPERTY_OLD, null);// See if the user specified the Log implementation to useString specifiedLogClassName = findUserSpecifiedLogClassName();//如果找到用户配置的的 日志实现if (specifiedLogClassName != null) {if (isDiagnosticsEnabled()) {logDiagnostic("Attempting to load user-specified log class '" + specifiedLogClassName + "'...");}//使用用户 配置的日志实现result = createLogFromClass(specifiedLogClassName,logCategory,true);//如果按照用户配置的创建日志对象失败if (result == null) {StringBuffer messageBuffer = new StringBuffer("User-specified log class '");messageBuffer.append(specifiedLogClassName);messageBuffer.append("' cannot be found or is not useable.");// Mistyping or misspelling names is a common fault.// Construct a good error message, if we caninformUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LOG4J_LOGGER);informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_JDK14_LOGGER);informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LUMBERJACK_LOGGER);informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_SIMPLE_LOGGER);throw new LogConfigurationException(messageBuffer.toString());}//如果按照用户配置的创建日志对象成功,直接返回创建的对象return result;}if (isDiagnosticsEnabled()) {logDiagnostic("No user-specified Log implementation; performing discovery" +" using the standard supported logging implementations...");}// 如果用户没有配置任何日志实现// 依次遍历 classesToDiscover 并尝试在classpath中加载每一个日志实现// 如果哪个加载成功就返回哪一个,后面的不在尝试// 所以按照顺序是// 先加载 = "org.apache.commons.logging.impl.Log4JLogger";// 再加载 org.apache.commons.logging.impl.Jdk14Loggerfor(int i=0; i<classesToDiscover.length && result == null; ++i) {result = createLogFromClass(classesToDiscover[i], logCategory, true);}//如果从classpath没有加载到任何日志实现 就报错if (result == null) {throw new LogConfigurationException("No suitable Log implementation");}return result;
}
private static final String[] classesToDiscover = {"org.apache.commons.logging.impl.Log4JLogger","org.apache.commons.logging.impl.Jdk14Logger","org.apache.commons.logging.impl.Jdk13LumberjackLogger","org.apache.commons.logging.impl.SimpleLog"
};这里是写死的,
优先加载 org.apache.commons.logging.impl.Log4JLogger
然后加载 org.apache.commons.logging.impl.Jdk14Logger
org.apache.commons.logging.impl.Log4JLogger是对org.apache.log4j.Logger简单装饰
org.apache.commons.logging.impl.Jdk14Logger是对java.util.logging.Logger简单装饰可以看到 commons-logging 中默认实现的日志我们常用的只有 org.apache.log4j.Logger
和 java.util.logging.Logger 如果想用其他的一些流行的日志还得自己去实现该日志的装饰
类,并且还得通过 attributes 或者 环境变量进行 配置才能使用,要不就得下载源码,自己在
数组中加入要使用的日志实现。这样就比较麻烦。所以使用commons-logging的人越来越少了,
还有一个原因是 自从 1.2 版本之后,commons-logging 就不再更新了
三、slf4j 通过动态绑定灵活调整要使用的日志
相关文章:

系统复习Java日志体系
一,我们采用硬编码体验一下几个使用比较多的日志 分别导入几种日志的 jar 包 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSch…...

网络管理linux命令
在Linux系统中,有许多常用的网络命令用于检查网络配置、诊断网络问题以及管理网络连接。以下是一些常用的网络命令及其简要说明: ifconfig 显示或配置网络接口。 ifconfigip 用于显示和操作路由、设备、策略路由和隧道。 ip addr show ip link show ip …...

PowerDNS架构解析与安装部署指南
1、背景介绍 目前公司使用PowerDNS进行DNS管理,但由于采用的是单节点架构,存在不可用的风险。为提升系统的稳定性和可靠性,我们计划对现有架构进行重构。通过引入高可用性设计,我们将优化系统架构,使其能够在故障情况…...

Ubuntu 20.04.6 安装 Elasticsearch
1.准备 -- 系统更新 sudo apt update sudo apt upgrade -- 安装vim 文本编辑器 sudo apt install vim-- jdk 版本确认 java -versionjdk 安装可以参照:https://blog.csdn.net/CsethCRM/article/details/140768670 2.官方下载Elasticsearch 官方地址:h…...

Python for循环迭代原理(迭代器 Iterator)
在使用Python时,我们经常会使用for循环来访问容器对象(列表、字符、字典等)中的元素。其幕后实际是通过迭代协议来完成的,迭代是一种依次访问对象中元素的方式,for循环在对象上调用iter()函数生成一个迭代器࿰…...

通信原理-思科实验四:静态路由项配置实验
实验四 静态路由项配置实验 一:实验内容 二:实验目的 三、实验原理 四、实验步骤 选择三个2811型号的路由器 R1、R2、R3 路由器默认只有两个快速以太网接口,为路由器R1和R3增加快速以太网接口模块NM-1FE-TX,安装后检查路由器的接…...

ngzero使用外部的svg图标
1.将图标svg下下来,放到项目中,路径如下所示 之后 <span nz-icon [nzIconfont]“‘icon-zhibiao’”>使用 2.直接使用阿里的图标 先将你要用的图标放入购物车,再将购物车的图标添加到你主页的我的项目中 之后代码中在startupService…...

逆矩阵、秩
在数学的广阔天地中,线性代数扮演着至关重要的角色。它不仅是现代科学和工程学的基石,也是理解复杂数据结构的关键。本文将深入探讨线性代数中的几个核心概念:逆矩阵、秩、列空间和零空间,通过详细的解释和丰富的实例,…...

pc端小程序抓包修改数据相关记录
看了很多关于小程序抓包的 废话不多说直接演示 一、小程序抓包 1.所需要的工具 官网下载即可: https://www.charlesproxy.com/latest-release/download.do 我这里用的 Charles-proxy-4.6.6-win64 需要中文破解参考 https://www.jianshu.com/p/4d67dbbf2f6a 2、破…...

用Python打造精彩动画与视频.2.1 Python基础语法概述
2.1 Python基础语法概述 Python作为一门功能强大且易于学习的编程语言,其基础语法简单直观,非常适合初学者入门。这一节将带你了解Python的基本语法规则,为后续制作动画和视频打下坚实的基础。 1. 变量与数据类型 Python的变量不需要提前声…...

Golang高效合并(拼接)多个gzip压缩文件
有时我们可能会遇到需要把多个 gzip 文件合并成单个 gzip 文件的场景,最简单最容易的方式是把每个gzip文件都先解压,然后合并成一个文件后再次进行压缩,最终得到我们想要的结果,但这种先解压后压缩的方式显然效率不高,…...

MySQL数据库-基本概念
数据 描述事物的符号记录包括属组、文字、图形、图像、声音、档案记录等以“记录”形式按统一的格式进行存储 表 将不同的记录组织在一起用来存储具体数据 数据库 表的集合,是以一定的组织方式存储的相互有关的数据集合 数据库管理系统(DBMS&#…...

【无标题】web+http协议+nginx搭建+nginx反向代理(环境准备)
一.Web 为用户提供互联网上浏览信息的服务,web服务是动态的,可交互的。 1.安装httpd yum -y install httpd 2.启动 systemctl start httpd 3.关闭防火墙 systemctl stop firewalld [rootrs html]# echo "我手机号是" > …...

c-periphery RS485串口库文档serial.md(serial.h)(非阻塞读)(VMIN、VTIME)
c-peripheryhttps://github.com/vsergeev/c-periphery 文章目录 NAMESYNOPSISENUMERATIONS关于奇偶校验枚举类型 DESCRIPTIONserial_new()serial_open()关于流控制软件流控制(XON/XOFF)硬件流控制(RTS/CTS)选择流控制方法 serial_…...

Matlab arrayfun 与 bsxfun——提高编程效率的利器!
许多人知道 MATLAB 向量化编程,少用 for 循环 可以提高代码运行效率,但关于代码紧凑化编程, arrayfun 与 bsxfun 两个重要函数却鲜有人能够用好,今天针对这两个函数举例说明其威力。 Matlab arrayfun 概述 arrayfun 是 Matlab …...

【Unity编辑器拓展】GraphView自定义可视化节点
1、创建节点区域脚本 其中的new class UxmlFactory,可以让该元素显示在UI Builder中,我们就可以在Library-Project中看到我们新建的这两个UI元素,就可以拖入我们的UI窗口编辑了 public class NodeTreeViewer : GraphView {public new class…...

教程系列4 | 趋动云『社区项目』极速体验 LivePortrait 人脸表情“移花接木”大法
LivePortrait LivePortrait 由快手可灵大模型团队开源,只需 1 张原图就能生成动态视频。 LivePortrait 的核心优势在于其卓越的表情"迁移"技术,能够令静态图像中的人物瞬间焕发活力,无论是眨眼、微笑还是转头,皆栩栩如…...

WGS84、GCJ-02、BD09三大坐标系详解
文章目录 前言WGS84坐标系定义应用WGS84 Web 墨卡托投影 GCJ-02坐标系(火星坐标系)定义应用GCJ-02经纬度投影与Web墨卡托投影 BD09坐标系(百度坐标系)定义应用BD09经纬度投影与Web墨卡托投影 坐标系之间的区别与注意事项总结 前言…...

css上下动画 和淡化
.popup_hidden_bg { transition: opacity .5s ease-out; opacity: 0; pointer-events: none; /* 防止在隐藏时仍然能点击 */ } keyframes popupShop { from { transform: translateY(100%); opacity: 0; } to {transform: translateY(0);opacity: 1; }} keyframes popupHidd…...

深入解析C#中的URI和URL编码:理解EscapeDataString、EscapeUriString和UrlEncode的区别及字符编码错误处理
在C#中,处理URI(统一资源标识符)和URL(统一资源定位符)时,可以使用Uri.EscapeDataString、Uri.EscapeUriString和HttpUtility.UrlEncode(或WebUtility.UrlEncode)方法来编码字符串。…...

【CSS】给图片设置 max-width
.logo img{width:100%; /* 缩成父盒子的100% */max-width:100%; /* (谁小用谁的百分之百) *//* max-width:100%;【1】图片比盒子大,缩成父盒子的100%【2】图片比盒子小,图片自身的100%*/ }示例 设置样式 .el-image {width: 100%;max-width: 100%;max-…...

区块链——代码格式检查(prettier、solhint)
一、引入依赖 // 导入prettier prettier-plugin-solidity yarn add --dev prettier prettier-plugin-solidity yarn add --dev solhint二、创建.prettierrc文件 {"tabWidth": 2,"semi": false,"useTabs": false,"singleQuote": fals…...

搭建自动化 Web 页面性能检测系统 —— 部署篇
作为一个前端想去做全栈的项目时,可能第一个思路是 node vue/react。一开始可能会新建多个工程目录去实现,假设分别为 web 和 server,也许还有管理后台的代码 admin,那么就有了三个工程的代码。此时为了方便管理就需要在远程仓库…...

知识图谱增强的RAG(KG-RAG)详细解析
转自:知识图谱科技 这是一个与任务无关的框架,它将知识图谱(KG)的显性知识与大型语言模型(LLM)的隐含知识结合起来。这是该工作的arXiv预印本 https://arxiv.org/abs/2311.17330 。 我们在这里利用一个名为…...

python中list的深拷贝和浅拷贝
其实这还是涉及到python中的可变对象和不可变对象的概念。 https://www.cnblogs.com/poloyy/p/15073168.html # -*- coding: utf-8 -*-person [name, [savings, 100.00]] hubby person[:] # slice copy wifey list(person) # fac func copy a [id(x) for x in person] b …...

【LeetCode】字母异位词分组
题目描述: 给你一个字符串数组,请你将字母异位词组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [[“bat”…...

Golang | Leetcode Golang题解之第295题数据流的中位数
题目: 题解: type MedianFinder struct {nums *redblacktree.Treetotal intleft, right iterator }func Constructor() MedianFinder {return MedianFinder{nums: redblacktree.NewWithIntComparator()} }func (mf *MedianFinder) AddNum(…...

【C语言】C语言期末突击/考研--数据的输入输出
目录 一、printf()输出函数介绍 二、scanf读取标准输入 (一)scanf函数的原理 (二)多种数据类型混合输入 三、练习题 今天我们学习printf和scanf读取标准输入。下面我们开始正式的学习吧。 C语言中有很多内置函数,今…...

How can I fix my Flask server‘s 405 error that includes OpenAi api?
题意:解决包含OpenAI API的Flask服务器中出现的405错误(Method Not Allowed,即方法不允许) 问题背景: Im trying to add an API to my webpage and have never used any Flask server before, I have never used Java…...

LeetCode Hot100 将有序数组转换为二叉搜索树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。 示例 1: 输入:nums [-10,-3,0,5,9] 输出:[0,-3,9,-10,null,5] 解释:[0,-10,5,null,-3,null,9] 也将被视为正确…...