日志就是发现和定位问题的好方法
除此之外,日志还有其他作用:
在此之前也许会经常使用 System.out.println 来作为日志打印信息,看程序运行到何处出现了问题,但是该方法所包含的信息太少,没有办法将信息持久化,没有办法控制日志等级从而进行信息的过滤…
通过本节将介绍真正的高效日志的输出与存储
日志等级的划分方便了程序员对信息的筛选
trace
:级别最低,意为微量少许debug
:需要调试时打印的信息info
:普通打印信息(默认)warn
:警告信息error
:错误信息,级别较高fatal
:致命的,代码异常导致退出,系统级别的日志级别,无法手动控制trace 和 debug 这两种日志一般使用来记录系统运行状态,通过该日志,我们可以查看操纵的每一步执行的详细过程
info 这种日志用来记录系统正常运行状态,比如系统初始化,请求成功执行…
warn 这种日志表示系统警告,或者说系统可能出现的问题,就目前而言,还不算是错误,如果不及时处理就有变成错误的可能
error 这种日志就表示有错误发生了,说不定已经影响到用户的正常访问了,和 fatal 相比严重程度半径八两,fatal 是服务挂了,error 是没挂但是无法提供正常服务,需要马上被处理掉
fatal 这种日志表示需要立马、火速、马不停蹄进行处理系统错误,这是最严重的日志级别,一般来说,一个进程的声明周期中只记录一次 fatal 级别的日志,就是说当有 fatal 级别的错误发生时,进程遇见无法恢复的错误直接退出
步骤一:获取日志对象
获取日志对象需要使用日志工厂 LoggerFactory
private Logger logger = LoggerFactory.getLogger(UserController.class);
其中括号里的参数是需要获取日志对象的类的类型
,这样就可以知道日志的归属,方便问题的定位
注意:这里的 Logger 类输入org.slf4j
包下的,不可导错包
步骤二:使用日志对象输出内容
通过 logger 变量来输出日志内容,可以发现日志的打印方法有很多,比如我们选择 warn 方法来打印日志,回头控制台打印的就是一个 warn 等级的日志
代码展示
@Controller
@ResponseBody
public class UserController {
private Logger logger = LoggerFactory.getLogger(UserController.class);
@RequestMapping("/login")
public void func1() {
logger.warn("自定义的 warn 等级日志");
}
}
结果显示
我们可以在配置文件中进行日志级别的设置(设置 logging.level
配置项),在默认情况下,日志输出级别为 info,因此项目启动的时候我们只能看见 info 等级及其以上的日志等级的信息
Controller 包下的 UserController 类
@Controller
@ResponseBody
public class UserController {
private Logger logger = LoggerFactory.getLogger(UserController.class);
@RequestMapping("/login")
public void func1() {
logger.trace("trace等级日志");
logger.debug("debug等级日志");
logger.info("info等级日志");
logger.warn("warn等级日志");
logger.error("error等级日志");
}
}
通过一下代码,设置全局日志等级为warn,设置 Controller 包下的内容日志等级为 debug
logging:
level:
root: warn
com:
example:
demo:
Controller: debug
结果显示
从结果中可以看出,启动项目后 Spring 图标下就没有打印日志,访问 127.0.0.1:8080/login 后控制台就打印 debug 日志等级及其以上的日志信息,说明日志等级设置有效
为方便发生问题后进行定位或者追溯问题,就需要将日志保存下来。
可以通过配置文件指定日志的存储目录
或者指定日志保存文件名
,如此,控制台中的日志就会写到设置的目录(文件)下
方法一:配置保存路径
logging:
file:
path: F:\Work
运行完项目后,在指定的路径下多了一个 spring.log 文件
方法二:配置保存文件
logging:
file:
name: F:\Work\spring-demo.log
在 Java 程序中常用的日志框架可以分成两类:
没有具体实现的抽象日志门面框架
,比如 Commons Logging、SLF4J有具体实现的框架
,比如 Log4j 1、Log4j 2、JUL、Logback所谓的门面框架就是提供了一套日志相关功能的接口,本身并没有具体实现,通过调用具体的日志框架来进行日志的记录
门面框架就是日志框架和系统实现之间的桥梁,将系统和具体日志实现之间充分解耦,程序员操作的是门面,根本无需关心门面框架究竟使用的是哪个具体日志实现框架,哪怕哪天突然换了一个具体日志实现框架,也不需要改动任何代码
在 Spring Boot 中选择 SLF4J 作为日志门面
,SLF4J 使用 Logback 作为其实现日志的框架
,这也就是导入的 Logger 类的包是 slf4j的原因
我们发现,写日志的时候都需要在被记录日志的类中进行获取日志对象操作,事实上,通过在类上添加注解 @Slf4j 就可以不用进行之前的麻烦操作了
步骤一:添加 lombok 依赖
可以在项目创建是就添加改依赖,也可以直接粘贴复制
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
如果想向创建项目那样引入依赖,又是社区版 IDEA ,可以先安装一个插 EditStarters
,然后在 pom.xml 文件中右键选择 Generate,选择 Edit Starters,选择 OK,然后就是熟悉的添加依赖的界面
步骤二:使用 @Slf4j 注解输出日志
@Controller
@ResponseBody
@Slf4j
public class UserController {
@RequestMapping("/login")
public void func1() {
log.trace("trace等级日志");
log.debug("debug等级日志");
log.info("info等级日志");
log.warn("warn等级日志");
log.error("error等级日志");
}
}
注意:如果使用 @Slf4j 注解的话,需要使用 log
对象调用各种方法,这是 lomlok提供的对象名
通过加一个注解就能使得获取日志对象操作变得简单,lombok 究竟是如何做到这一点的能,注解的背后又是什么呢?
通过查看目录 target 答案就被揭晓,我们知道 target 实际上就是编译好的字节码文件目录,JVM 最后真正执行的就是字节码文件
这是编译好的字节码文件,可以发现 @Slf4j注解不见了,代码里出现了老版获取日志文件的代码
@Controller
@ResponseBody
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
public UserController() {
}
@RequestMapping({"/login"})
public void func1() {
log.trace("trace等级日志");
log.debug("debug等级日志");
log.info("info等级日志");
log.warn("warn等级日志");
log.error("error等级日志");
}
}
Java 程序运行原理:
编码过程:
lombok 就在编码
时做了手脚,lombok 通过遵循 Java 编译器增强的规范,实现了 Java 源代码在生成字节码的时候的功能增强
lombok 的更多常用注解
基本注解
注解 | 作用 |
---|---|
@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 的日志对象 |