【Spring Boot】Spring Boot 日志文件详解

本文阅读 11 分钟
首页 代码,Java 正文

1.1 日志是什么?

日志 就是介绍一个过程的详细记录,项目中的日志 就是项目开发过程的详细记录,代码里的日志 就是程序员记录某个开发过程的详细情况。

代码里的日志是项目中非常重要的组成成分,它的详细程度能够决定系统是否容易维护。

1.2 日志的作用

  • 发现问题和定位问题。
  • 记录用户的登录日志,方便大数据分析用户信息。
  • 记录系统的操作日志,方便恢复数据和定位操作人。
  • 记录程序执行的时间,方便为以后优化程序提供数据支持。

1.3 日志格式说明

Spring Boot 项目在启动时默认就有日志输出,如下图所示:img

其中日志的格式包含了六个部分,分别是:

  • 日志打印的时间
  • 日志级别
  • 线程ID
  • 线程名称
  • 执行的类型
  • 日志信息

Java 中日志的演化历史:

在 Java 中,最先出现的日志是 Apache 开源社区中的 log4j。后来 Java 开发主体 Sun 公司在 jdk1.4 中增加了 JUL(java.util.logging 包下)日志的实现,由于不同的日志工具之间没有关联,导致替换和统一日志工具变得非常棘手,使得 Java 开发局面比较混乱。

为了解决这个问题,Apache 开源社区提供了一个日志框架 commons-logging 作为日志的抽象,commons-logging 对各种日志接口进行抽象,抽象出了一个接口层,对每个日志实现都进行适配,出色的兼容了主流的日志实现,包括 log4j 和 JUL 等。

后来 log4j 的作者实现了一个更加优雅的日志框架 SLF4J,并为 SLF4J 实现了一个 logback 的具体实现。最后又将 log4j 改造成了新的 log4j2,并让其能够支持 commons-logging 和 SLF4J。

Java 日志体系图:

img

通过上述 Java 日志演化的历史和体系图,我们可以了解到:

  • commons-logging 和 SLF4J 是日志的接口,而没有提供实现。
  • log4j 1/2、JUL、logback 是日志的具体实现。

为什么需要日志接口?

接口用于定制规范,可以有多个实现,使用时是面向接口的(导入的包都是 SLF4J 的包或者是 commons-logging 的包,而不是具体某个日志框架中的包),即直接和接口交互,不直接使用实现,所以当需要更换实现的时候,直接更换就可以了,而不用更改代码中的日志相关代码。

3.1 日志级别的作用

日志的级别能够筛选符合目标的日志信息。对日志进行分级,能够过滤出自己想看的信息,比如设置日志级别为 error,那么就可以只看到程序的报错日志,而忽略普通的调试日志和业务日志等,节省了开发者的信息筛选时间。

3.2 日志级别的分类

  • 默认日志级别为 info。
  • 程序会打印高于或等于当前日志级别的日志。

3.3 日志级别的设置

在项目的配置文件中设置 logging.level 就可以设置日志级别。

在 application.properties 中设置日志级别:

# 设置所有目的的日志级别为 error
logging.level.root=error

# 设置 com.example.demo.controller 目录下的日志级别为 debug
logging.level.com.demo.controller=debug

在 application.yml 中设置日志级别:

logging:
  server:
    root: error # 设置所有目的的日志级别为 error
    com:
      example:
        demo:
          controller: debug # 设置 com.example.demo.controller 目录下的日志级别为 debug

4.1 在程序中得到日志对象

在程序中,日志对象为 Logger,获取日志对象需要使用日志工厂 LoggerFactory 的 getLogger 方法,代码如下所示:

// 1. 得到日志对象
private Logger logger = LoggerFactory.getLogger(LoginController.class);

这里推荐使用 SLF4J + logback 或者 SLF4J + log4j2,而 Spring Boot 中内置了日志框架 SLF4J,所以在使用的时可以直接使用。上述使用的是 SLF4J 日志框架,所以 Logger 对象是属于 org.slf4j 包下的,导包的时候不要导错!

img

4.2 使用日志对象打印日志

在要执行的类中,使用日志对象提供的 API 进行日志打印。代码如下所示:

@Controller
@ResponseBody
public class LoginController { 

    // 1. 得到日志对象
    private Logger logger = LoggerFactory.getLogger(LoginController.class);

    @RequestMapping("/login")
    public String login(String username, String password) { 
        // 2. 使用日志打印
        logger.trace("日志级别 trace");
        logger.debug("日志级别 debug");
        logger.info("日志级别 info");
        logger.warn("日志级别 warn");
        logger.error("日志级别 error");

        String result = "未知错误!";
        if (StringUtils.hasLength(username) && StringUtils.hasLength(password)
                && username.equals("admin") && password.equals("1234")) { 
            result = "登录成功!";
        } else { 
            result = "登陆失败!用户名或密码错误!";
        }
        return result;
    }
}

img

上述代码中,由于没有主动设置日志级别,默认日志级别为 info。因为程序只会打印高于或等于当前日志级别的日志,因此并不会打印 trace 的日志信息。而

以上的⽇志都是输出在控制台上的,然⽽在⽣产环境上需要将⽇志保存下来,以便出现问题之后追溯问题,把⽇志保存下来的过程就叫做持久化。

想要将⽇志进⾏持久化,只需要在配置⽂件中指定⽇志的存储⽬录或者是指定⽇志保存⽂件名之后,Spring Boot 就会将控制台的⽇志写到相应的⽬录或⽂件下了。

配置日志文件的保存路径:

# 设置日志文件的保存路径
logging:
  file:
    path: C:\Users\bbbbbge\Desktop

img

配置日志文件的文件名:

# 设置日志文件的文件名
logging:
  file:
    # path: C:\Users\bbbbbge\Desktop
    name: C:\Users\bbb bbge\Desktop\spring-boot.log

img

6.1 lombok 介绍

lombok 是一个 Java 库,能自动插入编辑器并构建工具,简化 Java 开发。通过添加注解的方式,不需要为类编写getter、setter、equals、toString 等方法,同时可以自动创建日志变量。

使用 lombok 前需要在项目中引入其依赖:

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

6.2 lombok 注解说明

6.3 使用 @Slf4j 注解打印日志

通过 lombok 中的 @Slf4j 注解,可以自动添加一个名为 log 的日志对象对象,使得我们不用每次再通过 LoggerFactory.getLogger(xxx.class) 代码的方法去创建一个日志对象。

示例代码:

@Controller
@ResponseBody
@Slf4j
public class LoginController { 

    @RequestMapping("/login")
    public String login(String username, String password) { 
        // 2. 使用日志打印
        log.trace("日志级别 trace");
        log.debug("日志级别 debug");
        log.info("日志级别 info");
        log.warn("日志级别 warn");
        log.error("日志级别 error");

        String result = "未知错误!";
        if (StringUtils.hasLength(username) && StringUtils.hasLength(password)
                && username.equals("admin") && password.equals("1234")) { 
            result = "登录成功!";
        } else { 
            result = "登陆失败!用户名或密码错误!";
        }
        return result;
    }
}

img

6.4 lombok 工作原理

通过 lombok,我们只需要添加相应的注解,就能够省略对应的代码。那么 lombok 为何能做到这么神奇的事呢?

我们编写的代码是 Java 文件,而编写完成后需要通过编码生成字节码文件,JVM 通过加载和运行字节码文件才能得到程序的结果。

我们可以观察和比较一下上述代码的源文件和字节码文件中代码的差别:

img

我们发现,源代码中我们使用的 @Slf4j 注解在字节码文件中消失了,反而字节码文件中多出了使用LoggerFactory.getLogger(xxx.class) 获取日志对象的一行代码,并且创建的日志对象变量叫 log。因此我们可以猜测出 lombok 中的注解在 Java 代码编译的时候能够转换成对应的代码,使得最终的字节码文件能够正常运行。

lombok 实际上是通过 jdk 实现的 JSR 269: Pluggable Annotation Processing API (编译期的注解处理器),在编译期时把 lombok 的注解转换成 Java 代码,相当于在编译期对代码进行了修改。

我们知道 Java 源文件是通过 javac 编译器来编译成字节码文件的,而 javac 编译器的编译过程大致可以分为1个准备和3个处理过程:

  1. 初始化插入式注解处理器
  2. 解析与填充符号表
  3. 插入式注解处理器的注解处理
  4. 分析与字节码生成

而 lombok 就是实现了插入式注解处理器,通过插入式注解处理器,就可以读取、修改、添加抽象语法树中的任意元素。因此,在 javac 编译的过程中,它产生的作用流程具体如下:

  1. javac 对源代码进行分析,生成了一棵抽象语法树(AST)。
  2. 运行过程中调用实现了插入式注解处理器的 lombok 程序。
  3. lombok 对 AST 进行处理,找到相关注解所在的类对应的语法树,然后修改 AST,增加相应的代码定义的语法树的节点。
  4. javac 使用修改后的抽象语法树生成字节码文件。

6.5 lombok 的优缺点

优点:

  • 能通过注解的形式自动生成构造器、getter、setter、equals、hashcode、toString 等方法,提高了一定的开发效率。
  • 让代码变得简洁,不用过多的去关注相应的方法。
  • 属性做修改时,也简化了维护为这些属性所生成的 getter、setter 方法等。

缺点:

  • 不支持多种参数构造器的重载。
  • 虽然省去了手动创建 getter、setter 等方法编写的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度。
  • 由于是编译器生成的代码,所以不能够调试。 码文件。
本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://t4dmw.blog.csdn.net/article/details/124763275
-- 展开阅读全文 --
BUUCTF Web [极客大挑战 2019]Knife
« 上一篇 06-24
安全面试之XSS(跨站脚本攻击)
下一篇 » 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复