Spring Boot无法设置自定义日志文件路径问题排查求助
环境信息
- Windows
- Java 8(1.8.0_291)
- Spring Boot v2.4.10
需求
希望将日志同时输出到控制台和指定日志文件,通过resources/application.properties配置日志规则。
当前日志配置(application.properties)
#Try1 Don't work with it # logging.level.org.springframework.web=ERROR #Try2 Don't work with it # logging.level.ru.leodev=DEBUG #Try3 Don't work with it logging.level.root = DEBUG logging.level.com.mycompany.stackexp = DEBUG logging.pattern.console= "%d{yyyy-MM-dd HH:mm:ss} - %msg%n" logging.pattern.file= "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" logging.file=e:\Projects\logs\app.log
异常现象
已提前创建e:\Projects\logs目录,启动Spring应用后访问http://localhost:3333/myLog接口输出测试日志时,仅控制台有日志输出,指定路径下未生成日志文件,全程无任何报错信息。
相关代码
启动类代码
package com.mycompany.stackexp; import java.util.Properties; import javax.servlet.MultipartConfigElement; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.web.servlet.MultipartConfigFactory; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.util.unit.DataSize; @SpringBootApplication @EnableScheduling @EnableAsync public class ThreadSpringServer { private ConfigurableApplicationContext context; //Config spring app public ThreadSpringServer(){} public void start() throws InterruptedException, Exception { Thread.currentThread().setName("ThreadSpringServer"); System.out.println("Start SpringServer..."); context = SpringApplication.run(ThreadSpringServer.class); System.out.println("SpringServer was successfully started, port: "+System.getProperty("server.port")); } @Bean("Bean1") public MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); factory.setMaxFileSize(DataSize.parse("100MB")); factory.setMaxRequestSize(DataSize.parse("100MB")); return factory.createMultipartConfig(); } }
控制器代码
package com.mycompany.stackexp; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; //my logger import org.slf4j.Logger; import org.slf4j.LoggerFactory; @RestController public class ControllerSpring { private Logger springLogger = LoggerFactory.getLogger(ControllerSpring.class); @Autowired private ServletWebServerApplicationContext webServerAppCtxt; @GetMapping("/myLog") @ResponseBody public String getSpringTestMes() throws InterruptedException, IOException, ParseException, Exception { springLogger.error("errorMes"); springLogger.info("infoMes"); springLogger.debug("debugMes"); return "Spring boot create test mes in log file"; } }
pom.xml依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany</groupId> <artifactId>AutoHandler</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <java.version>1.8</java.version>> </properties> <dependencies> <!-- Spring for REST API --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.4.10</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.9</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-core</artifactId> <version>3.6.3</version> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-artifact</artifactId> <version>3.6.3</version> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-project</artifactId> <version>2.2.1</version> </dependency> <!-- Test dependencies --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.28</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.28</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.28</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.28</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.28</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> </dependencies> <build> <plugins> <!-- Other build plugins for create .jar--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.10</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-dependencies</id> <phase>prepare-package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>false</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.mycompany.stackexp.Main</mainClass> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> </archive> <source>1.5</source> <target>1.5</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.2.1</version> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <mainClass>com.mycompany.stackexp.Main</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <!-- this is used for inheritance merges --> <phase>package</phase> <!-- bind to the packaging phase --> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <name>AutoHandler</name> </project>
疑问
程序启动无报错,运行正常,但指定路径未生成日志文件,可能的错误原因是什么?
核心原因
1. 日志框架依赖冲突
Spring Boot 2.4.x默认整合了Logback作为日志实现,但你的pom.xml中存在大量冗余且冲突的日志依赖:
- 手动引入了老旧版本的
logback-classic(1.0.9),与Spring Boot自带的Logback版本不兼容 - 同时引入
log4j、slf4j-log4j12等多个日志实现,导致日志加载逻辑混乱,无法正确解析文件输出配置 spring-boot-starter-web已经包含了spring-boot-starter-logging(整合Logback+SLF4J),手动添加的slf4j-api、commons-logging等会破坏默认依赖链
2. 日志配置格式错误
logging.pattern.console和logging.pattern.file的值被多余的双引号包裹,Spring Boot的properties配置中不需要添加引号,这会导致格式解析失败,文件输出规则无法生效。
3. 启动类缺少标准入口
ThreadSpringServer没有main方法,若你的Main类未正确调用start()方法,可能导致Spring Boot的日志自动配置未完全生效。
修复步骤
1. 清理pom.xml冗余日志依赖
保留spring-boot-starter-web、spring-boot-starter-test以及非日志类的maven依赖,移除所有冲突的日志依赖:
<dependencies> <!-- Spring for REST API --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.4.10</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-core</artifactId> <version>3.6.3</version> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-artifact</artifactId> <version>3.6.3</version> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-project</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.28</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.28</version> </dependency> </dependencies>
2. 修正application.properties配置
移除日志pattern的双引号,同时将Windows路径的反斜杠转义(或使用正斜杠):
logging.level.root = DEBUG logging.level.com.mycompany.stackexp = DEBUG logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} - %msg%n logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n logging.file=e:\\Projects\\logs\\app.log
3. 完善启动类入口
在ThreadSpringServer中添加标准main方法:
public static void main(String[] args) throws InterruptedException, Exception { new ThreadSpringServer().start(); }
验证
重新构建并启动应用,访问/myLog接口后,检查e:\Projects\logs\app.log是否生成,此时控制台和文件应同时输出日志。
内容的提问来源于stack exchange,提问作者Yella32121

