⽇志是程序的重要组成部分它在我们运行检查程序时用来发现和定位问题
除了发现和定位问题之外,我们还可以通过⽇志实现以下功能:
● 记录⽤户登录⽇志,⽅便分析⽤户是正常登录还是恶意破解⽤户
● 记录系统的操作⽇志,⽅便数据恢复和定位操作⼈
● 记录程序的执⾏时间,⽅便为以后优化程序提供数据⽀持
以上这些都是⽇志提供的⾮常实⽤的功能
⽇志真⽤案例:
关键节点上的关键数据⽇志记录举例:例如,⽐抖音,在注册时候不⽌要在抖音添加⼀条⽤户记录,同时也会给抖音极速版添加⼀条⼀模⼀样的⽤户记录,这样做的⽬的是为了实现⼀次注册,多处使⽤的⽬的。不需要⽤户在两边系统注册了,等于在程序中以极低的成本实现的⽤户数据的同步,但这样设计有⼀个致命的问题,⽤户在抖音注册信息的时候,如果抖音挂了,那么⽤户的注册⾏为就会失败?因为⽤户在注册的时候需要同步注册到抖音极速版,但抖音极速版现在挂了,这个时候怎么办呢?
解决方案:
最简单的解决⽅案,抖音在注册的时候,不管抖音极速版是否注册成功,都给⽤户返回成功,那这个时候如果抖音极速版注册失败了怎么办?⾮常简单,如果注册失败了,记录⼀下⽇志,等抖音极速版系统恢复正常之后,把⽇志给抖音极速版的管理⼈员,让他⼿动将注册失败的⽤户同步到抖音极速版,这样就最低成本的解决了问题。这就是⽇志的重要作⽤
其实在我们使用Spring Boot框架运行时我们就已经在控制台中看到了日志的打印
以上内容就是 Spring Boot 输出的控制台⽇志信息
通过上述⽇志信息我们能发现以下 3 个问题:
●Spring Boot 内置了⽇志框架(不然也输出不了⽇志)
●默认情况下,输出的⽇志并⾮是开发者定义和打印的,那开发者怎么在程序中⾃定义打印⽇志呢?
●⽇志默认是打印在控制台上的,⽽控制台的⽇志(内存)是不能被保存的,那么怎么把⽇志永久的保存下来呢
下⾯我们⼀起来找寻这些问题的答案
开发者⾃定义打印⽇志的实现步骤:
●在程序中得到⽇志对象
●使⽤⽇志对象的相关语法输出要打印的内容
注意:Logger 对象是属于 org.slf4j 包下的,不要导⼊错包。到问题类
private final static Logger log = LoggerFactory.getLogger(类名.class)
⽇志⼯⼚需要将每个类的类型传递进去,这样我们才知道⽇志的归属类,才能更⽅便、更直观的定位
@Controller
@ResponseBody //动态页面
public class UserController {
//1. 先得到日志对象(来自 slf4j)
//通过日志工厂的getLogger()方法获取需要打印日志类中的对象
private final static Logger log = LoggerFactory.getLogger(UserController.class);
@RequestMapping("/sayhi")
public void sayHi(){
log.trace("我是trace 微量级比");
log.debug("我是 debug 调试日志");
log.info("我是 info 普通信息日志");
log.warn("我是 warn 警告日志");
log.error("我是 error 错误日志");
// fatal 是导致程序崩坏的(致命bug)程序会自动去打印的
}
}
我们在网页127.0.0.1:8080/sayhi 之后就可以在控制台看到打印出的日志
我们发现我们应该在打印台中看到日志的信息只有info warn error
三个级别,这是因为spring boot默认的日志打印级别为info
日志的级别是怎样的呢,记下了我们就要开始认识日志的级别了
● ⽇志级别可以帮你筛选出重要的信息,⽐如设置⽇志级别为 error,那么就可以只看程序的报错⽇志了,对于普通的调试⽇志和业务⽇志就可以忽略了,从⽽节省开发者信息筛选的时间
● ⽇志级别可以控制不同环境下,⼀个程序是否需要打印⽇志,如开发环境我们需要很详细的信息,⽽⽣产环境为了保证性能和安全性就会输⼊尽量少的⽇志,⽽通过⽇志的级别就可以实现此需求
⽇志的级别分为:
●trace:微量,少许的意思,级别最低
●debug:需要调试时候的关键信息打印
●info:普通的打印信息(默认⽇志级别)
●warn:警告,不影响使⽤,但需要注意的问题
●error:错误信息,级别较⾼的错误⽇志信息
●fatal:致命的,因为代码异常导致程序退出执⾏的事件
越往上接收到的消息就越少,如设置了 warn 就只能收到 warn、error、fatal 级别的⽇志了
⽇志级别配置只需要在配置⽂件中设置“logging.level”配置项即可,如下所示:
# 设置全局日志级别
logging.level.root=info
@Controller
@ResponseBody //动态页面
public class UserController {
//1. 先得到日志对象(来自 slf4j)
//通过日志工厂的getLogger()方法获取需要打印日志类中的对象
private final static Logger log = LoggerFactory.getLogger(UserController.class);
@RequestMapping("/sayhi")
public void sayHi(){
log.trace("我是trace 微量级比");
log.debug("我是 debug 调试日志");
log.info("我是 info 普通信息日志");
log.warn("我是 warn 警告日志");
log.error("我是 error 错误日志");
// fatal 是导致程序崩坏的(致命bug)程序会自动去打印的
}
}
清除掉配置⽂件中的⽇志设置,观察控制台输⼊的⽇志级别,得到以下结论,⽇志的输出级别,默认是 info
每次都使⽤ LoggerFactory.getLogger(xxx.class) 很繁琐,且每个类都添加⼀遍,也很麻烦,这⾥讲⼀种更好⽤的⽇志输出⽅式,使⽤ lombok 来更简单的输出
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<optional>true</optional>
</dependency>
@Controller
@ResponseBody
@Slf4j
public class UserService {
// Logger log = LoggerFactory.getLogger(UserService.class);
@RequestMapping("/sayhi2")
public void sayHi2(){
log.trace("我是 trace");
log.debug("我是 debug");
log.info("我是 info");
log.warn("我是 warn");
log.error("我是 error");
}
}
注意:使⽤ @Slf4j 注解,在程序中使⽤ log 对象即可输⼊⽇志,并且只能使⽤ log 对象才能输出,这是 lombok 提供的对象名
Lombok 的作⽤如下图所示:
lombok通过@Slf4j在运行时会生成一个private final static Logger log = LoggerFactory.getLogger(UserController.class)
类似这个对象
基本注解
注解 | 作⽤ |
---|---|
@Getter | ⾃动添加 getter ⽅法 |
@Setter | ⾃动添加 setter ⽅法 |
@ToString | ⾃动添加 toString ⽅法 |
@EqualsAndHashCode | ⾃动添加 equals 和 hashCode ⽅法 |
@NoArgsConstructor | ⾃动添加⽆参构造⽅法 |
@AllArgsConstructor | ⾃动添加全属性构造⽅法,顺序按照属性的定义顺序 |
@NonNull | 属性不能为 null |
@RequiredArgsConstructor | ⾃动添加必需属性的构造⽅法,final + @NonNull 的属性为必需 |
组合注解
注解 | 作⽤ |
---|---|
@Data | @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @NoArgsConstructor |
⽇志注解
注解 | 作⽤ |
---|---|
@Slf4j | 添加⼀个名为 log 的⽇志,使⽤ slf4j |
以上的⽇志都是输出在控制台上的,然⽽在⽣产环境上咱们需要将⽇志保存下来,以便出现问题之后追溯问题,把⽇志保存下来的过程就叫做持久化.想要将⽇志进⾏持久化,只需要在配置⽂件中指定⽇志的存储⽬录或者是指定⽇志保存⽂件名之后,Spring Boot 就会将控制台的⽇志写到相应的⽬录或⽂件下了
配置⽇志⽂件的保存路径目录
:
# 设置日志保存的目录(日志存储大小是24kb,大于会默认生成(1)(2)这种类型名文件)
#logging.file.path=D:/Data/
logging.file.path=D:\\Data\\
配置日志文件的⽂件名
:
# 设置日志保存的名称
logging.file.name=D:/Data/spring-boot.log