Spring Boot - 日志记录

Spring Boot - 日志记录,第1张

[TOC]

Spring Boot 内部使用的日志框架为 Commons Logging ,但是 Commons Logging 的内部具体实现可以由用户自行指定。

默认已提供了对 Java Utils Logging , Log4J2 和 Logback 日志库的相关配置

无论选择以上哪一个日记库,Spring Boot 都预置了将日志输出到控制台以及可选的文件上。

如果项目配置使用起步依赖(Starters),那么默认情况下,Spring Boot 使用的日记记录库为 Logback。

因此,本文主要介绍在 Spring Boot 中使用 Logback 进行日志记录。

前面已经介绍过,Spring Boot 默认使用的日志框架为 Apache Commons Logging 。

在 Spring 4.x(也即 Spring Boot 1.x )时,我们需要手动进行依赖导入。

但是在 Spring 5.x(也即 Spring Boot 2.x )时,该依赖由 Spring Framework 模块 spring-jcl 提供。

当我们项目使用各种起步依赖(Starter)时, spring-jcl 模块包含在 spring-boot-starter-logging 中,理论上我们需要手动导入该依赖,如下所示:

但实际上我们无需手动导入该起步依赖,因为几乎每一个起步依赖(比如: spring-boot-starter , spring-boot-starter-web ...)都内置了 spring-boot-starter-logging 。

因此,当我们使用起步依赖创建 Spring Boot 项目时,日志功能开箱即可用。

且日记框架内部默认实现采用 Logback。

还有其他一些设置日志级别的方法,这里就不展开阐述了。

更多内容可参考: Log Levels zero-configuration-logging

Spring Boot 支持多种不同的日志系统实现,可以通过导入相应的依赖库从而在运行时激活对应的日志系统,并且可以通过在 classpath 或 logging.config 属性指定一个配置文件,实现自定义系统日志配置。

对于不同的日志系统,Spring Boot 会默认加载的日志配置文件如下表所示:

:Spring Boot 建议我们使用带有 -spring 后缀的作为日志配置文件名称(即相较于使用 logback.xml ,更建议使用 logback-spring.xml )。

如果使用标准配置路径,Spring 无法完全控制日志初始化过程(因为 logback.xml 的加载时间非常早,导致一些扩展功能无法在其内进行配置,而此时使用 logback-spring.xml 即可解决这个问题)。

我们主要关注的是 Logback 的配置文件内容。

要对 Logback 添加配置文件,只需创建 resources/logback-spring.xml ,然后对该文件进行配置即可,其基本配置内容如下:

:日志配置文件路径也可以在 application.properties 中进行指定:

简单对上述 logback-spring.xml 的配置内容进行一些介绍:

更多 Logback 配置文件内容,请参考: A Guide To Logback

可以通过在日志配置文件中使用标签 <springProfile>来创建不同的环境日志配置。

比如,我们可以通过定义生产环境 prod ,测试环境 test 和开发环境 dev 来实现不同的日志输出,如下所示:

然后,启动服务的时候,设置相应环境的 profile 即可。

比如,可以直接通过命令指定运行环境 profile,如下:

Spring Boot 多环境配置内容,可参考: Spring Boot - 多环境配置

可以用spring aop 进行日志管理,下面是我博客中的内容,项目中也是这么用,只是复杂度更高:

第一步:导包,可以参考:spring4 项目搭建

还需要添加AspectJ(java中最流行的aop框架):

1

2

3

4

5

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aspects</artifactId>

<version>4.2.2.RELEASE</version>

</dependency>

第二步:配置bean文件

配置aop可以通过注解,也可以通过配置文件,项目中建议有配置文件,这样便于修改。我先讲解注解方法

配置自动扫描和AspectJ框架

1

2

3

4

<!-- 配置自动扫描的aop包 -->

<context:component-scan base-package="com.spring.aop"/>

<!-- 配置 AspectJ -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

如果aop显示不出来就先xml头文件中导入(我相信大家会导入的,就不多说了)

1

2

xmlns:aop="http://www.springframework.org/schema/aop"

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd

第三步:业务代码,模拟用户的 *** 作

业务代码AopService

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

package com.spring.aop

import org.springframework.stereotype.Service

@Service

public class AopService {

// 用户登入

public void login(){

System.out.println("登入成功")

}

// 用户退出

public void loginOut(){

System.out.println("用户退出系统")

}

// 用户 *** 作

public void writeABlog(){

System.out.println("用户编写博客")

}

// 用户 *** 作

public void deleteABlog(){

System.out.println("用户删除博客")

}

}

切面代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package com.spring.aop

import org.aspectj.lang.JoinPoint

import org.aspectj.lang.annotation.After

import org.aspectj.lang.annotation.Aspect

import org.springframework.stereotype.Component

@Component

@Aspect

public class LogAspect {

@After("execution(public void com.spring.aop.AopService.*(..))")

public void afterMethod(JoinPoint joinPoint) {

String opreate = joinPoint.getSignature().getName()

System.out.println("ITDragon opreate " + opreate)

}

}

测试类:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

package com.spring.aop

import org.junit.Test

import org.springframework.context.ApplicationContext

import org.springframework.context.support.ClassPathXmlApplicationContext

public class AopTest {

private ApplicationContext ctx = null

{

ctx = new ClassPathXmlApplicationContext("beans.xml")

}

@Test

public void aopTest(){

AopService aopService = (AopService) ctx.getBean("aopService")

aopService.login()

aopService.writeABlog()

aopService.deleteABlog()

aopService.loginOut()

}

}

测试结果:

1

2

3

4

5

6

7

8

登入成功

ITDragon opreate login

用户编写博客

ITDragon opreate writeABlog

用户删除博客

ITDragon opreate deleteABlog

用户退出系统

ITDragon opreate loginOut

@Before: 前置通知, 在方法执行之前执行

@After: 后置通知, 在方法执行之后执行

@AfterRunning: 返回通知, 在方法返回结果之后执行,方法必须有返回值。需要添加returning = "result",其中result就是返回结构,

1

@AfterReturning(pointcut="execution(public void com.spring.aop.AopService.*(..))",returning="result")

@AfterThrowing: 异常通知, 在方法抛出异常之后,有异常的时候才执行

1

@AfterThrowing(pointcut="execution(public void com.spring.aop.AopService.*(..))",throwing="e")

@Around: 环绕通知, 围绕着方法执行

@Component:标识该类受spring管理

@Aspect: 标识该类是一个切面

execution(public void com.spring.aop.AopService.*(..)) : 切入点签名表达式,用*号表示所有,也可以指定,括号内两点表示多个变量,也可以指定,还可以用 &&, || , !;以每个execution为一个单位

JoinPoint:连接点,该参数可以访问到更多的数据,还有很多方法可以自己试试。

@Order(n): 切面执行的优先级,n值越小,越优先执行

还有重用切面,等知识我就不过多描述了,毕竟是入门,讲一些常用的就可以了。

使用xml配置文件

1

2

3

4

5

6

7

8

9

package com.spring.aop

import org.aspectj.lang.JoinPoint

public class LogAspect {

public String afterMethod(JoinPoint joinPoint) {

String opreate = joinPoint.getSignature().getName()

System.out.println("ITDragon opreate " + opreate)

return ""

}

}

配置文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

<!-- 扫描切面类 -->

<bean class="com.spring.aop.LogAspect" id="logAspect"></bean>

<!-- aop配置 -->

<aop:config>

<!-- 切点 -->

<aop:pointcut expression="execution(public void com.spring.aop.AopService.*(..))" id="aop"/>

<!-- 切面 : ref 的值是 切面类的id-->

<aop:aspect id="aspect" ref="logAspect">

<!-- 前置方法 : pointcut-ref 的值是 切点的id -->

<aop:before method="afterMethod" pointcut-ref="aop"/>

</aop:aspect>

</aop:config>

还是一样的测试方法,其结果为:

ITDragon opreate login

登入成功

ITDragon opreate writeABlog

用户编写博客

ITDragon opreate deleteABlog

用户删除博客

ITDragon opreate loginOut

用户退出系统

在需要打印日志的地方添加切入点即可。切入点函数名尽量见名知意。这样切面函数才能通用。

Spring Boot默认是使用logback

之前在Spring中使用logback的时候是需要加入slf4j和logback的依赖的

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>1.7.21</version>

</dependency>

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-core</artifactId>

<version>1.1.7</version>

</dependency>

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-classic</artifactId>

<version>1.1.7</version>

</dependency>

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-access</artifactId>

<version>1.1.7</version>

</dependency>

在Spring Boot中默认已经引入了相关的jar包,所以就不需要额外手动引入了~

logback是一款优秀的日志框架,本文就介绍logback

spring boot默认会加载classpath:logback-spring.xml或者classpath:logback-spring.groovy

当然,日志文件的名称也可以采用自定义的方式,此时需要在properties文件中加入以下配置::

logging.config=classpath:logback-winner.xml

注意:不要使用logback这个来命名,否则spring boot将不能完全实例化

项目结构:

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

<!-- 文件输出格式 -->

<property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>

<!-- test文件路径 -->

<property name="TEST_FILE_PATH" value="/opt/winner/logs"/>

<!-- pro文件路径 -->

<property name="PRO_FILE_PATH" value="/opt/winner_0715/logs"/>

<!-- 开发环境 -->

<springProfile name="dev">

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>${PATTERN}</pattern>

</encoder>

</appender>

<root level="INFO">

<appender-ref ref="STDOUT"/>

</root>

</springProfile>

<!-- 测试环境 -->

<springProfile name="test">

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>${PATTERN}</pattern>

</encoder>

</appender>

<!-- ch.qos.logback.core.rolling.RollingFileAppender 文件日志输出 -->

<appender name="TEST-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">

<!--不能有这项配置!!!!!-->

<!--<Encoding>UTF-8</Encoding>-->

<File>${TEST_FILE_PATH}/guide.log</File>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<FileNamePattern>${TEST_FILE_PATH}/guide.%d{yyyy-MM-dd}-%i.log</FileNamePattern>

<MaxHistory>30</MaxHistory>

<TimeBasedFileNamingAndTriggeringPolicy

class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">

<MaxFileSize>10KB</MaxFileSize>

</TimeBasedFileNamingAndTriggeringPolicy>

</rollingPolicy>

<layout class="ch.qos.logback.classic.PatternLayout">

<pattern>${PATTERN}</pattern>

</layout>

</appender>

<root level="info">

<appender-ref ref="STDOUT"/>

<appender-ref ref="TEST-FILE"/>

</root>

</springProfile>

<!-- 生产环境 -->

<springProfile name="prd">

<!-- ch.qos.logback.core.rolling.RollingFileAppender 文件日志输出 -->

<appender name="PROD_FILE"

class="ch.qos.logback.core.rolling.RollingFileAppender">

<!--<Encoding>UTF-8</Encoding>-->

<File>${PRO_FILE_PATH}/guide.log</File>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<FileNamePattern>${PRO_FILE_PATH}/guide.%d{yyyy-MM-dd}-%i.log</FileNamePattern>

<MaxHistory>30</MaxHistory>

<TimeBasedFileNamingAndTriggeringPolicy

class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">

<MaxFileSize>50MB</MaxFileSize>

</TimeBasedFileNamingAndTriggeringPolicy>

</rollingPolicy>

<layout class="ch.qos.logback.classic.PatternLayout">

<pattern>${PATTERN}</pattern>

</layout>

</appender>

<root level="INFO">

<appender-ref ref="PROD_FILE"/>

</root>

</springProfile>

</configuration>

注意,这里的springProfile 的名字与properties文件各个环境的名字要保持一致~

下面简单说一下File和FileNamePattern两个标签的含义:

<File>${TEST_FILE_PATH}/guide.log</File>

<FileNamePattern>${TEST_FILE_PATH}/guide.%d{yyyy-MM-dd}-%i.log</FileNamePattern>

这两项的配置的意思是:

日志首先写入到文件中,当这个文件的大小超过设置的MaxFileSize时,就会把这个文件分割,分割后的文件命名按照来命名,为了方便,我上面将MaxFileSize设置为10KB,实际效果如下:

PS:被其中的一项配置折磨到死:

<Encoding>UTF-8</Encoding>

没错,就是它,在Spring中配置这一项是没错的,但是在Spring Boot中配置这一项不行,原因暂时未知


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/11488710.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-16
下一篇2023-05-16

发表评论

登录后才能评论

评论列表(0条)

    保存