logback弃用SizeAndTimeBasedFNATP

在尝试把Spring Boot版本从3.3.0升级到3.4.0时启动报错。报错如下:

ERROR in ch.qos.logback.core.model.processor.ImplicitModelHandler - Could not create component [timeBasedFileNamingAndTriggeringPolicy] of type [ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP] java.lang.ClassNotFoundException: ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP

原因是在日志配置中使用了SizeAndTimeBasedFNATP,该类在logback1.5.8版本被重命名,而spring boot3.4.0的内置logback版本是1.5.12,因此启动时会报错。修改方法有两个,一个是移除spring boot web中自带的logback包,引入1.5.8以下的logback,另一个就是使用SizeAndTimeBasedFileNamingAndTriggeringPolicy来代替SizeAndTimeBasedFNATP,具体描述可见对应issue链接:
SizeAndTimeBasedFNATP was renamed but is still mentionned in the documentation

分析异常:Active code page: 65001 Logging system failed to initialize using configuration from 'null' java.lang.IllegalStateException: Logback configuration error detected: ERROR in ch.qos.logback.core.model.processor.ImplicitModelHandler - Could not create component [timeBasedFileNamingAndTriggeringPolicy] of type [ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP] java.lang.ClassNotFoundException: ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP ERROR in c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - Filename pattern [work/syncUser2ThirdParty-%d{yyyy-MM-dd}.%i.log.zip] contains an integer token converter, i.e. %i, INCOMPATIBLE with this configuration. Please remove it. at org.springframework.boot.logging.logback.LogbackLoggingSystem.reportConfigurationErrorsIfNecessary(LogbackLoggingSystem.java:287) at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:265) at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:81) at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:61) at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:196) at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:332) at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298) at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246) at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138) at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136) at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81) at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64) at java.base/java.lang.Iterable.forEach(Iterable.java:75) at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118) at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112) at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63) at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:370) at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:149) at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:198) at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:114) at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:77) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138) at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136) at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81) at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64) at java.base/java.lang.Iterable.forEach(Iterable.java:75) at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118) at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112) at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63) at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:370) at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:149) at com.hd.rcugrc.ui.ProjectApplication.main(ProjectApplication.java:111) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:102) at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:64) at org.springframework.boot.loader.launch.WarLauncher.main(WarLauncher.java:53) Suppressed: java.lang.ClassNotFoundException: ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587) at org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader.loadClass(JarUrlClassLoader.java:97) at org.springframework.boot.loader.launch.LaunchedClassLoader.loadClass(LaunchedClassLoader.java:91) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) at ch.qos.logback.core.util.Loader.loadClass(Loader.java:132) at ch.qos.logback.core.model.processor.ImplicitModelHandler.doComplex(ImplicitModelHandler.java:134) at ch.qos.logback.core.model.processor.ImplicitModelHandler.handle(ImplicitModelHandler.java:94) at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:241) at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253) at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253) at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253) at ch.qos.logback.core.model.processor.DefaultProcessor.traversalLoop(DefaultProcessor.java:90) at ch.qos.logback.core.model.processor.DefaultProcessor.process(DefaultProcessor.java:106) at ch.qos.logback.core.joran.GenericXMLConfigurator.processModel(GenericXMLConfigurator.java:222) at org.springframework.boot.logging.logback.SpringBootJoranConfigurator.processModel(SpringBootJoranConfigurator.java:133) at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:178) at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:123) at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:66) at org.springframework.boot.logging.logback.LogbackLoggingSystem.configureByResourceUrl(LogbackLoggingSystem.java:296) at org.springframework.boot.logging.logback.LogbackLoggingSystem.lambda$loadConfiguration$1(LogbackLoggingSystem.java:258) at org.springframework.boot.logging.logback.LogbackLoggingSystem.withLoggingSuppressed(LogbackLoggingSystem.java:472) at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:252) ... 46 more 2025-07-24T11:04:35.063+08:00 ERROR 50600 --- [xcoa] [ main] [ ] o.s.boot.SpringApplication : Application run failed
最新发布
07-25
<think>我们正在处理一个Spring Boot应用启动时的日志配置错误,错误信息是: `Logback配置错误,ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP类找不到,ERROR: Filename pattern contains %i token converter incompatible` 根据错误信息,问题出现在Logback的配置中,具体是使用了`%i`(索引)的转换模式,但是相关的类`SizeAndTimeBasedFNATP`找不到。 分析原因: 1.Logback的旧版本中,我们使用`SizeAndTimeBasedFNATP`类来实现基于时间和文件大小的滚动策略,并且文件名模式中需要同时包含`%d`(日期)和`%i`(索引)两个转换符。 2.Logback的新版本中(从1.1.7版本开始),这个类被重命名为`SizeAndTimeBasedRollingPolicy`,并且对应的配置方式也有所改变。 因此,这个错误通常是因为Logback版本升级导致的类名变更。在Spring Boot的早期版本中,默认集成的Logback版本可能较低,而升级到较新的Spring Boot版本后,Logback版本也随之升级,导致旧配置失效。 解决方案: 1. 修改Logback配置文件(如logback-spring.xml),将旧的`SizeAndTimeBasedFNATP`配置方式更新为新的`SizeAndTimeBasedRollingPolicy`。 具体步骤: 旧配置可能类似于: ```xml <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE}</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory> </rollingPolicy> ... </appender> ``` 新配置应该改为: ```xml <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE}</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!-- 文件名模式同时包含日期和索引 --> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 设置每个文件的最大大小 --> <maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize> <!-- 保留的历史日志文件数量 --> <maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory> <!-- 可选:设置总大小限制 --> <totalSizeCap>${LOG_FILE_TOTAL_SIZE_CAP:-0}</totalSizeCap> </rollingPolicy> ... </appender> ``` 注意:新的配置方式中,我们直接使用`SizeAndTimeBasedRollingPolicy`作为滚动策略,并且将原来在`SizeAndTimeBasedFNATP`中配置的`maxFileSize`移到了`rollingPolicy`中。 2. 另外,确保你的Spring Boot版本对应的Logback版本是兼容的。Spring Boot 2.x默认使用Logback 1.2.x以上版本,而Logback 1.1.7及以上版本已经使用新的类名。 3. 如果问题仍然存在,检查项目中是否有多个Logback的配置文件,或者是否有依赖引入了旧版本的Logback(比如通过其他依赖传递)。可以通过Maven的依赖树检查: ``` mvn dependency:tree ``` 确保使用的Logback版本至少是1.1.7。 4. 如果项目中没有显式配置Logback,而是使用Spring Boot的默认配置,那么可能需要检查是否在配置文件中(如application.properties)设置了日志文件名的模式。在Spring Boot中,我们可以通过以下属性设置日志滚动策略: ```properties logging.pattern.rolling-file-name=your_log.%d{yyyy-MM-dd}.%i.log ``` 但是,这种配置方式在底层也是使用Logback的,所以同样需要新的Logback版本支持`%i`。如果使用的是旧版本,同样会出现问题。 因此,建议升级Spring Boot到较新的版本(如2.2.x以上),并确保Logback版本在1.1.7以上。 如果项目无法升级Spring Boot,那么可能需要降级Logback版本(不推荐,因为可能有安全漏洞),或者修改配置不使用`%i`(即不使用基于文件大小的滚动,只使用时间滚动)。 但是,根据错误信息,配置中包含了`%i`,所以必须使用支持`%i`的滚动策略。因此,升级Logback配置是根本的解决方法。 总结:修改Logback配置文件,使用新的`SizeAndTimeBasedRollingPolicy`类替代旧的`SizeAndTimeBasedFNATP`。 下面是一个完整的新配置示例(logback-spring.xml): ```xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/> <property name="LOG_FILE_MAX_SIZE" value="10MB" /> <property name="LOG_FILE_MAX_HISTORY" value="30" /> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_FILE}</file> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>${LOG_FILE_MAX_SIZE}</maxFileSize> <maxHistory>${LOG_FILE_MAX_HISTORY}</maxHistory> </rollingPolicy> </appender> <root level="INFO"> <appender-ref ref="FILE" /> </root> </configuration> ``` 注意:上面的配置中,我们使用了`SizeAndTimeBasedRollingPolicy`,并且`fileNamePattern`中同时包含了`%d`和`%i`。 修改后,重新启动应用,问题应该得到解决。 如果问题依旧,请检查Logback的版本。在Spring Boot 2.2.5.RELEASE中,默认的Logback版本是1.2.3,这个版本是支持`SizeAndTimeBasedRollingPolicy`的。 相关问题: 1. 如何在Spring Boot中配置Logback日志? 2. Logback滚动策略有哪些? 3. 如何解决Logback配置中的类找不到问题? 4. Spring Boot升级后日志配置不兼容怎么办?</think>### 分析及解决 Logback 配置错误:`SizeAndTimeBasedFNATP` 类找不到 #### 问题原因 该错误通常由以下原因引起: 1. **Logback 版本兼容性问题** `SizeAndTimeBasedFNATP` 类在 Logback 1.1.7+ 版本中已被用,并在 1.2.0+ 版本中被移除[^1]。Spring Boot 2.2.x+ 默认使用 Logback 1.2.x+,导致旧配置失效。 2. **配置语法过时** 错误信息 `Filename pattern contains %i token converter incompatible` 表明配置中使用了旧版滚动策略语法: ```xml <!-- 过时语法 (Logback <1.1.7) --> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> ``` 3. **依赖冲突** 项目中可能存在多个 Logback 版本或 SLF4J 绑定冲突。 --- ### 解决方案 #### 步骤 1:更新 Logback 配置 使用新版 `SizeAndTimeBasedRollingPolicy` 替代用的 `FNATP` 类: ```xml <!-- logback-spring.xml 新版配置 --> <configuration> <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/app.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!-- 关键:使用 %i 需包含 %d --> <fileNamePattern>logs/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxFileSize>200MB</maxFileSize> <!-- 引用[2]中的配置 --> <maxHistory>30</maxHistory> <!-- 引用[2] --> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="${logback.rootLevel:-DEBUG}"> <!-- 引用[2] --> <appender-ref ref="ROLLING" /> </root> </configuration> ``` #### 步骤 2:检查依赖版本 确保 `pom.xml` 使用兼容组合: ```xml <!-- Spring Boot 2.2.x+ 需匹配 Logback 1.2.x+ --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <!-- 引用[4] --> </parent> <dependencies> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> <!-- 最低要求 1.2.0 --> </dependency> </dependencies> ``` #### 步骤 3:解决冲突 检查依赖冲突: ```bash mvn dependency:tree | grep logback ``` 若存在多个版本,通过 `<exclusions>` 解决: ```xml <dependency> <groupId>com.example</groupId> <artifactId>problematic-lib</artifactId> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> </exclusions> </dependency> ``` #### 步骤 4:验证配置 在 `application.properties` 激活配置检查: ```properties # 开启配置调试模式 logging.config=classpath:logback-spring.xml debug=true ``` 启动应用观察日志输出: ``` 15:30:00,000 |-INFO in RollingFileAppender[ROLLING] - Active log file: logs/app.log ``` --- ### 关键注意事项 1. **文件名模式规则** `%i`(索引)必须与 `%d{pattern}` 同时使用,否则触发 `incompatible token` 错误。 2. **Profile 配置** 使用 `logback-spring.xml` 替代 `logback.xml` 以支持 Spring Profile[^1]: ```xml <springProfile name="staging"> <maxHistory>60</maxHistory> <!-- 生产环境保留更多日志 --> </springProfile> ``` 3. **日志工厂兼容性** 确保日志工厂类使用 SLF4J 接口(引用[3]): ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LogFactory { private static final Logger logger = LoggerFactory.getLogger(LogFactory.class); // ... 方法实现 } ``` --- ### 相关问题 1. **如何在 Spring Boot 中配置多环境日志策略?** > 使用 `logback-spring.xml` 结合 `<springProfile>` 标签,为不同环境设置滚动策略[^1]。 2. **升级 Spring Boot 后出现 `NoClassDefFoundError` 如何解决?** > 检查依赖树中的版本冲突,使用 `mvn dependency:tree` 分析并排除旧版依赖。 3. **Logback 和 Log4j2 在 Spring Boot 中如何选择?** > Logback 是 Spring Boot 默认实现,需排除 `spring-boot-starter-logging` 并引入 `spring-boot-starter-log4j2` 切换。 4. **如何动态修改运行时的日志级别?** > 通过 Spring Boot Actuator 的 `/actuator/loggers` 端点动态调整,需添加依赖: > ```xml > <dependency> > <groupId>org.springframework.boot</groupId> > <artifactId>spring-boot-starter-actuator</artifactId> > </dependency> > ``` [^1]: Spring Boot 日志配置要求 [^2]: Logback 参数配置示例 [^3]: 日志工厂实现规范 [^4]: Spring Boot 依赖管理要求
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值