日志
日志框架可以分为 日志门面(facade) 和 日志实现(implementation),spring boot 使用了 slf4j 作为日志门面,logback 或 log4j2 作为日志实现。
日志门面以及日志实现
日志门面
日志门面(facade)
日志门面 是一个设计模式中的“门面模式(facade pattern)”,它提供了统一的接口,简化了日志记录的使用,屏蔽了不同日志框架之间的细节。
门面本身并不实现日志的具体记录功能,它只是提供了日志记录的 api 规范,开发者通过这些规范来记录日志。
典型的日志门面框架是 slf4j(simple logging facade for java),它定义了一组通用的日志接口,开发者通过这些接口来进行日志记录。
日志实现
日志实现 是实际执行日志记录的组件,它负责处理日志的输出、格式化、存储等具体功能。
日志实现提供了对日志的具体管理方式,包括日志级别、输出位置、格式、日志文件的滚动与清理等。
常见的日志实现框架有:
logback:spring boot 默认使用的日志框架,提供了功能丰富的日志管理和配置。
log4j2:apache 提供的日志框架,相较于 logback 提供了更多的性能优化(如异步日志处理)和扩展性。
两者关系
门面(facade) 是日志框架的统一接口,开发者通过它来调用日志功能。
实现(implementation) 是执行日志记录、管理和配置的具体框架,处理如何生成、存储和输出日志。
springboot中日志的配置
spring boot 默认配置 中,slf4j 是日志门面,logback 是默认的日志实现框架。你无需做任何特别的配置,只要在 spring boot 项目中添加了相关依赖,spring boot 会自动配置日志系统。
当你在代码中使用 slf4j 的日志接口时(例如:logger logger = loggerfactory.getlogger(yourclass.class)),日志实际上会被传递给 logback(或者 log4j2)。
如何使用slf4j进行日志记录
通过 slf4j 提供的日志接口进行日志记录
import org.slf4j.logger;
import org.slf4j.loggerfactory;
public class myservice {
private static final logger logger = loggerfactory.getlogger(myservice.class);
public void dosomething() {
logger.info("starting the task...");
try {
// 执行任务
} catch (exception e) {
logger.error("an error occurred", e);
}
}
}loggerfactory.getlogger(myservice.class) 获取了一个 logger 实例,这个实例是通过 slf4j 提供的 api 来使用的。你通过这个 logger 来记录日志(如 info, error 等)。
但是,日志实际的记录过程是由 logback 或 log4j2 执行的,这些框架提供了具体的日志输出方式、格式化和管理机制。
优化 使用lombok 依赖
再pom.xml文件添加lombok依赖
<dependency>
<groupid>org.project.lombok<groupid>
<artifactid>lombok<artifactid>
<dependency>再类上添加@slf4j注解,然后直接使用log.info(“日志”);
@service
@slf4j
public class testserviceimpl implements testservice{
@resource(name = "poolexecutor")
private threadpooltaskexecutor executor;
@override
public string test() {
threadpooltaskexecutor taskexecutor = executor;
// 获取线程池信息
int activecount = taskexecutor.getactivecount();
int corepoolsize = taskexecutor.getcorepoolsize();
int poolsize = taskexecutor.getpoolsize();
taskexecutor.execute(()->{
system.out.printf(activecount+"--"+corepoolsize);
});
log.info("日志");
return null;
}
}如何控制日志输出
控制日志输出就需要日志实现了logback或者log4j2
这里使用logback举例
spring boot 支持两种日志配置方式:通过 application.yml/application.properties 文件配置 和 通过 logback-spring.xml 配置文件进行详细配置。这两种方式各有不同的适用场景
application.yml
示例
logging:
level:
root: info # 根日志级别
com.example: debug # 某个包的日志级别
file:
name: e:\ide\demlnewlog\myapp.log # 日志文件路径
path: e:\ide\demlnewlog
pattern:
console: "%d{yyyy-mm-dd hh:mm:ss} - %msg%n" # 控制台输出格式

logback-spring.xml
当你需要更细致地控制日志行为(如日志的滚动策略、异步日志、日志文件分割、过滤器等高级功能)时,你可以使用 logback-spring.xml 配置文件。这种方式提供了非常灵活和强大的日志配置能力。
创建 logback-spring.xml 配置文件: 将 logback-spring.xml 文件放在 src/main/resources 目录下,这样 spring boot 会自动读取该文件。名字必须是 logback-spring.xml(springboot专有的)才能覆盖logback配置
spring boot 自动读取 logback-spring.xml 配置:
如果存在 logback-spring.xml 配置文件,spring boot 会自动加载它,覆盖默认的 logback 配置。
logback-spring.xml 文件与普通的 logback.xml 文件的不同之处在于,logback-spring.xml 文件支持 spring 的配置和属性注入,例如可以使用 spring 的 propertysource 来动态设置日志级别、输出路径等。
再resource目录下创建logback-spring.xml文件
<?xml version="1.0" encoding="utf-8"?>
<configuration debug="true">
<!-- appender是configuration的子节点,是负责写日志的组件。 -->
<!-- consoleappender:把日志输出到控制台 -->
<appender name="stdout" class="ch.qos.logback.core.consoleappender">
<!-- 默认情况下,每个日志事件都会立即刷新到基础输出流。 这种默认方法更安全,因为如果应用程序在没有正确关闭appender的情况下退出,则日志事件不会丢失。但是,为了显着增加日志记录吞吐量,可以将immediateflush属性设置为false -->
<!--<immediateflush>true</immediateflush>-->
<encoder>
<!-- %37():如果字符没有37个字符长度,则左侧用空格补齐 -->
<!-- %-37():如果字符没有37个字符长度,则右侧用空格补齐 -->
<!-- %15.15():如果记录的线程字符长度小于15(第一个)则用空格在左侧补齐,如果字符长度大于15(第二个),则从开头开始截断多余的字符 -->
<!-- %-40.40():如果记录的logger字符长度小于40(第一个)则用空格在右侧补齐,如果字符长度大于40(第二个),则从开头开始截断多余的字符 -->
<!-- %msg:日志打印详情 -->
<!-- %n:换行符 -->
<!-- %highlight():转换说明符以粗体红色显示其级别为error的事件,红色为warn,blue为info,以及其他级别的默认颜色。 -->
<pattern>%d{yyyy-mm-dd hh:mm:ss.sss} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n</pattern>
<!-- 控制台也要使用utf-8,不要使用gbk,否则会中文乱码 -->
<charset>utf-8</charset>
</encoder>
</appender>
<!-- info 日志文件-->
<!-- rollingfileappender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<!-- 以下的大概意思是:
1.先按日期存日志,日期变了,将前一天的日志文件名重命名为xxx%日期%索引,新的日志仍然是project_info.log
2.如果日期没有发生变化,但是当前日志的文件大小超过10mb时,对当前日志进行分割 重命名-->
<appender name="info_log" class="ch.qos.logback.core.rolling.rollingfileappender">
<!--日志文件路径和名称-->
<file>e:\ide\demlnewlog\info.log</file>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<!-- 打印除了error的日志 -->
<filter class="ch.qos.logback.classic.filter.levelfilter">
<level>error</level>
<onmatch>deny</onmatch> <!-- 如果命中error就禁止这条日志 -->
<onmismatch>accept</onmismatch> <!-- 如果没有命中就使用这条规则 -->
</filter>
<rollingpolicy class="ch.qos.logback.core.rolling.sizeandtimebasedrollingpolicy">
<!-- 日志文件的名字会根据filenamepattern的值,每隔一段时间改变一次 -->
<!-- 文件名示例:logs/project_info.2017-12-05.0.log -->
<!-- 注意:sizeandtimebasedrollingpolicy中 %i和%d令牌都是强制性的,必须存在,否则报错 -->
<filenamepattern>logs/project_info.%d.%i.log</filenamepattern>
<!-- 每产生一个日志文件,该日志文件的保存期限为30天 -->
<!-- 注:maxhistory的单位是根据filenamepattern中的翻转策略自动推算出来的,例如上面选用了yyyy-mm-dd,则单位为天,如果上面选用了yyyy-mm,则单位为月。另外上面的单位默认为yyyy-mm-dd-->
<maxhistory>30</maxhistory>
<!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到20gb,哪怕没到30天也要删除多余的日志 -->
<totalsizecap>20gb</totalsizecap>
<!-- maxfilesize:这是活动文件的大小,默认值是10mb,测试时可改成5kb看效果 -->
<maxfilesize>10mb</maxfilesize>
</rollingpolicy>
<!--编码器-->
<encoder>
<!-- pattern节点,用来设置日志的输入格式 ps:日志文件中不要设置颜色,否则颜色部分会有esc[0:39em等乱码-->
<pattern>%d{yyyy-mm-dd hh:mm:ss.sss} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>utf-8</charset>
</encoder>
</appender>
<!-- error 日志文件-->
<appender name="error_log" class="ch.qos.logback.core.rolling.rollingfileappender">
<!--日志文件路径和名称-->
<file>e:\ide\demlnewlog\error.log</file>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<!-- thresholdfilter过滤低于指定阈值的事件。 对于等于或高于阈值的事件,thresholdfilter将在调用其decision()方法时响应neutral。 但是,将拒绝级别低于阈值的事件 -->
<filter class="ch.qos.logback.classic.filter.thresholdfilter">
<!-- 低于error级别的日志(debug,info)将被拒绝,等于或者高于error的级别将相应neutral -->
<level>error</level>
</filter>
<rollingpolicy class="ch.qos.logback.core.rolling.sizeandtimebasedrollingpolicy">
<!-- 活动文件的名字会根据filenamepattern的值,每隔一段时间改变一次 -->
<!-- 文件名示例:logs/project_error.2017-12-05.0.log -->
<!-- 注意:sizeandtimebasedrollingpolicy中 %i和%d令牌都是强制性的,必须存在,要不会报错 -->
<filenamepattern>logs/project_error.%d.%i.log</filenamepattern>
<!-- 每产生一个日志文件,该日志文件的保存期限为30天 -->
<maxhistory>30</maxhistory>
<!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到20gb,哪怕没到30天也要删除多余的日志 -->
<totalsizecap>20gb</totalsizecap>
<!-- maxfilesize:这是活动文件的大小,默认值是10mb,测试时可改成5kb看效果 -->
<maxfilesize>10mb</maxfilesize>
</rollingpolicy>
<!--编码器-->
<encoder>
<!-- pattern节点,用来设置日志的输入格式-->
<pattern>%d{yyyy-mm-dd hh:mm:ss.sss} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>utf-8</charset>
</encoder>
</appender>
<!-- configuration中最多允许一个root,别的logger如果没有设置级别则从父级别root继承 -->
<root level="info">
<appender-ref ref="stdout" />
</root>
<!-- name属性指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<logger name="com.example.demonew.controller" level="info">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
</logger>
<!-- 利用logback输入mybatis的sql日志,
注意:如果不加 additivity="false" 则此logger会将输出转发到自身以及祖先的logger中,就会出现日志文件中sql重复打印-->
<logger name="com.example.demonew.service" level="debug" additivity="false">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
</logger>
<!-- additivity=false代表禁止默认累计的行为,即com.atomikos中的日志只会记录到日志文件中,不会输出层次级别更高的任何appender-->
<logger name="com.example" level="info" additivity="false">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
</logger>
</configuration>到此这篇关于springboot 日志实现的文章就介绍到这了,更多相关springboot 日志实现内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论