作者:追梦1819

原文:https://www.cnblogs.com/yanfei1819/p/10973583.html

版权声明:本文为博主原创文章,转载请附上博文链接!

## 引言

  日志是软件系统的“基础设施”,它可以帮助我们了解系统的运行轨迹,查找系统的运行异常等。很多人都没有引起对日志的重视。

下面我们先来设定几个实际项目项目的场景:

1、xxx物流云系统,公司在给货车司机打款的时候,司机没收到账款。司机在线等,没收到账款,就不继续跑了;

2、xxx商城小程序,给用户进行退款的时候,用户没有收到钱,然后要举报公司。。。;

3、线上系统挂了,待找原因,待上线等。

  这些都属于很严重的生产事故了,直接影响公司的运营。然而,这些问题的解决,通常在要日志中查找原因(当然,日志的作用不限于此),然后解决。

  我们见过最多的日志相关的代码莫过于System.out.println("");log4j 这两种了。下面我们来说说 SpringBoot 中日志框架的使用。

## 日志框架介绍

目前市面上的日志框架有:

JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....

log4j

  log4j 是 Apache 的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、数据库等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

Log4j有7种不同的log级别,按照等级从低到高依次为:TRACE<DEBUG<INFO<WARN<ERROR<FATAL<OFF。如果配置为OFF级别,表示关闭 log。

  Log4j支持两种格式的配置文件:properties和xml。

  包含三个主要的组件:Logger、appender、Layout。

slf4j

  slf4j,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,而是通过Facade Pattern提供一些Java logging API,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。作者创建SLF4J的目的是为了替代Jakarta Commons-Logging。

实际上,slf4j 所提供的核心API是一些接口以及一个 LoggerFactory 的工厂类。在使用 slf4j 的时候,不需要在代码中或配置文件中指定你打算使用那个具体的日志系统。slf4j 提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式、记录级别、输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统。

适用场景:

  如果你开发的是类库或者嵌入式组件,那么就应该考虑采用 slf4j,因为不可能影响最终用户选择哪种日志系统。在另一方面,如果是一个简单或者独立的应用,确定只有一种日志系统,那么就没有使用 slf4j 的必要。假设你打算将你使用 log4j 的产品卖给要求使用 JDK 1.4 Logging 的用户时,面对成千上万的 log4j 调用的修改,相信这绝对不是一件轻松的事情。但是如果开始便使用slf4j,那么这种转换将是非常轻松的事情。

logback

  Logback,一个“可靠、通用、快速而又灵活的Java日志框架”。

  logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core 是其它两个模块的基础模块。logback-classic 是 log4j 的一个改良版本。此外logback-classic 完整实现 SLF4J API 使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。logback-access 访问模块与 Servlet 容器集成提供通过Http来访问日志的功能。

  Java提供了自己的日志框架,类似于 slf4j,但是API并不完善,对开发者不是很友好,而且对于日志的级别分类也不是很清晰,比如:SEVERE, WARNING, INFO, CONFIG, FINE,FINER, FINEST。所以不推荐使用这种方式输出日志。

JCL

  Jakarta Commons Logging 和 slf4j 非常类似,也是提供的一套API来掩盖了真正的 logger 实现。便于不同的 logger 的实现的替换,而不需要重新编译代码。缺点在于它的查找 logger 的实现者的算法比较复杂,而且当出现了一些class loader之类的异常时,无法去修复它。

Log4j 2

  已经有很多其他的日志框架对 slf4j 进行了改良,比如说 slf4j、logback 等。而且 log4j2 在各个方面都与 logback 非常相似,那么为什么我们还需要 log4j2 呢?

  1. 插件式结构。log4j2 支持插件式结构。我们可以根据自己的需要自行扩展 log4j2 , 我们可以实现自己的 appender、logger、filter;
  2. 配置文件优化。在配置文件中可以引用属性,还可以直接替代或传递到组件。而且支持json格式的配置文件。不像其他的日志框架,它在重新配置的时候不会丢失之前的日志文件;
  3. Java 5 的并发性。log4j2 利用Java 5中的并发特性支持,尽可能地执行最低层次的加锁。解决了在 log4j1.x 中存留的死锁的问题。如果你的程序仍然在饱受内存泄露的折磨,请毫不犹豫地试一下 log4j2 吧;
  4. 异步 logger。log4j2 是基于 LMAX Disruptor库的。在多线程的场景下,和已有的日志框架相比,异步的 logger 拥有10左右的效率提升。

SpringBoot默认日志框架

默认配置

SpringBoot 默认使用的是 logback 日志系统,需要引入 maven 依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>

下面我们看看底层的依赖关系:

由上图可以得到几个结论:

  • SpringBoot 底层也是使用 slf4j+logback 的方式进行日志记录;
  • SpringBoot也把其他的日志都替换成了slf4j;

我们在启动类做一个简单的测试,观察效果:

@SpringBootApplication
public class LogDemoApplication {
private static final Logger logger = LoggerFactory.getLogger(LogDemoApplication.class);
public static void main(String[] args) {
logger.info("hello,logback!");
SpringApplication.run(LogDemoApplication.class, args);
}
}

  以上代码关于 LoggerFactory.getLogger() 方法中的参数 Clazz.class,主要是准确编写class信息能够提供快速定位日志的效率。即可以在日志中款速定位到要查找的内容。

启动程序,能够看到打印的日志:

自定义配置

  以上的示例中,都是用的 SpringBoot 默认的日志属性,当然,这些属性可修改,下图是属性列表,可以根据自己的需求进行自定义。

针对属性中关于日志格式的符号定义,此处也做一个简单的说明:

%d{HH:mm:ss.SSS}——日志输出时间
%thread——输出日志的进程名字,这在Web应用以及异步任务处理中很有用
%-5level——日志级别,并且使用5个字符靠左对齐
%logger- ——日志输出者的名字
%msg——日志消息
%n——平台的换行符

日志持久化

  以上示例是将日志打印到控制台。在实际项目中,日志通常是进行持久化,存储在文件中或者数据库中。

一、存储在文件中

只要在 application.properties 或者 application.yml 中配置以下属性:

# 日志路径
logging.path=
# 日志名称
logging.file=SpringBoot.log

二、存入数据库

这种方式就是醒目中的添加业务了。通常用的不多。

## SpringBoot与其他日志框架

  SpringBoot 默认使用的日志框架是 logback + slf4j ,如果想与其它的日志框架整合,则必须将默认的日志框架排除:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

与 log4j2 整合:

首先,引入 maven 依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

其次,log4j2.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<property name="LOG_PATH">../logs/</property>
<property name="LOG_FILE">testlog4j2</property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout>
<pattern>%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] - %m%n</pattern>
</PatternLayout>
</Console>
<RollingFile name="errorlogfile" fileName="${LOG_PATH}/${LOG_FILE}.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/${LOG_FILE}-%d{yyyy-MM-dd HH-mm}-%i.log">
<PatternLayout>
<pattern>%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="50 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
</Appenders>
<Loggers>
<root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="errorlogfile" />
</root>
</Loggers>
</Configuration>

第三步,在 application.properties 中指定配置文件的位置:

logging.config= classpath:log4j2.xml

第四步,在启动类中测试:

@SpringBootApplication
public class LogOtherDemoApplication {
private static Logger logger = LogManager.getLogger(LogOtherDemoApplication.class);
public static void main(String[] args) {
logger.info("这里是整合其他日志框架");
SpringApplication.run(LogOtherDemoApplication.class, args);
}
}

最后,启动项目,可以看到对应的日志和日志文件。

总结

  日志框架适用很广泛,而且涉及的内容内多,本章只做了日志介绍和适用的阐述。后续还涉及很多的内容,比如如何进行日志检索、如何进行日志清洗等。由于篇幅所限,本章不做过多的介绍。

  源码:我的GitHub

SpringBoot第十三篇:日志处理的更多相关文章

  1. SpringBoot第二十三篇:安全性之Spring Security

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11350255.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   系统的安全 ...

  2. MySQL学习【第十三篇日志管理】

    一.MySQL日志类型 日志文件 选项  文件名/表名称   程序 错误日志 --log-error   host_name.err N/A 常规日志 --general_log host_name. ...

  3. SpringBoot | 第二十三章:日志管理之整合篇

    前言 在本系列<第四章:日志管理>中,由于工作中日志这块都是走默认配置,也没有深入了解过,因为部署过程中直接使用了linux中的输出重定向功能,如java -jar xx.jar > ...

  4. 第十三篇 Integration Services:SSIS变量

    本篇文章是Integration Services系列的第十三篇,详细内容请参考原文. 简介在前一篇我们结合了之前所学的冒泡.日志记录.父子模式创建一个自定义的SSIS包日志记录模式.在这一篇,我们将 ...

  5. 【译】第十三篇 Integration Services:SSIS变量

    本篇文章是Integration Services系列的第十三篇,详细内容请参考原文. 简介在前一篇我们结合了之前所学的冒泡.日志记录.父子模式创建一个自定义的SSIS包日志记录模式.在这一篇,我们将 ...

  6. 在SpringBoot中用SpringAOP实现日志记录功能

    背景: 我需要在一个SpringBoot的项目中的每个controller加入一个日志记录,记录关于请求的一些信息. 代码类似于: logger.info(request.getRequestUrl( ...

  7. 跟我学SpringCloud | 第十三篇:Spring Cloud Gateway服务化和过滤器

    SpringCloud系列教程 | 第十三篇:Spring Cloud Gateway服务化和过滤器 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich. ...

  8. Spring Cloud第十三篇 | Spring Boot Admin服务监控

    本文是Spring Cloud专栏的第十三篇文章,了解前十二篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Clo ...

  9. 🔥SpringBoot图文教程2—日志的使用「logback」「log4j」

    有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 文章结尾配套自测面试题,学完技术自我测试更扎实 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例 ...

随机推荐

  1. DVWA-CSRF学习笔记

    DVWA-CSRF学习笔记 一.CSRF(跨站请求伪造) CSRF(跨站请求伪造),是指利用受害者尚未失效的身份认证信息(cookie.session会话等),诱骗其点击恶意链接或者访问包含攻击代码的 ...

  2. JMeter性能测试入门--简单使用

    1.JMeter整体简介 Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域. 它可以用于测试 ...

  3. Qt for Android使用grpc探索

    利用Qt在Android上使用grpc需要*.a的静态库,Windows上编译的lib库以及linux编译出来的.a,经过尝试,均无法链接成功.本文尝试使用NDK来编译Android版本的grpc静态 ...

  4. 英语cartialgenous鹿茸cartialgenous单词

    鹿茸cartialgenous是雄鹿未骨化密生茸毛的幼角,主要从梅花鹿和马鹿头上采收,前者叫花鹿茸.黄毛茸,后者叫青毛茸.雄鹿到了一定年纪头上就会长角,初发时嫩如春笋,其表面上有一层纤细茸毛的嫩角就是 ...

  5. Scrum 冲刺第二篇

    我们是这次稳了队,队员分别是温治乾.莫少政.黄思扬.余泽端.江海灵 一.会议 1.1  26号站立式会议照片: 1.2  昨天已完成的事情 团队成员 任务内容 黄思扬 Web 端首页.内容管理页开发. ...

  6. js 实现JSONP

    编写一个 jsonp.html 内容如下: <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  7. [TCP/IP]TCP服务端accept发生在三次握手的哪一个阶段

    TCP服务端accept发生在三次握手之后 客户端socket()==>connect()==>write()==>read()服务端socket()==>bind()==&g ...

  8. centos7 下 通过终端 连接 蓝牙设备

    #首先确定硬件上有支持蓝牙的设备,插入蓝牙发射器.然后运行如下命令,就可以开到我们的蓝牙设备了: lsusb [root@localhost ~]# lsusbBus 002 Device 003: ...

  9. python 模块、包

    #-----模块.包----- 模块: 一个.py 文件就称之为模块模块好处:1.提高代码可读性 2.编写代码不需要从零开始 python 模块: 1.python标准库 2.第三方模块 3.应用程序 ...

  10. scanf的返回值

    参考这个博客,https://blog.csdn.net/sinat_40936062/article/details/84348021 #include<stdio.h> int mai ...