还在用log.isDebugEnabled()判断debug日志你out了
作为程序员,程序开发写代码一定少不了记录日志(没日志的代码都是耍流氓!)今天记录一下自己新搭建spring-boot项目后对日志的思考。
起因:项目是一个无页面,通过直接访问数据库,然后调用第三方api实现数据上传的简单应用。因为项目很小,所以在项目完成后,为了使jar包的大小更小(强迫症,想把无用的maven引用全部去掉),所以打包完成后对lib下的jar包进行查看,发现关于log的jar包很多,由此引发联想,难道一个简单的日志都要用这么多的jar包吗?
查看自己的代码,发现只用到了如下代码
先说结论
-
commons-logging和slf4j是java中的日志门面,即它们提供了一套通用的接口,具体的实现可以由开发者自由选择。log4j和logback则是具体的日志实现方案。这是典型的门面模式
-
比较常用的搭配是commons-logging log4j,slf4j logback
spring默认使用commons-logging log4j
spring-boot默认使用slf4j logback
-
SLF4J是编译时绑定到具体的日志框架,性能优于采用运行时搜寻的方式的commons-logging
-
不需要使用logger.isDebugEnabled()来解决日志因为字符拼接产生的性能问题
-
-
logger.info("my name is {}", "medusar");
-
logger.info("my name is " "medusar");
在效率上,第一行比第二行更高,因为如果当前日志级别是ERROR,第一行不会进行字符串拼接,而第二行,无论日志级别是什么,都会先进行字符串拼接。
-
-
所以为了解决这个问题,commons-logging等框架提供了下面的方式:
-
if (log.isDebugEnabled()){
-
log.debug("dddd" "eee");
-
}
-
-
所以说,现在使用spring-boot开发,已经不需要再使用log.isDebugEnabled()来判断debug了
下面我们顺藤摸瓜开始今天的寻根之旅!
先看下slf4j的实现
配合第一张图,可知:
-
可单独只使用slf4j
-
logback就是默认slf4j的实现(logback-classic.jar,logback-core.jar)
-
log4j的slf4j实现要通过log4j-to-slf4j.jar
-
将java.util.logging的日志桥接到slf4j实现要通过jul-to-slf4j-1.7.36.jar
这些包的目的是什么?
答案是:统一日志记录。a(slf4j logback): Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx等等,每个框架都是自己使用的日志框架,如何统一他们的?
- 将系统中其他日志框架先排除出去;
- 用中间包来替换原有的日志框架;
- 我们导入slf4j其他的实现
说白了就是,其他的框架还以为他们用的还是自己的日志框架,而实际上,他们的日志框架已经不存在了,存在的是slf4j替换过后的对原有框架的实现的中间包
形象的比喻是:春秋战国时期,各个诸侯纷纷自立为王,他们的臣子都拥戴自己的大王,忽然有一天,秦国的影密卫,将其中几个大王偷偷换成了自己的亲信,让他们代替这几个诸侯国的大王,然后将真正的大王们都杀了,做的神不知鬼不觉,他们的大臣们依然死心塌地的拥戴着自己的大王,并不知道大王已经是替身;实际上他们的大王已经都听命于秦国。表面是各国纷乱,而实际上他们已经实现了统一,都归秦国管理!!!
每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;
使用logback 配置文件是:
logback.xml:直接就被日志框架识别了。
logback-spring.xml:日志框架就不直接加载日志的配置项,由 SpringBoot 解析日志配置,可以使用 SpringBoot 的高级 Profile 功能。
logback-spring.xml完整配置文件:
-
<!--
-
logback的语法可以描述为:<configuration>元素包含零个或多个<appender>元素,后跟零个或多个<logger>元素,后跟至多一个<root>元素。
-
configuration :根标签
-
属性:
-
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true,在logback-spring.xml使用时可能会报错,所以不能一起使用
-
scanPeriod:默认情况下,将每分钟扫描一次配置文件的更改。可以以毫秒、秒、分钟或小时为单位指定值。未指定时间单位为毫秒
-
-->
-
<configuration>
-
<!-- 用来引入外部资源文件,resource:表示资源路径 -->
-
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
-
<!-- 每个logger都关联到logger上下文,默认上下文名称为default,可以设置成其他名字,用于区分不同应用程序的记录,
-
一旦设置,不能修改,可以通过%contextName来打印日志上下文名称 -->
-
<contextName>logback</contextName>
-
-
<!-- 日志级别:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF -->
-
<!-- 自定义变量,使用${}来使用变量
-
name:变量名
-
value:变量值
-
scope:变量的作用范围-->
-
<property name="log_path" value="log" scope="context" />
-
<property name="log_pattern" value="%clr(%d{yy-MM-dd hh-mm-ss.SSS}){yellow} [%clr(%t){magenta}] [%clr(%p)] %clr(%C{1}.%M:%L) |:%clr(%m%n){blue}"/>
-
<property name="log_fileNamePattern" value="-%d{yyyy-MM-dd}.%i.log"/>
-
<property name="log_maxFileSize" value="10MB"/>
-
<property name="log_maxHistory" value="15"/>
-
<property name="dev_log_level" value="DEBUG" />
-
<property name="test_log_level" value="DEBUG" />
-
<property name="prod_log_level" value="INFO" />
-
-
<!-- 输出到控制台 -->
-
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
-
<encoder charset="UTF-8">
-
<pattern>${log_pattern}</pattern>
-
</encoder>
-
</appender>
-
-
<!--
-
appender标签:定义日志输出策略,包括日志文件名称,输出格式,日志滚动策略,日志文件大小等等,具体看下面说明
-
属性:
-
name:策略名称
-
class:策略类型
-
控制台输出:ch.qos.logback.core.ConsoleAppender
-
文件滚动输出:ch.qos.logback.core.rolling.RollingFileAppender
-
标签:
-
<file>:日志输出的路径及文件名
-
<encoder>:设置日志输出的格式和编码
-
<rollingPolicy>:设置日志切割策略
-
<fileNamePattern>:定义了日志的切割方式,切割后存放的文件名。
-
<maxFileSize>:触发策略,指定单个日志文件的上限大小,超限就会进行切割。
-
<maxHistory>:日志文件保留天数
-
<filter>:过滤规则
-
具体可看:http://logback.qos.ch/manual/configuration.html
-
http://logback.qos.ch/manual/appenders.html
-
-->
-
<!-- 时间滚动输出 系统日志 -->
-
<appender name="SYSTEM" class="ch.qos.logback.core.rolling.RollingFileAppender">
-
<file>${log_path}/app.log</file>
-
<encoder>
-
<pattern>${log_pattern}</pattern>
-
<charset>UTF-8</charset>
-
</encoder>
-
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
<fileNamePattern>${logpath}/info/app${log_fileNamePattern}</fileNamePattern>
-
<maxFileSize>${log_maxFileSize}</maxFileSize>
-
<maxHistory>${log_maxHistory}</maxHistory>
-
</rollingPolicy>
-
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-
<level>DEBUG</level>
-
</filter>
-
</appender>
-
-
<!-- sql输出到sql.log文件 -->
-
<appender name="SQL" class="ch.qos.logback.core.rolling.RollingFileAppender">
-
<file>${log_path}/sql.log</file>
-
<encoder charset="UTF-8">
-
<pattern>${log_pattern}</pattern>
-
</encoder>
-
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
<fileNamePattern>${log_path}/sql-${log_fileNamePattern}</fileNamePattern>
-
<maxFileSize>${log_maxFileSize}</maxFileSize>
-
<maxHistory>${log_maxHistory}</maxHistory>
-
</rollingPolicy>
-
</appender>
-
-
<!-- logger:记录器用来指定某一个包或者具体的类的日志打印级别。
-
name:指定某个包或者具体的类
-
level:指定日志输出级别。
-
additivity:如果没有指定level值,是否从最近的父标签继承level值,值为true或false-->
-
<logger name="org.springframework" level="WARN" />
-
<logger name="org.apache" additivity="false" level="WARN" />
-
<logger name="org.mybatis" additivity="false" level="DEBUG" />
-
-
<!-- 测试环境 -->
-
<springProfile name="test">
-
<root level="${test_log_level}">
-
<appender-ref ref="CONSOLE" />
-
</root>
-
</springProfile>
-
-
<!-- 开发环境 -->
-
<springProfile name="dev">
-
<root level="${dev_log_level}">
-
<appender-ref ref="CONSOLE" />
-
</root>
-
</springProfile>
-
-
<!-- 生产环境 -->
-
<springProfile name="prod">
-
<logger name="com.boot.sql" level="DEBUG" additivity="false">
-
<appender-ref ref="SQL" />
-
</logger>
-
<root level="${prod_log_level}">
-
<appender-ref ref="SYSTEM" />
-
</root>
-
</springProfile>
-
-
</configuration>
-
使用log42 配置文件是(pom排除其他,引入中间包):
log4j2.xml
log4j2-spring.xml
使用jul 配置文件是(pom排除其他,引入中间包,存在已知的类加载问题,这些问题会导致从“可执行 jar”运行时出现问题。建议在从“可执行 jar”运行时尽可能避免使用。):
logging.properties
补充,以前我们使用spring的时候,Logging是spring中唯一强制的外部依赖,spring中默认使用的日志是commons-logging
,简称JCL
,这里说的强制性,是因为在spring-core
这个模块中引入了该依赖。不过,引入了该依赖,也无需做任何其他的配置,它是日志门面
,它内部会有自己的算法去找日志门面的实现类,比如log4j
,如果说没有引入其他日志依赖,它默认就会去找JDK自带的java.util.logging
简称jul
作为其日志实现类
log4j1.x版本已经停止更新了,log4j2.x习惯性叫做`log4j2`。(大家还记得前段时间关于log4j漏洞的事情吧)
更换spring的common-logging日志系统 依赖配置,排除commons-logging
-
<dependency>
-
<groupId>org.springframework</groupId>
-
<artifactId>spring-orm</artifactId>
-
<exclusions>
-
<exclusion>
-
<groupId>commons-logging</groupId>
-
<artifactId>commons-logging</artifactId>
-
</exclusion>
-
</exclusions>
-
</dependency>
这个时候如果运行程序会抛异常,因为我们把 Spring 依赖的 commons-logging 排除了, 而这个依赖是必须有的,不是可选的。
加入转换包
这个转换包就相当于我们上面说的那个转换器,spring会调用jcl-over-slf4j,spring以为调用的还是commons-logging,但是实际上commons-logging已经被我们删除掉了,并且jcl-over-slf4j还可以将输出转换为slf4j类型的输出,又因为我们前面引入了logback的依赖,lagback是slf4j的实现,所以最终输出的就是logback的日志系统
-
<!-- 其他日志框架的中间转换包 -->
-
<dependency>
-
<groupId>org.slf4j</groupId>
-
<artifactId>jcl-over-slf4j</artifactId>
-
</dependency>
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfkfkbg
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24