欢迎光临
我们一直在努力

Java EE 进阶:7.Spring Boot 日志(第二弹)

目录

2.5 日志配置

2.5.1 配置日志级别

分目录/路径设置级别

2.5.2 日志持久化

配置日志文件的路径和文件名:

配置日志文件的保存路径

2.5.3 配置日志文件分割

2.5.4 配置日志格式

3.更简单的日志输出

3.1 添加 Lombok 依赖

3.2 输出日志

4.总结


书接上文:Java EE 进阶:7.Spring Boot 日志(第一弹)~~

2.5 日志配置

上述是日志的使用, 日志框架支持我们更灵活的输出日志, 包括内容, 格式等.

2.5.1 配置日志级别

日志级别配置只需要在配置文件中设置"logging.level"配置项即可,如下所示: 后面课程中出现的配置, properties 和yml只需要配置其中一个即可. 二者转换方式: Properties文件的点( . ) 对应yml文件中的换行 以下两个配置, 根据项目使用其中之一. Properties配置

logging.level.root=debug

yml配置(咱们手动调整成 tarce 级别)

logging:
level:
root: trace

这个 root 就是根目录的意思~~

对于所有目录都生效,所有目录都是 trace 级别

重新运行上述代码, 观察结果我们发现此时日志就变得特别细了,甚至创建一个对象都跟你说👇

而我们打印的日志就在这里👇

找不到的话就右键全部清空,然后再访问 http://127.0.0.1:8080/log/print

分目录/路径设置级别

那我现在又有需求了,我只想看我自己打印的 tarce 级别的日志,其他的那些日志我都不想看,咋办??上面我们说 root 是根目录,那么这时候就用到分目录了👇

logging:
level:
root: info
com:
bit:
log:
controller: trace

此时我们发现 Spring 那些低于 info 的就不打印了,没有那么多了,同时还把我们需要的 trace 和 debug 打印出来了👇

答疑:

Q1:之前讲的验证码那个 session 的 key 写死了那多个用户请求验证码是不是会有错误??👇

先说一下,不会报错的,这就又需要我们 Session 相关的知识了

一句话:Session 是存储用户信息的会话机制,自然能分辨出不同的用户信息~~

所以说 Session 本身就是分用户的,我们的 Tomcat (就是咱们一直用的 IDEA 的 Web 服务器)本身就是多线程的,所以我们不用取考虑这用户过来的时候什么样,当我们运行项目的时候,Tomcat 就会从线程池中拿一个线程给我们跑,所以这个线程的安全性是我们的服务器本身就给我们保证了的

所以这里分两个都给我们了保证:

Session 本身的机制就保证了各个用户的隔离性,SessionId 已经帮我们区分好了

服务端帮我们做的,下面给大家演示一下👇

@RequestMapping("/captcha")
@RestController
public class CaptchaController {
private static final Logger logger = LoggerFactory.getLogger(CaptchaController.class);
@Autowired//把配置文件的内容注入进来
//……
logger.info("getCaptcha cost time:"+(end-start)+"ms");
}

/**
* 验证用户输入的验证码是否正确
* @param captcha:用户输入的验证码
* @param session
* @return false:校验失败,true:验证成功
*/
//……
}

然后多请求几次👇

此时我们就能发现服务端已经帮我们创建多线程了👇

所以请求过来的时候,Tomcat 是去线程池中去拿线程的,已经帮我们做好了,咱们无需考虑,当然,如果是你自己写的,你就需要考虑了~~

有同学一开始说给定义在上面,像这个一样👇

那这时候就可能有问题了,因为这个 static 本身意思就是大家共享的了,所以我们要引入 Session~~

Q2:现在面试的时候日志这里问的多吗??

现在问的不多了,因为日志现在也越来越好用了,15年前问的多,15年前大家都用的 log4j 和 logback,用着是非常麻烦的,日志老是出问题,要么就是项目启动了,但是没日志~~

注意 log4j 念 log Four j,而不是数字 4,说出去让人家笑话~~

闲聊:校招VS社招

校招:校园招聘(只针对在校学生)

社招:社会招聘(在校学生+社会人士)

猎聘、智联、BOSS直聘这都属于社招,我们可以直接在网上搜索校园招聘,比如字节的,这就是只针对在校学生👇字节跳动校园招聘官网|字节跳动校招

其中大四或者即将大四毕业走应届生招聘,大一、大二、大三走实习生招聘~~

但是校招相对社招来说会多一点点

Q:高中生能招吗??

一般是不招的,高中招的话只能是小时工或者兼职

但是学历在咱们这还是比较看重的,大公司更是在意,因为他们认为,基础知识是可以培养的,但是一个人的先天的智商培养不出来,所以更喜欢问一些场景题来考察思维

社招的话,场景提问就比较少了,社招主要看你以往的公司、工作经验,工作时间越长就越不看你学校了,工作个十年,可以说学历这个滤镜就彻底没有了~~

当然,我们投简历的时候先投小公司,练练手,挂了也无所谓,因为大公司都是有面试记录的,甚至连几年前甚至问了你什么,你的态度……都会有记录的~~

所以日志这里大家会用就行了,日志就不用准备面试了~~

2.5.2 日志持久化

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

1. 配置日志文件名 2. 配置日志的存储目录

这个图片取自:Common Application Properties :: Spring Boot

配置日志文件的路径和文件名:

 Properties配置

logging.file.name=log.log

yml配置

# 设置日志文件的文件名
logging:
file:
name: log.log

注意,我们官方文档和课件中给的配置都是从最左边给大家提供的,所以要稍微修改一下👇

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
name: log.log

运行程序后刷新一下就会在左边多了一个日志文件👇

而这个日志文件就会持久记录我们的日志👇形式是追加的~~

后面可以跟绝对路径或者相对路径 下面我们来写一下相对路径👇

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
name: log/log.log

重启服务后,还是相同的刷新方法,然后就会发现在这里多了一个 log 文件夹👇里面就是日志文件,把刚才启动的日志存储在这里了

配置日志文件的保存路径

为了方便观察,我们把上述两个日志文件全部删掉,再来测试

Properties配置

logging.file.path=D:/temp

yml配置

# 设置日志文件的目录
logging:
file:
path: D:/temp

上述是课件的绝对路径,我们现在配置相对路径👇

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
# name: log/log.log
path: logger/

运行服务后刷新👇发现加载出来了,已经放在我们的硬盘上了

那我们能不能像上面一样,把名称也配置上呢??下面来测试一下👇(依旧把刚刚的日志文件删掉,方便观察)

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
# name: log/log.log
path: logger/log.log

运行服务后刷新👇

我们发现并不能,log.log 变成了一个文件夹,它认为这是一个文件夹,因为这是配置路径的,所以只能为路径,不能为文件

这种方式只能设置日志的路径, 文件名只能为 spring.log,不能修改名称 那么我们现在就知道了:

file.name:可以配置名称,可以带绝对路径或相对路径

file.path:可以配置路径

那么我一个配置的 log,一个配置的 logger,到底用哪个??👇

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
name: log/log.log
path: logger

依旧删除旧日志文件,重启服务后刷新,观察结果👇

我们发现 log.log 生效了~~

那是不是因为 log.log 写在了 logger/ 上面才生效呢??我们把它俩互换一下位置再来测试👇

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
path: logger
name: log/log.log

我们发现还是 log.log 生效了👇

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

那么现在我们又有疑问了,既然一个是配置路径一个是配置名称,那我能不能这么写,把 log.log 文件放在 logger 文件夹下面呢??👇

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
path: logger
name: log.log

依旧删除旧日志文件,重启服务后刷新,观察结果👇

我们发现这是不可以的,也就是说,logging.file.name 和 logging.file.path 同时存在时,logging.file.path 是完全不生效的~~

2.5.3 配置日志文件分割

我们上面也说了,这种日志是追加的方式👇

如果我们的日志都放在一个文件中, 随着项目的运行, 日志文件会越来越大, 需要对日志文件进行分割. 当然, 日志框架也帮我们考虑到了这一点, 所以如果不进行配置, 就走自动配置 默认日志文件超过10M就进行分割

配置项说明默认值
logging.logback.rollingpolicy.file-name-pattern 日志分割后的文件名格式 ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
logging.logback.rollingpolicy.max-file-size 日志文件超过这个大小就自动分割 10MB

配置日志文件分割:

下面我们按 1KB 尝试分割,为了日志内容多一些,把日志级别改为 tarce👇

logging:
level:
root: trace
com:
bit:
log:
controller: trace
file:
# path: logger
name: logger/log.log
logback:
rollingpolicy:
max-file-size: 1KB

logback 大家应该不陌生了,这个是一个日志框架,因为我们的 slf4j 或者 Spring 都是对 logback 进行封装,里面的包括这些配置也都是 logbcak 的配置

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

打开查看确实每个都是 1KB👇

随便打开一个,可以发现里面就是日志的内容👇

上面文件的命名格式对应着

file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz

${LOG_FILE}:定义的日志名称

%d:日期

{yyyy-MM-dd}:日期格式

%i:序号

gz:文件格式

如果说刚刚生成的文件名不合适,那么我还可以设置一个文件名称,比如把 .gz 去掉,这样打开方便点,能避免解压👇

logging:
level:
root: trace
com:
bit:
log:
controller: trace
file:
# path: logger
name: logger/log.log
logback:
rollingpolicy:
max-file-size: 10KB
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i

可以看到这次不用解压就能打开了👇

注意:这个日志分割不是严格的 10KB,而是按行为单位来,起码把这一行日志给你打印完整才会分割的

比如我们接下来设置成 1字节,直接改为 1B👇

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
# path: logger
name: logger/log.log
logback:
rollingpolicy:
max-file-size: 1B
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i

运行后我们随便打开一看,基本上都是一行一个日志👇

而文件大小显然已经超过了 1B👇

所以说 1B 可以说根本就设置不上的~~

2.5.4 配置日志格式

目前日志打印的格式是默认的

打印日志的格式, 也是支持配置的. 支持控制台和日志文件分别设置

配置项说明默认值
logging.pattern.console 控制台日志格式 %clr(%d${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:-}){magenta} %clr(—){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
logging.pattern.file 日志文件的日志格式 %d${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } — [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}

配置项说明:(上面这个默认值是旧的,大家了解即可) 1. %clr(表达式){颜色} 设置输入日志的颜色 支持颜色有以下几种: • blue • cyan • faint • green • magenta • red • yellow

2. %d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} 日期和时间–精确到毫秒 %d{} 日期 ${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX} 非空表达式, 获取 系统属性LOG_DATEFORMAT_PATTERN , 若属性 LOG_DATEFORMAT_PATTERN 不存在,则使用 -yyyy-MM-dd HH:mm:ss.SSSXXX 格式, 系统属性可以 System.getProperty("LOG_DATEFORMAT_PATTERN") 获取 3. %5p 显示日志级别ERROR,MARN,INFO,DEBUG,TRACE. 4. %t 线程名. %c 类的全限定名. %M method. %L 为行号. %thread 线程名称. %m 或者 %msg 显示输出消息. %n 换行符 5. %5 若字符长度小于5,则右边用空格填充. %-5 若字符长度小于5,则左边用空格填充. %.15 若字符长度超过15,截去多余字符. %15.15 若字符长度小于15,则右边用空格填充. 若字符长度超过15,截去多余字符 更多说明, 参考:Chapter 6: Layouts 设置了颜色, 却没有生效? 需要配置, 让idea支持控制台颜色显示

运行程序,找到这个👇 1. 打开启动配置, 添加VM options

2. 添加VM options -Dspring.output.ansi.enabled=ALWAYS

3. 重新启动程序, 就发现控制台支持颜色了(日志级别不同颜色也不同~~)

Properties配置

logging.pattern.console='%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'

yml配置

logging:
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
file: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'

总的 yml 👇

logging:
level:
root: info
com:
bit:
log:
controller: trace
file:
# path: logger
name: logger/log.log
logback:
rollingpolicy:
max-file-size: 10MB
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
file: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'

启动服务后重新访问一下网页(调用一下接口)👇

观察日志变化,可以看到此时我们自定义的日志格式就生效了👇

格式:日期+时间+类+print+打印的行+线程名称+日志+换行

通常情况下, 咱们就使用默认的日志格式打印即可.

3.更简单的日志输出

package com.bit.log.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* Created with IntelliJ IDEA.
* Description:
* User: CoderYanger
* Date: 2026-11-02
* Time: 19:37
*/
@RequestMapping("/log")
@RestController
public class LogController {
private static Logger logger = LoggerFactory.getLogger(LogController.class);
@RequestMapping("/print")
public String print(){
System.out.println("sout打印日志");
logger.info("logger 打印日志");
logger.trace("logger trace…");
logger.debug("logger debug…");
logger.info("logger info…");
logger.warn("logger warn…");
logger.error("logger error…");
//Logger没提供fatal,因为也用不上,问题太大也没必要看日志了~~
return "打印日志";
}
}

上述代码的这一行👇

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

默认打印的就是 LogController.class,全限定名称(路径+类名)👇

如果我们改成 aaaa👇

private static Logger logger = LoggerFactory.getLogger("aaaa");

那么打印的就是 aaaa👇

但是我们基本是不会改的,因为一改就不知道这是个啥了,所以这一行默认就是固定的~~

每次都使用 LoggerFactory.getLogger(xxx.class) 很繁琐, 且每个类都添加一遍, lombok给我们提供了一种更简单的方式. 1. 添加 lombok 框架支持 2. 使用 @slf4j 注解输出日志。

3.1 添加 Lombok 依赖

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

3.2 输出日志

@Slf4j
@RequestMapping("/log2")
@RestController
public class LogController2 {
@RequestMapping("/print")
public String print(){
System.out.println("sout打印日志");
log.info("logger 打印日志");
log.trace("logger trace…");
log.debug("logger debug…");
log.info("logger info…");
log.warn("logger warn…");
log.error("logger error…");
return "打印日志";
}
}

注意:此处路径映射为 log2,不能与刚刚的 log 重复,否则会路径映射错误,引起报错~~

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

启动服务后,重新调用一下接口,再来查看日志👇​​​​​​​

我们接下来来看它的原理是什么👇

以后我们打印日志直接用这个来自 Lombok 的注解就可以了~~

4.总结

1. 日志是程序中的重要组成部分,使用日志可以快速的发现和定位问题,Spring Boot 内容了日志框架,默认情况下使用的是 info 日志级别将日志输出到控制台的,我们可以通过 lombok 提供的 @Slf4j 注解和 log 对象快速的打印自定义日志. 2. 日志包含 6 个级别, 日志级别越高,收到的日志信息也就越少,我们可以通过配置日志的保存名称或保存目录来将日志持久化. 

赞(0)
未经允许不得转载:171主机测评 » Java EE 进阶:7.Spring Boot 日志(第二弹)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址