SpringBoot3 整合 Logback 日志框架
1. 默认框架实现
SpringBoot3 默认是使用 SLF4J + Logback 作为默认的日志门面和实现,但也支持其他日志系统,如 Log4j2、JUL (Java Util Logging),
这是通过所谓的日志门面实现的,开发者可以根据自己的需求选择合适的日志实现框架进行配置。
日志门面是指通过引入日志框架的抽象层来统一管理应用程序中的日志输出。
SpringBoot 内置了 Commons Logging、SLF4J 或 jboss-logging 作为日志抽象层(门面),具体的实现可以是 Log4j、JUL、Log4j2 或 Logback。
pom 文件中导入 spring-boot-starter-web
依赖后,会自动导入 spring-boot-starter
依赖,而其又依赖 spring-boot-starter-logging
,
该 spring-boot-starter-logging
即为 SpringBoot 的日志相关配置。因为 SpringBoot 启动的时候就要用到日志。
SpringBoot 启动后,默认日志如下图所示:
如果发现控制台日志没有显示颜色,需要在 application 配置文件中设置 spring.output.ansi.enabled=ALWAYS
spring:
# 配置 ANSI 输出
output:
ansi:
# 有三个可选值:DETECT / ALWAYS / NEVER
# DETECT - 检查终端是否支持 ANSI,是的话就启用彩色输出,默认值
# ALWAYS - 不检查,总是彩色输出
# NEVER - 禁用彩色输出
enabled: ALWAYS
2. 自定义 Logback 日志框架
在 resources 目录下新建 logback.xml
或 logback-spring.xml
作为 Logback 的配置文件。
2.1 常用标签解释
<!--
configuration 根节点
scan
当该属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值: true
scanPeriod
监测 配置文件是否有修改 的时间间隔,如果没有给出时间单位,默认单位是毫秒
当 scan 为 true 时,此属性生效。默认的时间间隔为 "1 minute",或者设为 "60 seconds"
debug
当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback 运行状态。默认值为 false
-->
<configuration scan="" scanPeriod="" debug="">
<!-- property 节点用来定义变量值,可以通过 ${} 来使用变量 -->
<property name="xxx" value="" />
<!--
appender 子节点:负责写日志的组件
name
指定 appender 的名称
class
指定 appender 全限定名,有以下几种:
ConsoleAppender:日志输出到控制台,类名 ch.qos.logback.core.ConsoleAppender
FileAppender:日志输入到文件,类名 ch.qos.logback.core.FileAppender
RollingFileAppender:滚动记录文件,FileAppender 的子类,当符合条件(大小、时间),日志进行切分处理
类名:ch.qos.logback.core.rolling.RollingFileAppender
-->
<appender name="" class="">
<!-- encoder 节点:对日志进行格式化 -->
<encoder>
<!-- 输出格式,${xxx} 括号中引用的是 property 标签的 name 值 -->
<pattern>${xxx}</pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
<!-- 有两个过滤器可供选择:临界值过滤器,级别过滤器。 -->
<!-- 临界值过滤器 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- 输出 DEBUG 级别及以上的日志 -->
<level>DEBUG</level>
</filter>
<!--
级别过滤器
DENY:日志将立即被抛弃不再经过其他过滤器
NEUTRAL:有序列表里的下个过滤器过接着处理日志,该级别既不处理,也不抛弃,日志会被保存下来并在本 appender 被执行
ACCEPT:日志会被立即处理,不再经过剩余过滤器
-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 只保留 ERROR 级别的日志 -->
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 配置日志输出,根据当前 ROOT 级别,日志输出时,级别高于 ROOT 默认的级别时会输出 -->
<root level="INFO">
<!-- 添加 appender 节点到 root 标签下 -->
<appender-ref ref="" />
</root>
</configuration>
2.2 日志输出到控制台
2.2.1 自定义输出
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--
定义变量:输出到控制台的日志格式(彩色输出)
输出值:
%d:表示日期
%thread:表示线程名
%-5level:"-"左对齐,"5" 不满 5 位右补空格
%logger{40}:Java 类名(含包名,这里设定了 40 位,若超过 40 位,包名会精简为类似 a.b.c.JavaBean 形式)
%msg:日志消息
%n:换行符
输出颜色:
%black, %green, %yellow, %blue,
%magenta, %cyan, %white, %gray,
%boldRed, %boldGreen, %boldYellow, %boldBlue,
%boldMagenta, %boldCyan, %boldWhite
%highlight(建议使用在 level 上,亮高显示区分 level 级别)
-->
<property name="log.console.pattern" value="%magenta(%d{yyyy-MM-dd HH:mm:ss:SSS}) [%thread] %highlight([%-5level]) %cyan(%logger{90}) - %msg%n" />
<!-- 配置控制台的 appender -->
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoder 节点:对日志进行格式化 -->
<encoder>
<!-- 输出格式 -->
<pattern>${log.console.pattern}</pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 配置日志输出,所有的 appender 都要挂载到 root 节点下,level 标签指定了所有 appender 的默认日志级别 -->
<root level="INFO">
<appender-ref ref="CONSOLE_APPENDER" />
</root>
</configuration>
2.2.2 使用 SpringBoot 默认格式输出
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 引入 SpringBoot 框架中的默认配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 配置控制台的 appender -->
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoder 节点:对日志进行格式化 -->
<encoder>
<!-- 输出格式,${CONSOLE_LOG_PATTERN} 是在 defaults.xml 中引入的变量 -->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 配置日志输出 -->
<root level="INFO">
<appender-ref ref="CONSOLE_APPENDER" />
</root>
</configuration>
IDEA 启动后,可能日志不是彩色的,需要在 application 配置文件中 添加 spring.output.ansi.enabled = ALWAYS
spring:
# 配置 ANSI 输出
output:
ansi:
# 有三个可选值:DETECT / ALWAYS / NEVER
# DETECT - 检查终端是否支持 ANSI,是的话就启用彩色输出,默认值
# ALWAYS - 不检查,总是彩色输出
# NEVER - 禁用彩色输出
enabled: ALWAYS
2.3 日志输出到文件
2.3.1 自定义输出
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--
定义变量:输出到文件的日志格式
输出值:
%d:表示日期
%thread:表示线程名
%-5level:"-"左对齐,"5" 不满 5 位右补空格
%logger{40}:Java 类名(含包名,这里设定了 40 位,若超过 40 位,包名会精简为类似 a.b.c.JavaBean 形式)
%msg:日志消息
%n:换行符
-->
<property name="log.file.pattern" value="%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] [%-5level] %logger{90} - %msg%n" />
<!-- 日志文件存储目录 -->
<property name="log.file.path" value="D:/xxx/UniApp-Shop/xxx/system_logback" />
<!-- 滚动输出日志到文件 -->
<appender name="ROLLING_FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径 -->
<file>${log.file.path}/system.log</file>
<!-- encoder 节点:对日志进行格式化 -->
<encoder>
<pattern>${log.file.pattern}</pattern>
<charset>UTF-8</charset>
</encoder>
<!--
设置滚动策略,用于配置文件大小限制、保留天数、文件名格式
TimeBasedRollingPolicy: 基于时间滚动策略
SizeAndTimeBasedRollingPolicy: 基于大小和时间的滚动策略(对时间滚动策略的补充)
FixedWindowRollingPolicy: 基于固定窗口的滚动策略
-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 文件命名格式,%d{yyyy-MM-dd} 表示日期格式,%i 表示文件索引,文件的名字会根据 fileNamePattern 的值,每隔一段时间改变一次 -->
<fileNamePattern>${log.file.path}/system-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 每个日志文件的大小限制,建议 10MB 起才能有效果 -->
<maxFileSize>2MB</maxFileSize>
<!-- 设置保留的日志文件的最大数量,超出数量就删除旧文件。如果设置每天滚动,则下面的 3 代表最多保留 3 天 -->
<maxHistory>3</maxHistory>
<!-- 文件总大小 -->
<totalSizeCap>10MB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 将各 appender 挂载到 root 节点下,根据当前 ROOT 级别,日志输出时,级别高于 ROOT 默认的级别时会输出 -->
<root level="DEBUG">
<appender-ref ref="ROLLING_FILE_APPENDER" />
</root>
</configuration>
2.3.2 使用 SpringBoot 默认格式输出
参照:2.2.2 使用 SpringBoot 默认格式输出
2.4 过滤器的使用
2.4.1 临界值过滤器 ThresholdFilter
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义日志输出到控制台的格式(含颜色) -->
<property name="log.console.pattern" value="%magenta(%d{yyyy-MM-dd HH:mm:ss:SSS}) [%thread] %highlight([%-5level]) %cyan(%logger{90}) - %msg%n" />
<!-- 输出日志到控制台 -->
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.console.pattern}</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 临界值过滤器 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- 输出 DEBUG 级别及以上的日志,即,输出:DEBUG / INFO / WARN / ERROR -->
<level>DEBUG</level>
</filter>
</appender>
<!-- 将各 appender 挂载到 root 节点下,根据当前 ROOT 级别,日志输出时,级别高于 ROOT 默认的级别时会输出 -->
<root level="DEBUG">
<appender-ref ref="CONSOLE_APPENDER" />
</root>
</configuration>
2.4.2 级别过滤器 LevelFilter
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义日志输出到控制台的格式(含颜色) -->
<property name="log.console.pattern" value="%magenta(%d{yyyy-MM-dd HH:mm:ss:SSS}) [%thread] %highlight([%-5level]) %cyan(%logger{90}) - %msg%n" />
<!-- 输出日志到控制台 -->
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.console.pattern}</pattern>
<charset>UTF-8</charset>
</encoder>
<!--
级别过滤器
DENY:日志将立即被抛弃不再经过其他过滤器
NEUTRAL:有序列表里的下个过滤器过接着处理日志,该级别既不处理,也不抛弃,日志会被保存下来并在本 appender 被执行
ACCEPT:日志会被立即处理,不再经过剩余过滤器
-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 只保留 ERROR 级别的日志 -->
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 将各 appender 挂载到 root 节点下,根据当前 ROOT 级别,日志输出时,级别高于 ROOT 默认的级别时会输出 -->
<root level="DEBUG">
<appender-ref ref="CONSOLE_APPENDER" />
</root>
</configuration>
2.5 logger 标签指定具体包或类的日志级别
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义日志输出到控制台的格式(含颜色) -->
<property name="log.console.pattern" value="%magenta(%d{yyyy-MM-dd HH:mm:ss:SSS}) [%thread] %highlight([%-5level]) %cyan(%logger{90}) - %msg%n" />
<!-- 输出日志到控制台 -->
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.console.pattern}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--
logger 标签:用来设置某一个包或者具体的某一个类的日志打印级别
name 属性:用来指定受此 logger 约束的某一个包或某一个类
level 属性:用来设置打印级别,若为设置此属性,当前 logger 将会继承上级(root)的级别
additivity 属性:是否向上级传递打印信息,默认 true
-->
<!--
控制 org.springframework 包下的所有类的 INFO 级别及以上的日志打印
没有设置 appender,此 logger 本身不打印任何信息
没有设置 additivity,默认 true,此 logger 的日志信息向上级(ROOT)传递
ROOT 接到下级传递的信息,交给挂载的 appender-ref(有三个)进行打印输出
-->
<logger name="org.springframework" level="INFO" />
<!-- 将各 appender 挂载到 root 节点下,根据当前 ROOT 级别,日志输出时,级别高于 ROOT 默认的级别时会输出 -->
<root level="DEBUG">
<appender-ref ref="CONSOLE_APPENDER" />
</root>
</configuration>
2.6 从配置文件获取全局属性值
使用 <springProperty scope="context" name="" source="" defaultValue="" />
标签从 application 文件中获取全局配置。
- name 属性是在 logback.xml 中引用的名称,对应的值就为 source 或 defaultValue 属性的值
- source 属性是 application 配置文件中的 变量名(key),通过这个变量名找到 value
- defaultValue 属性:如果没有找到 source 属性的话就用 defaultValue 的值
注意:
(1) 如果是 从配置文件获取全局属性值 的话,那么 logback 的配置文件名称应为“logback-spring.xml”
(2) logback 的配置文件 关于 springProperty 标签会报红色,是因为 configuration
标签引用了 xsd 文件,不影响可忽略
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<property name="log.file.pattern" value="%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] [%-5level] %logger{90} - %msg%n" />
<!-- 日志文件存储目录 -->
<!-- <property name="log.file.path" value="D:/xxx/UniApp-Shop/xxx/system_logback" /> -->
<!--
从 application 配置文件取得 logback.path 的值作为变量,如果没有找到该属性的话就用 defaultValue 的值
在 Windows 上,可以通过打开 Windows 资源管理器,然后在地址栏中键入 %userprofile% 来找到 user.home
在 Mac 上,可以通过打开终端应用程序,然后输入 echo $HOME 命令来找到 user.home
在 Linux 上,可以通过打开终端应用程序,然后输入 echo $HOME 命令来找到 user.home
使用方式和 property 标签一样,使用 ${} 来引用
-->
<springProperty scope="context" name="log.file.path" source="logback.path" defaultValue="${user.home}/ShopSystem/log" />
<!-- 滚动输出日志到文件 -->
<appender name="ROLLING_FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径 -->
<file>${log.file.path}/system.log</file>
<!-- encoder 节点:对日志进行格式化 -->
<encoder>
<pattern>${log.file.pattern}</pattern>
<charset>UTF-8</charset>
</encoder>
<!--
设置滚动策略,用于配置文件大小限制、保留天数、文件名格式
TimeBasedRollingPolicy: 基于时间滚动策略
SizeAndTimeBasedRollingPolicy: 基于大小和时间的滚动策略(对时间滚动策略的补充)
FixedWindowRollingPolicy: 基于固定窗口的滚动策略
-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 文件命名格式,%d{yyyy-MM-dd} 表示日期格式,%i 表示文件索引,文件的名字会根据 fileNamePattern 的值,每隔一段时间改变一次 -->
<fileNamePattern>${log.file.path}/system-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 每个日志文件的大小限制,建议 10MB 起才能有效果 -->
<maxFileSize>2MB</maxFileSize>
<!-- 设置保留的日志文件的最大数量,超出数量就删除旧文件。如果设置每天滚动,则下面的 3 代表最多保留 3 天 -->
<maxHistory>3</maxHistory>
<!-- 文件总大小 -->
<totalSizeCap>10MB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 将各 appender 挂载到 root 节点下,根据当前 ROOT 级别,日志输出时,级别高于 ROOT 默认的级别时会输出 -->
<root level="DEBUG">
<appender-ref ref="ROLLING_FILE_APPENDER" />
</root>
</configuration>
application.yaml
# logback.xml 中日志文件的配置项
logback:
# 日志文件存储目录
path: D:/xxx/UniApp-Shop/xxx/system_logback
3. logback 配置文件示例
根据需要自行修改(后续可能进行补充)
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定义日志输出到控制台的格式 -->
<property name="log.console.pattern" value="%magenta(%d{yyyy-MM-dd HH:mm:ss:SSS}) [%thread] %highlight([%-5level]) %cyan(%logger{90}) - %msg%n" />
<!-- 定义日志输出到文件中的格式 -->
<property name="log.file.pattern" value="%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] [%-5level] %logger{90} - %msg%n" />
<!-- 日志文件存储目录(从 application 配置文件取得) -->
<springProperty scope="context" name="file.path" source="logback.path" defaultValue="${user.home}/ShopSystem/log" />
<!-- 输出 info 级别及以上的日志文件名-前缀(从 application 配置文件取得) -->
<springProperty scope="context" name="file.name.info.prefix" source="logback.file-name.info.prefix" defaultValue="system" />
<!-- 输出 info 级别及以上的日志文件名-后缀(从 application 配置文件取得) -->
<springProperty scope="context" name="file.name.info.suffix" source="logback.file-name.info.suffix" defaultValue="log" />
<!-- 输出 error 级别的日志文件名-前缀(从 application 配置文件取得) -->
<springProperty scope="context" name="file.name.error.prefix" source="logback.file-name.error.prefix" defaultValue="system.error" />
<!-- 输出 error 级别的日志文件名-后缀(从 application 配置文件取得) -->
<springProperty scope="context" name="file.name.error.suffix" source="logback.file-name.error.suffix" defaultValue="log" />
<!-- 输出日志到控制台 -->
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.console.pattern}</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 输出 DEBUG 级别及以上的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<!-- 滚动输出 INFO 级别及以上的日志到文件 -->
<appender name="ROLLING_FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${file.path}/${file.name.info.prefix}.${file.name.info.suffix}</file>
<encoder>
<pattern>${log.file.pattern}</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 设置滚动策略,基于大小和时间的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${file.path}/${file.name.info.prefix}.%d{yyyy-MM-dd}.%i.${file.name.info.suffix}</fileNamePattern>
<maxFileSize>2MB</maxFileSize>
<maxHistory>3</maxHistory>
<totalSizeCap>10MB</totalSizeCap>
</rollingPolicy>
<!-- 输出 INFO 级别及以上的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!-- 滚动输出 ERROR 级别的日志到文件 -->
<appender name="ROLLING_FILE_ERROR_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${file.path}/${file.name.error.prefix}.${file.name.error.suffix}</file>
<encoder>
<pattern>${log.file.pattern}</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 设置滚动策略,基于大小和时间的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${file.path}/${file.name.error.prefix}.%d{yyyy-MM-dd}.%i.${file.name.error.suffix}</fileNamePattern>
<maxFileSize>2MB</maxFileSize>
<maxHistory>3</maxHistory>
<totalSizeCap>10MB</totalSizeCap>
</rollingPolicy>
<!-- 只保留 ERROR 级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 控制 org.springframework 包下的所有类的 INFO 级别及以上的日志打印 -->
<logger name="org.springframework" level="INFO" />
<!-- 控制 _org.springframework 包下的所有类的 INFO 级别及以上的日志打印 -->
<logger name="_org.springframework" level="INFO" />
<!-- 将各 appender 挂载到 root 节点下 -->
<root level="DEBUG">
<appender-ref ref="CONSOLE_APPENDER" />
<appender-ref ref="ROLLING_FILE_APPENDER" />
<appender-ref ref="ROLLING_FILE_ERROR_APPENDER" />
</root>
</configuration>
application.yaml
# logback.xml 中日志文件的配置项
logback:
# 日志文件存储目录
path: D:/xxx/UniApp-Shop/xxx/system_logback
# 文件名
file-name:
# 输出 info 级别及以上的日志文件名
info:
# 文件名前缀
prefix: system
# 文件名后缀
suffix: log
# 输出 error 级别的日志文件名
error:
# 文件名前缀
prefix: system.error
# 文件名后缀
suffix: log
4. 在 IDEA 中设置 logback.xml 的自动提示功能
参考:https://blog.csdn.net/adley_app/article/details/131365159
- 方式1
在 configuration 标签中添加 xmlns、xmlns:xsi 和 xsi:schemaLocation 属性
<configuration xmlns="http://ch.qos.logback/xml/ns/logback"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ch.qos.logback/xml/ns/logback
https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
选择 https://raw.githubxxx/xxx/logback.xsd
,点击 fetch external resource(提取外部资源),自动下载 xsd 文件
- 方式2
若无法下载,则在 resource 目录下创建 logback.xsd 文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--
logback.xml schema,
https://github.com/enricopulatzo/logback-XSD
https://github.com/nkatsar/logback-XSD
-->
<xsd:schema targetNamespace="http://ch.qos.logback/xml/ns/logback"
xmlns="http://ch.qos.logback/xml/ns/logback"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="1.1">
<xsd:element name="configuration" type="Configuration"/>
<xsd:element name="included" type="Configuration"/>
<xsd:complexType name="Configuration">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="shutdownHook" minOccurs="0" maxOccurs="1" type="ShutdownHook"/>
<xsd:element name="statusListener" minOccurs="0" maxOccurs="unbounded" type="StatusListener"/>
<xsd:element name="contextListener" minOccurs="0" maxOccurs="unbounded" type="ContextListener"/>
<xsd:element name="jmxConfigurator" minOccurs="0" maxOccurs="1" type="JmxConfigurator"/>
<xsd:element name="conversionRule" minOccurs="0" maxOccurs="unbounded" type="ConversionRule"/>
<xsd:element name="include" minOccurs="0" maxOccurs="unbounded" type="Include"/>
<xsd:element name="contextName" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="define" minOccurs="0" maxOccurs="unbounded" type="Define"/>
<xsd:element name="timestamp" minOccurs="0" maxOccurs="1" type="Timestamp"/>
<xsd:element name="if" minOccurs="0" maxOccurs="unbounded" type="If"/>
<xsd:element name="property" minOccurs="0" maxOccurs="unbounded" type="Property"/>
<xsd:element name="appender" minOccurs="0" maxOccurs="unbounded" type="Appender"/>
<xsd:element name="logger" minOccurs="0" maxOccurs="unbounded" type="Logger"/>
<xsd:element name="root" minOccurs="0" maxOccurs="1" type="Root"/>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attribute name="debug" type="xsd:boolean" use="optional"/>
<xsd:attribute name="scan" type="xsd:boolean" use="optional" default="false"/>
<xsd:attribute name="scanPeriod" type="xsd:string" use="optional" default="1 minute"/>
<xsd:attribute name="packagingData" type="xsd:boolean" use="optional" default="false"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="ShutdownHook">
<xsd:attribute name="class" type="xsd:string" use="optional"
default="ch.qos.logback.core.hook.DelayingShutdownHook"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="ConversionRule">
<xsd:attribute name="conversionWord" type="xsd:string"/>
<xsd:attribute name="converterClass" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="StatusListener">
<xsd:attribute name="class" type="xsd:string" use="optional"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="ContextListener">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="resetJUL" type="xsd:boolean"/>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attribute name="class" type="xsd:string"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="Include">
<xsd:attribute name="file" use="optional" type="xsd:string"/>
<xsd:attribute name="resource" use="optional" type="xsd:string"/>
<xsd:attribute name="url" use="optional" type="xsd:string"/>
<xsd:attribute name="optional" use="optional" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="Define">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="Timestamp">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="key" type="xsd:string" use="optional"/>
<xsd:attribute name="datePattern" type="xsd:string" use="optional"/>
<xsd:attribute name="timeReference" type="xsd:string" use="optional"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="RollingPolicy">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="fileNamePattern" minOccurs="1" maxOccurs="1" type="xsd:string"/>
<xsd:element name="maxHistory" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="minIndex" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="maxIndex" minOccurs="0" maxOccurs="1" type="xsd:int"/>
<xsd:element name="timeBasedFileNamingAndTriggeringPolicy" minOccurs="0" maxOccurs="1" type="TriggeringPolicy"/>
<xsd:element name="cleanHistoryOnStart" minOccurs="0" maxOccurs="1" type="xsd:boolean"/>
<xsd:element name="maxFileSize" minOccurs="0" maxOccurs="1" type="FileSize"/>
<xsd:element name="totalSizeCap" minOccurs="0" maxOccurs="1" type="FileSize"/>
</xsd:choice>
<xsd:attribute name="class" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:simpleType name="FileSize">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[1-9][0-9]*(KB|MB|GB)?"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="TriggeringPolicy">
<xsd:sequence>
<xsd:element name="maxFileSize" minOccurs="0" maxOccurs="1" type="FileSize"/>
</xsd:sequence>
<xsd:attribute name="class" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="If">
<xsd:choice maxOccurs="unbounded">
<xsd:element type="Configuration" name="then"/>
<xsd:element type="Configuration" name="else"/>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attribute name="condition" type="xsd:string"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="Property">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="scope" type="xsd:string" use="optional"/>
<xsd:attribute name="name" type="xsd:string" use="optional"/>
<xsd:attribute name="value" type="xsd:string" use="optional"/>
<xsd:attribute name="file" type="xsd:string" use="optional"/>
<xsd:attribute name="resource" type="xsd:string" use="optional"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="Appender">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="target" minOccurs="0" maxOccurs="1" type="Target"/>
<xsd:element name="file" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:element name="withJansi" minOccurs="0" maxOccurs="1" type="xsd:boolean"/>
<xsd:element name="encoder" minOccurs="0" maxOccurs="1" type="Encoder"/>
<xsd:element name="filter" minOccurs="0" maxOccurs="1" type="Filter"/>
<xsd:element name="append" minOccurs="0" maxOccurs="1" type="xsd:boolean"/>
<xsd:element name="prudent" minOccurs="0" maxOccurs="1" type="xsd:boolean"/>
<xsd:element name="layout" minOccurs="0" maxOccurs="1" type="Layout"/>
<xsd:element name="rollingPolicy" minOccurs="0" maxOccurs="1" type="RollingPolicy"/>
<xsd:element name="connectionSource" minOccurs="0" maxOccurs="1" type="ConnectionSource"/>
<xsd:element name="triggeringPolicy" minOccurs="0" maxOccurs="1" type="TriggeringPolicy"/>
<xsd:element name="appender-ref" minOccurs="0" maxOccurs="1" type="AppenderRef"/>
<xsd:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="class" type="xsd:string" use="required"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:simpleType name="Target">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="System.out"/>
<xsd:enumeration value="System.err"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="Filter">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="level" minOccurs="0" maxOccurs="unbounded" type="LoggerLevel"/>
<xsd:element name="onMatch" minOccurs="0" maxOccurs="unbounded" type="MatchValue"/>
<xsd:element name="onMismatch" minOccurs="0" maxOccurs="unbounded" type="MatchValue"/>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attribute name="class" type="xsd:string" use="optional"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:simpleType name="MatchValue">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="ACCEPT"/>
<xsd:enumeration value="DENY"/>
<xsd:enumeration value="NEUTRAL"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="Layout">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="pattern" minOccurs="0" maxOccurs="1" type="xsd:string"/>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attribute name="class" type="xsd:string" use="optional"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="Logger">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="appender-ref" minOccurs="0" maxOccurs="unbounded" type="AppenderRef"/>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="level" type="LoggerLevel" use="optional"/>
<xsd:attribute name="additivity" type="xsd:boolean" use="optional" default="true"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="Encoder">
<xsd:choice maxOccurs="unbounded">
<xsd:element name="charset" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<xsd:element name="immediateFlush" type="xsd:boolean" minOccurs="0" maxOccurs="1"/>
<xsd:element name="layout" minOccurs="0" maxOccurs="1" type="Layout"/>
<xsd:element name="outputPatternAsHeader" type="xsd:boolean" minOccurs="0" maxOccurs="1"/>
<xsd:element name="pattern" type="xsd:string" minOccurs="0" maxOccurs="1"/>
</xsd:choice>
<xsd:attribute name="class" type="xsd:string" use="optional"
default="ch.qos.logback.classic.encoder.PatternLayoutEncoder"
/>
</xsd:complexType>
<xsd:complexType name="Root">
<xsd:sequence>
<xsd:element name="appender-ref" minOccurs="0" maxOccurs="unbounded" type="AppenderRef"/>
</xsd:sequence>
<xsd:attribute name="level" use="required" type="LoggerLevel"/>
<xsd:anyAttribute/>
</xsd:complexType>
<xsd:complexType name="AppenderRef">
<xsd:attribute name="ref" type="xsd:string"/>
</xsd:complexType>
<xsd:simpleType name="LoggerLevel">
<xsd:union>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="OFF"/>
<xsd:enumeration value="off"/>
<xsd:enumeration value="ALL"/>
<xsd:enumeration value="all"/>
<xsd:enumeration value="INHERITED"/>
<xsd:enumeration value="inherited"/>
<xsd:enumeration value="NULL"/>
<xsd:enumeration value="null"/>
<xsd:enumeration value="ERROR"/>
<xsd:enumeration value="error"/>
<xsd:enumeration value="WARN"/>
<xsd:enumeration value="warn"/>
<xsd:enumeration value="INFO"/>
<xsd:enumeration value="info"/>
<xsd:enumeration value="DEBUG"/>
<xsd:enumeration value="debug"/>
<xsd:enumeration value="TRACE"/>
<xsd:enumeration value="trace"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="($\{.+:-)?[Oo][Ff]{2}\}?"/>
<xsd:pattern value="($\{.+:-)?[Aa][Ll]{2}\}?"/>
<xsd:pattern value="($\{.+:-)?[Ii][Nn][Hh][Ee][Rr][Ii][Tt][Ee][Dd]\}?"/>
<xsd:pattern value="($\{.+:-)?[Nn][Uu][Ll]{2}\}?"/>
<xsd:pattern value="($\{.+:-)?[Ee][Rr]{2}[Oo][Rr]\}?"/>
<xsd:pattern value="($\{.+:-)?[Ww][Aa][Rr][Nn]\}?"/>
<xsd:pattern value="($\{.+:-)?[Ii][Nn][Ff][Oo]\}?"/>
<xsd:pattern value="($\{.+:-)?[Dd][Ee][Bb][Uu][Gg]\}?"/>
<xsd:pattern value="($\{.+:-)?[Tt][Rr][Aa][Cc][Ee]\}?"/>
<xsd:pattern value="\$\{.+\}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:union>
</xsd:simpleType>
<xsd:complexType name="JmxConfigurator"/>
<xsd:complexType name="ConnectionSource">
<xsd:sequence>
<xsd:element name="driverClass" type="xsd:string"/>
<xsd:element name="url" type="xsd:string"/>
<xsd:element name="user" type="xsd:string"/>
<xsd:element name="password" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="class" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:schema>
- 方式3
若不想在 resource 目录下创建 xsd 文件,可将 xsd 文件放到本地。
在 方式1 中自动下载的 xsd 一般放在 C:\Users\xxx\AppData\Local\JetBrains\IdeaIC2024.1\extResources 目录下,
File > Settings... > Languages & Frameworks > Schemas and DTDs > 在右侧 "External schemas and DTDs" 区域添加关联
URI: xml 文件中引用的 xsd 地址,即,https://raw.githxxx/logback.xsd
File: 本地存放 xsd 的路径
参考:
https://www.cnblogs.com/gavincoder/p/10091757.html
https://www.dandelioncloud.cn/article/details/1530032828347858945
https://cloud.tencent.com/developer/article/1733197
https://www.cnblogs.com/wlovet/p/17517263.html
https://www.cnblogs.com/hefeng2014/p/17973169
https://blog.csdn.net/qq_21259459/article/details/106517209
以上!
2024年7月7日 19:28
标签:UTF,整合,logback,SpringBoot3,file,spring,日志,Logback,log From: https://www.cnblogs.com/wuze-blog/p/18287445