Spring Boot 日志

目录

一、为什么要学习日志

二、认识日志格式

三、日志使用

打印日志

步骤

日志框架介绍

门面模式(外观模式)

门面模式的实现

门面模式的优点

四、日志级别

日志级别分类

日志级别的使用

日志配置

配置日志级别

日志持久化

配置日志文件分割

五、更简单的日志输出


一、为什么要学习日志

日志对我们来说并不陌生,从JavaSE部分,我们就在使用 System.out.print 来打印日志了.通过打
印日志来发现和定位问题,或者根据日志来分析程序的运行过程.在 Spring 的学习中,也经常根据控制台的日志来分析和定位问题.

随着项目的复杂度提升,我们对日志的打印也有了更高的需求,而不仅仅是定位排查问题.

比如需要记录一些用户的操作记录(一些审计公司会要求),也可能需要使用日志来记录用户的一些喜好,把日志持久化,后续进行数据分析等.但是 System.out.print 不能很好的满足我们的需求,我们就需要使用一些专门日志框架(专业的事情交给专业的人去做).

二、认识日志格式

1️⃣时间日期:精确到毫秒
2️⃣日志级别:ERROR,WARN,INFO,DEBUG或TRACE
3️⃣进程 ID
4️⃣线程名
5️⃣Logger 名(通常使用源代码的类名)
6️⃣日志内容

三、日志使用

SpringBoot 内置了日志框架 Slf4j ,我们可以直接在程序中调用 Slf4j 来输出日志

打印日志

步骤

• 在程序中得到日志对象.

需要使用志工厂  LoggerFactory

private static Logger logger = LoggerFactory.getLogger(CaptchaController.class);

LoggerFactory.getLogger 需要传递⼀个参数, 标识这个日志的名称. 这样可以更清晰的知道是哪个类输出的日志. 当有问题时, 可以更方便直观的定位到问题类 

• 使用日志对象输出要打印的内容.

日志对象的打印方法有很多种,我们可以先使用 info() 方法来输出日志

logger.info("Logger生成验证码: " + code);

日志框架介绍

SLF4J不同于其他日志框架, 它不是一个真正的日志实现, 而是一个抽象层, 对日志框架制定的一种规范, 标准, 接口. 所有SLF4J并不能独立使用, 需要和具体的日志框架配合使用.

门面模式(外观模式)

SLF4J是门面模式的典型应用(但不仅仅使用了门面模式).

门面模式(Facade Pattern)又称为外观模式,提供了一个统一的接口,用来访问子系统中的一群接口.其主要特征是定义了一个高层接口,让子系统更容易使用.

门面模式主要包含2种角色:
外观角色(Facade):也称门面角色,系统对外的统一接口.
子系统角色(SubSystem):可以同时有一个或多个SubSystem.每个SubSytem都不是一个单独的类,
而是一个类的集合.SubSystem并不知道Facade的存在,对于SubSystem而言,Facade只是另一个客户端而已(即Facade对SubSystem透明)

门面模式的实现

场景: 回家, 我们会开各个屋的灯. 离开家时, 会关闭各个屋的灯. 如果家里设置⼀个总开关, 来控制整个屋的灯就会很方便.

没建门面前

package com.example.demo.facade;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public interface Light {void on();void off();
}public HallLight implements Light {private static Logger logger = LoggerFactory.getLogger(HallLight.class);@Overridepublic void on() {logger.info("打开走廊灯");}@Overridepublic void off() {logger.info("关闭走廊灯");}
}public LivingRoomLight implements Light {private static Logger logger = LoggerFactory.getLogger(LivingRoomLight.class);@Overridepublic void on() {logger.info("打开客厅灯");}@Overridepublic void off() {logger.info("关闭客厅灯");}
}public BedRoomLight implements Light {private static Logger logger = LoggerFactory.getLogger(BedRoomLight.class);@Overridepublic void on() {logger.info("打开卧室灯");}@Overridepublic void off() {logger.info("关闭卧室灯");}
}public class Main {public static void main(String[] args) {HallLight hallLight = new HallLight();LivingRoomLight livingRoomLight = new LivingRoomLight();BedRoomLight bedRoomLight = new BedRoomLight();hallLight.on();livingRoomLight.on();bedRoomLight.on();}
}

我们使用门面模式的实现

package com.example.demo.facade;public class LightFacade {void lightOn() {HallLight hallLight = new HallLight();LivingRoomLight livingRoomLight = new LivingRoomLight();BedRoomLight bedRoomLight = new BedRoomLight();hallLight.on();livingRoomLight.on();bedRoomLight.on();}void lightOff() {HallLight hallLight = new HallLight();LivingRoomLight livingRoomLight = new LivingRoomLight();BedRoomLight bedRoomLight = new BedRoomLight();hallLight.off();livingRoomLight.off();bedRoomLight.off();}
}
package com.example.demo.facade;public class Main {public static void main(String[] args) {LightFacade lightFacade = new LightFacade();lightFacade.lightOn();lightFacade.lightOff();}
}

门面模式的优点

●减少了系统的相互依赖,实现了客户端与子系统的耦合关系,这使得子系统的变化不会影响到调用它的客户端.
●提高了灵活性,简化了客户端对子系统的使用难度,客户端无需关心子系统的具体实现方式,而只需要和门面对象交互即可.
●提高了安全性,可以灵活设定访问权限,不在门面对象中开通方法,就无法访问.

SLF4J 就是其他日志框架的门面. SLF4J 可以理解为是提供日志服务的统一API接口, 并不涉及到具体的日志逻辑实现.

四、日志级别

日志级别代表着日志信息对应问题的严重性, 为了更快的筛选符合目标的日志信息.

日志级别分类

日志的级别从高到低依次为:FATAL、ERROR、WARN、INFO、DEBUG、TRACE
🔺FATAL: 致命信息,表示需要立即被处理的系统级错误.
🔺ERROR: 错误信息,级别较高的错误日志信息,但仍然不影响系统的继续运行.
🔺WARN: 警告信息,不影响使用,但需要注意的问题.
🔺INFO: 普通信息,用于记录应用程序正常运行时的一些信息,例如系统启动完成、请求处理完成等.
🔺DEBUG: 调试信息,需要调试时候的关键信息打印.
🔺TRACE: 追踪信息,比 DEBUG 更细粒度的信息事件(除非有特殊用意,否则请使用 DEBUG级别替代).

日志级别的使用

package com.example.demo.controller;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/logger")
@RestController
public class LoggerLevelController {private static Logger logger = LoggerFactory.getLogger(LoggerLevelController.class);@RequestMapping("/print")public String print() {logger.trace("trace级别日志......");logger.debug("debug级别日志......");logger.info("info级别日志......");logger.warn("warn级别日志......");logger.error("error级别日志......");return "打印日志";}
}

 

结果发现, 只打印了info, warn和error级别的日志.

这与日志级别的配置有关, 日志的输出级别默认是 info 级别, 所以只会打印大于等于此级别的日志, 也就是 info, warn和error.

日志配置

配置日志级别

logging:level:root: debug

日志级别也可以分类来设置

logging:level:root: infocom:example:demo:controller: trace

日志持久化

以上的日志都是输出在控制台上的, 然日在线上环境中, 我们需要把日志保存下来, 以便出现问题之后追溯问题. 把日志保存下来就叫持久化.

日志持久化有两种方式

1️⃣配置日志文件名

logging:file:name: logger/springboot.log

后⾯可以跟绝对路径或者相对路径

2️⃣配置日志的存储目录

logging:file:path: D:/temp

logging:file:path: D:/temp/aaa/springboot.log

这种方式只能设置日志的路径, 文件名为固定的 spring.log

⚠️logging.file.name 和 logging.file.path 两个都配置的情况下, 只生效其一, 以 logging.file.name 为准.

配置日志文件分割

如果我们的日志都放在一个文件中, 随着项目的运行, 日志文件会越来越大, 需要对日志文件进行分割.

logging:file:#path: D:/temp/aaa/springboot.logname: logger/springboot.loglogback:rollingpolicy:max-file-size: 1KBfile-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i

 

1.日志文件超过 1KB 就分割(设置 1KB 是为了更好展示.企业开发通常设置为200M,500M等,此处没有明确标准)
2.分割后的日志文件名为:日志名.日期.索引

五、更简单的日志输出

每次都使用 LoggerFactory.getLogger(xxx.class) 很繁琐, 且每个类都添加一遍, lombok 给我们提供了⼀种更简单的方式.

1️⃣添加 lombok 框架支持

2️⃣使用 @Slf4j 注解输出日志

lombok 提供的 @Slf4j 会帮我们提供⼀个日志对象 log, 我们直接使用就可以.

package com.example.demo.controller;import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RequestMapping("/logger2")
@RestController
public class LoggerLevelController2 {//private static Logger logger = LoggerFactory.getLogger(LoggerLevelController2.class);@RequestMapping("/print")public String print() {log.trace("trace级别日志......");log.debug("debug级别日志......");log.info("info级别日志......");log.warn("warn级别日志......");log.error("error级别日志......");return "打印日志";}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/31298.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux内存页块划分及位图存储机制

page_alloc.c - mm/page_alloc.c - Linux source code v5.4.285 - Bootlin Elixir Cross Referencer 一. 什么是页块(Pageblock)? 定义:页块是物理内存中的一个连续区域,由 2^pageblock_order 个物理页(Pag…

chebykan与代码3

目录 参考文献有 ‘’ 中文 各自讲了什么 切比雪夫多项式有两类吗?这里存疑 KAN变体 期刊 切比雪夫と爱因斯坦の约定 维度标签的含义 爱因斯坦求和约定 参考文献有 ‘’ 中文 [1] 神经网络:全面基础 [2] 通过sigmoid函数的超层叠近似 [3] 多层前…

DETR详解

1.概述 DETR,全称为Detection Transformer,是Facebook在ECCV2020上提出的基于Transformer的端到端目标检测网络最大的特点就是:不需要预定义的先验anchor,也不需要NMS的后处理策略,就可以实现端到端的目标检测。但是&…

南昌长空STONE 60A-M 无人机电调深度测评:轻量化设计与工业级安全的融合典范

引言 在无人机技术不断革新的今天,电调作为动力系统的核心组件,其性能直接影响飞行稳定性与操控体验。STONE 系列凭借 “轻量化设计” 理念,在竞争激烈的市场中独树一帜。本文将深度解析 STONE 60A-M 电调的技术亮点与实际表现,探…

初阶数据结构(C语言实现)——4.2队列

目录 2.队列2.1队列的概念及结构2.2队列的实现2.2.1 初始化队列2.2.2 销毁队列2.2.3 队尾入队列2.2.4 队头出队列2.2.5获取队列头部元素2.2.6 获取队列队尾元素2.2.7获取队列中有效元素个数2.2.8 检测队列是否为空,如果为空返回非零结果,如果非空返回0 3…

C++和OpenGL实现3D游戏编程【连载24】——父物体和子物体之间的坐标转换

欢迎来到zhooyu的C++和OpenGL游戏专栏,专栏连载的所有精彩内容目录详见下边链接: 🔥C++和OpenGL实现3D游戏编程【总览】 父子物体的坐标转换 1、本节要实现的内容 前面章节我们了解了父物体与子物体的结构,它不仅能够表示物体之间的层次关系,更重要的一个作用就是展示物…

怎么实现: 大语言模型微调案例

怎么实现: 大语言模型微调案例 目录 怎么实现: 大语言模型微调案例输入一个反常识的问题:首都在北京天安门之后对输出模型进行测试:首都在北京天安门微调代码:测试微调模型代码:微调输出模型结构输出模型参数大小对比Qwen 2.5_0.5:53MB输出模型:951MB 是一样的,没有进行…

知乎后台管理系统:数据库系统原理实验1——数据库基础概念

实验背景 通过练习绘制语义网络,加深对于基本概念之间关系的理解和掌握。掌握在VISIO中绘制能准确表达基本概念之间关系的语义网络的技能。了解并比较数据模型的Chen’s表示法和UML表示法。理解关系模型设计中的完整性约束的重要性。掌握在Linux操作系统下远程访问…

超过 37000 台 VMwareESXi 服务器可能受到持续攻击威胁

近日,威胁监测平台影子服务器基金会(The Shadowserver Foundation)发布报告,指出超 3.7 万个互联网暴露的威睿(VMware)ESXi 实例存在严重安全隐患,极易受到 CVE-2025-22224 漏洞的攻击。该漏洞属…

Linux《基础开发工具(中)》

在之前的Linux《基础开发工具(上)》当中已经了解了Linux当中到的两大基础的开发工具yum与vim;了解了在Linux当中如何进行软件的下载以及实现的基本原理、知道了编辑器vim的基本使用方式,那么接下来在本篇当中将接下去继续来了解另…

Vue3 Pinia 符合直觉的Vue.js状态管理库

Pinia 符合直觉的Vue.js状态管理库 什么时候使用Pinia 当两个关系非常远的组件,要传递参数时使用Pinia组件的公共参数使用Pinia

知识库Dify和cherry无法解析影印pdf word解决方案

近期收到大量读者反馈:上传pdf/图文PDF到Dify、Cherry Studio等知识库时,普遍存在格式错乱、图片丢失、表格失效三大痛点。 在试用的几款知识库中除了ragflow具备图片解析的能力外,其他的都只能解析文本。 如果想要解析扫描件&#xff0c…

Webservice创建

Webservice创建 服务端创建 3层架构 service注解(commom模块) serviceimpl(server) 服务端拦截器的编写 客户端拦截器 客户端调用服务端(CXF代理) 客户端调用服务端(动态模式调用&a…

腾讯云低代码开发应用

创建客户端应用 如上所示,登录腾讯云微搭低代码业务控制台,开始搭建企业官网应用 如上所示,在腾讯云微搭低代码业务控制台中,开始创建企业官网应用 如上所示,在腾讯云微搭低代码业务控制台中,开始编辑企业官…

【Java开发指南 | 第三十四篇】IDEA没有Java Enterprise——解决方法

读者可订阅专栏:Java开发指南 |【CSDN秋说】 文章目录 1、新建Java项目2、单击项目名,并连续按两次shift键3、在搜索栏搜索"添加框架支持"4、勾选Web应用程序5、最终界面6、添加Tomcat 1、新建Java项目 2、单击项目名,并连续按两次…

深度学习原理与Pytorch实战

深度学习原理与Pytorch实战 第2版 强化学习人工智能神经网络书籍 python动手学深度学习框架书 TransformerBERT图神经网络: 技术讲解 编辑推荐 1.基于PyTorch新版本,涵盖深度学习基础知识和前沿技术,由浅入深,通俗易懂&#xf…

uniapp项目运行失败Error: getaddrinfo *.bspapp.com 文件查找失败uview-ui及推荐MarkDown软件 Typora

一、uniapp项目运行失败Error: getaddrinfo *.bspapp.com 文件查找失败uview-ui 在运行一个uniapp项目时,出现报错 文件查找失败:uview-ui,Error: getaddrinfo ENOTFOUND 960c0a.bspapp.com。hostname异常,报错的详细信息如下&…

什么是vue的keep-alive?它是如何实现的?具体缓存了什么内容?

文章目录 一、keep-alive 的核心作用二、实现原理1. 缓存管理策略2. 核心源码解析(Vue 2.x 简化版)3. 缓存生命周期 三、缓存的具体内容1. 缓存对象结构2. 具体缓存内容 四、使用示例1. 基础用法2. 配置缓存策略 五、注意事项六、实现流程图解 Vue 的 k…

pytest基础知识

pytest知识了解 pytest的基础知识了解:Python测试框架之pytest详解_lovedingd的博客-CSDN博客_pytest框架 (包含设置断点,pdb,获取最慢的10个用例的执行耗时) pytest-pytest.main()运行测试用例,pytest参数: pytest-…

Liunx(CentOS-6-x86_64)使用Nginx部署Vue项目

一:编译vue项目和上传到linux系统 通过本地编译器编译后的文件 上传服务器后的 二:安装 node(版本 v16.20.2)和npm( 8.19.4或 9.6.5) 备注一:安装nodejs就是安装node和npm, su…