小白一个。平日在家代码,一般就System.out.print就完了,很少接触日志框架。入公司后,逐渐接触了日志框架。近期闲来无事研究了下如何平时代码中也把日志框架加入,才能了解其强大。毕竟在公司有接触,最开始的疑问就是,日志门面和日志实现是啥?这个不细说,详情请google百度。好处目前我能理解到的就是slf4j本身只是日志功能的抽象,没有具体实现,只提供接口。但他服务于各种日志系统。保证了日后更好切换其他日志实现。养成良好习惯不直接使用日志系统的api而是使用日志门面,当需要换日志实现的时候,只需要改日志系统的pom依赖就好,不需要更改上层调用日志api的代码。譬如从logback日志系统切换到log4j2,代码是不需要变更的。
因为log4j2比较常用,所以看了下pom中如何添加依赖。然后的疑问的是就为什么使用个log4j2实现并以slf4j当作日志门面,maven项目中pom文件里面还要引用几个api(看别人的pom配置里面一大堆依赖,还有两个api包)。于是看了下log4j官网文档解释如下:简单说log4j实现与api分离。如果不用slf4j,我单独使用log4j的话, 单独引用log4j-api就可以使编译通过了。但是真正功能还是由log4j-core实现。所以必须要再引用个core包。
官网原文如下:
Log4j 2 is broken up in an API and an implementation (core), where the API provides the interface that applications should code to. Strictly speaking Log4j core is only needed at runtime and not at compile time.
However, below we list Log4j core as a compile time dependency to improve the startup time for custom plugins as it provides an annotation processor that generates a metadata file to cache plugin information as well as the necessary code to compile against to create custom plugins.
Using Log4j in your Apache Maven build
To build with Apache Maven, add the dependencies listed below to your pom.xml file.
pom.xml
<dependencies>
<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>
</dependencies>
所以从实现角度讲这两个就可以了。但是我们需要用slf4j作为日志门面。所以还需要添加slf4j的pom依赖。如下:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
下面是配置的过程中遇到的问题:
当上述配置完毕后,尝试代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/0f3efaceca1e65d3401d7c4792ec77f4.png)
开心的编译运行后,报错==||:
![](https://i-blog.csdnimg.cn/blog_migrate/ff65109a72b768dad168667eec3b4113.png)
网上搜,官网解释需要红框中的其中一个jar包,此处迷茫,随便选择了NOP:
![](https://i-blog.csdnimg.cn/blog_migrate/fbe6b28a12aec5f0061df1afcfa3b2a8.png)
于是,当pom配置如下后,运行期没有任何报错:
![](https://i-blog.csdnimg.cn/blog_migrate/f6753874e859286966b3cc2d9f7f64be.png)
但是无论何种日志级别,没有输出日志,也没提示没配日志文件等报错。debug调试发现logger竟然是NOPLogger,而不是log4j2的实现。网上搜了下,发现NOP(原意No Operation,不做任何操作...所以啥日志木有,只是让其运行期不抛错):
![](https://i-blog.csdnimg.cn/blog_migrate/52b533e19b8374e6327b81499d2beb64.png)
推测log4j2的实现没有挂上日志门面,于是想直接先使用日志系统log4j2,不要门面了先打出日志再说==||
![](https://i-blog.csdnimg.cn/blog_migrate/0459fce3401ad63a476f7b3b06aa0530.png)
![](https://i-blog.csdnimg.cn/blog_migrate/40d6a6384ff71071bb5f8281c2ca1d26.png)
编译运行,遇到缺少配置文件的正常报错,配置上文件后即可输出到控制台。(关于log4j2的日志配置网上一大堆)
![](https://i-blog.csdnimg.cn/blog_migrate/6ba55f4a6e0453186aa6b68bcbe83ded.png)
那问题来了,如何绑定log4j2的实现到slf4j的门面上呢?
网上搜了下,有了结果。想桥接的话不能引入NOP包而是log4j-slf4j-impl包,删除nop包依赖,pom更改如下:
![](https://i-blog.csdnimg.cn/blog_migrate/5913c8c43e237ae1532167cf0b5846f1.png)
(注意桥接由slf4j提供,版本要保持一致)
然后运行终于看到了让人开心的报错:
![](https://i-blog.csdnimg.cn/blog_migrate/02b982f35d7045713ca63985f29fa05a.png)
其实这个配置文件有配,把log4j.properties放到resources目录下,可以正确输出。
纳闷为什么使用的log4j2的版本依旧要有log4j.properties这种配置文件==||,为什么会有这种想法呢,因为同事切三方件时跟我说,log4j2不支持properties格式。我竟信以为真....然后搜索网上发现,原来log4j2早期放弃properties配置,之后又支持了==|||
这我不得不去log4j2官网看下,现在使用的2.13.3版本到底是个咋子情况…...果然还得自己眼见为实:
![](https://i-blog.csdnimg.cn/blog_migrate/33974f498f2451fdb30ce5123a275b83.png)
![](https://i-blog.csdnimg.cn/blog_migrate/327e2027201b83951030ccb0c7f99a2a.png)
所以就此,普通非spring框架的程序也可以使用slf4j门面+底层log4j2的日志框架实现来让普通程序log.error了。后续会研究下log4j2的文件配置如何配比较实用。
近日,公司刚好安全排查需要防止“日志注入”的问题。如:前台输入一些带转义的字符%0d之类的,可能后台日志输出时便可能受到转义符的影响改变日志的格式等,虽然不影响业务功能,但着实会影响开发人员的判断,又或者帮助攻击者进一步迷惑安全人员的定位。所以需要过滤掉(替换)不必要的字符。顺便研究了一下log4j2的配置。废话不多说了,我所参考的文章感觉十分详细:
https://blog.csdn.net/thekenofDIS/article/details/80439776
,看过后便有自己的理解,然后根据所需的功能再在网上搜对应的配置就好。而防范日志注入所需的内容刚好这篇便可解答:
https://www.jianshu.com/p/37ef7bc6d6eb 。其中%replace{%msg}{\。}{/}这个配置便可让日志信息中的一些特殊字符替换成其他的字符。在log4j2.xml配置好后,想验证过滤特殊字符的配置是否生效的时候,刚好发现了之前的一个问题: 如果在resource下配置文件命名为log4j2.xml,则找不到配置文件,而命名log4j则可以。显然觉得是版本不对的问题,回看了pom log4j的版本肯定是没问题的,怀疑问题出在了slf4j的版本配置上。所以暂时去掉了slf4j,改直接用log4j2, LogManager的形式加载,来先验证log4j2.xml命名是否可被读取。答案是肯定的。之后便可验证pattern的替换语法,也生效。剩下的问题就是slf4j如何配呢? TBD