springboot 最简单的日志打印,输出日志文件 及全局异常捕获处理

本文介绍如何在SpringBoot项目中使用日志并配置全局异常捕获,通过实例演示了如何利用日志记录和异常类型处理提升运维效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一直使用System.out.println()的我终于在今天从良了,我决定开始使用log了。

 

好了,不废话了,进入正题(先介绍日志简单使用,再介绍全局异常捕获及根据异常类型处理,不想看日志使用的直接看后面。)

前言:

我在学习这个日志打印的时候,在网上浏览了很多相关的知识,发现有些高级配置啊,有些花样日志管理啊等等;

而我,仅仅是想用一下日志的打印, 然后把日志生成某个文件给运维人员看(然后关掉Tomcat那可恶的日志)。 也就是仅此而已。

所以,接下来的日志使用,还真的是蛮轻巧(简单)的。

首先,

日志这边用到的jar包方法是:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

为什么不把pom直接贴出来呢,是因为:

看,

也就是说,还是贴pom.xml的东西出来吧:

<dependencies>
    <dependency>
        <groupId>org.springfra
<think>我们正在解决Spring Boot中使用Starter Logging后System.out.println()不再输出到控制台的问题。这通常是因为Spring Boot默认配置了日志框架(如Logback)接管了控制台输出,而System.out.println()的输出被重定向到了日志框架,但日志框架默认可能不会将System.out的输出显示在控制台(除非配置了相应的Appender)。 然而,根据用户提供的引用内容,特别是引用[2]和引用[3],我们知道Spring Boot默认配置了日志,并且默认情况下,控制台日志是开启的(通过ConsoleAppender)。但是,System.out.println()的输出并没有经过日志框架,所以它不会按照日志框架的配置输出。但是,在Spring Boot应用中,我们可能会发现System.out.println()没有输出,这通常是因为日志框架重定向了标准输出。 实际上,Spring Boot在启动时,会通过`org.springframework.boot.logging.LoggingSystem`来初始化日志系统,并且可能会重定向System.out和System.err到日志框架。具体来说,Spring Boot的Logback实现中,在初始化时会调用`org.springframework.boot.logging.logback.LogbackLoggingSystem`的`initialize`方法,其中会重定向标准输出流到日志框架。 但是,默认情况下,Spring Boot并不会重定向System.out到日志框架。那么为什么System.out.println()不输出到控制台了呢?可能是因为Spring Boot启动后,控制台被日志框架接管,而System.out.println()的输出被缓冲或者被重定向到其他地方。 然而,根据引用[2]中的配置,我们可以通过配置日志模式来控制控制台输出的格式,但并没有提到System.out的输出。因此,我们需要明确:Spring Boot默认情况下,System.out.println()应该还是会输出到控制台的,除非我们做了特殊配置。 但是,用户遇到了System.out.println()没有输出的情况,这可能是由于以下原因: 1. 日志框架的配置将控制台输出关闭了?但实际上,日志框架的控制台输出和System.out是两个不同的通道。即使日志框架关闭了控制台输出,System.out也应该能输出到控制台(除非控制台被关闭,比如在服务器环境中没有控制台)。 2. 可能是在某些环境下(如嵌入式的Tomcat启动)控制台被重定向了?或者是在IDE中运行,但控制台被设置为只显示某个日志文件? 3. 另外,Spring Boot在启动时,可能会将System.out和System.err重定向到日志框架,这样System.out的输出就会通过日志框架输出,而日志框架的默认级别是INFO,所以如果System.out被重定向为DEBUG级别,那么可能因为日志级别设置而看不到。 根据Spring Boot官方文档,从1.4.0版本开始,Spring Boot提供了将System.out和System.err重定向到日志的功能,但默认是关闭的。我们可以通过配置`logging.console.include-stdout`来开启(但我在最新的文档中没有找到这个配置,可能已经改变)。在较新的版本中,我们可以通过`logging.console.enable-stdout`(这个配置名可能不准确)?或者,更常见的是,Spring Boot默认并没有重定向。 实际上,在Spring Boot中,如果你使用了`spring-boot-starter-logging`,它默认使用Logback,并且会初始化一个控制台Appender(输出到System.err,而不是System.out)。所以,System.out.println()的输出应该还是正常的。 但是,如果用户发现System.out.println()没有输出,我们可以尝试以下解决方案: 1. 检查是否在代码中调用了`System.setOut()`或`System.setErr()`重定向了标准输出。 2. 检查日志配置是否将控制台输出关闭(比如配置了只输出到文件,或者将控制台Appender移除了)。 3. 尝试在Spring Boot的配置文件中添加配置,强制将System.out和System.err的输出重定向到日志框架,然后通过日志框架的控制台Appender输出(这样我们就可以通过日志级别来控制)。 但是,用户的需求是恢复System.out的输出,我们可以考虑: 方案一:禁用Spring Boot日志控制台重定向(如果它确实重定向了)。但默认并没有重定向,所以这个方案可能不适用。 方案二:使用日志框架的配置,将System.out的输出通过日志框架输出到控制台。这可以通过在Logback配置中添加一个Appender来实现,但这样System.out的输出会经过日志框架,受到日志级别的影响。 方案三:检查运行环境,比如在IDE中运行,可能是控制台设置问题。 然而,根据引用[1]和[2],我们可以通过配置日志级别和输出格式,但并没有直接配置System.out的输出。 实际上,有一个更直接的方法:在Spring Boot的配置文件中,我们可以设置日志系统不重定向标准输出。在Spring Boot 2.0+中,可以通过以下配置: ``` spring: main: banner-mode: "off" # 这个配置与日志无关,只是关闭banner logging: system-err: "SYSTEM_OUT" # 这个配置不存在 ``` 经过查阅资料,Spring Boot默认并没有重定向System.out,所以不应该出现System.out被抑制的情况。因此,我们需要考虑其他原因。 但是,有一个常见的陷阱:当我们在使用Spring Boot的嵌入式容器启动时,控制台输出可能会被容器的日志系统捕获,然后按照容器的日志配置输出。而容器的日志配置可能默认只输出到文件,或者只输出ERROR级别。 因此,我建议先做以下检查: 1. 确保代码中确实执行了System.out.println()(比如在方法中加断点或日志,确保执行到)。 2. 尝试在System.out.println()之后立即调用System.out.flush(),看是否是缓冲问题。 3. 检查运行环境,比如在IDE中运行,查看控制台是否有其他输出,或者尝试在命令行运行(使用`java -jar`)。 如果以上检查都没有问题,那么我们可以考虑在Spring Boot中显式配置重定向System.out到日志框架,然后通过日志框架输出到控制台。这样我们就可以通过日志配置来控制。 具体步骤: 1. 添加依赖:`sysout-over-slf4j`(如之前回答所述),然后在Spring Boot启动时初始化重定向。 但是,在Spring Boot中,我们可以使用一个配置类来初始化: ```java import org.springframework.context.annotation.Configuration; import uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J; import javax.annotation.PostConstruct; @Configuration public class SysoutConfig { @PostConstruct public void init() { SysOutOverSLF4J.sendSystemOutAndErrToSLF4J(); } } ``` 2. 在application.properties中配置日志级别,确保System.out的输出级别(默认INFO)能够被输出: 例如,在application.properties中: ``` logging.level.root=INFO ``` 3. 确保日志配置中有控制台Appender(默认就有)。 这样,System.out.println()就会被重定向到SLF4J,然后通过Logback输出到控制台。 但是,请注意:重定向后,System.out的输出会变成日志记录,其日志记录器名称是"System.out",而System.err的是"System.err"。我们可以通过日志格式来显示。 在Logback的配置中(比如logback.xml),我们可以修改pattern来包含这个记录器名称: ```xml <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> ``` 这样,System.out的输出就会显示为: ``` 2023-05-10 14:30:22 [main] INFO System.out - 消息内容 ``` 总结:如果用户发现System.out.println()在Spring Boot中不输出,首先应该检查代码执行和环境问题。如果确认是日志框架导致的问题,可以通过重定向到SLF4J的方式,将System.out的输出交给日志框架,然后输出到控制台。 另外,需要注意的是,重定向后,所有的System.out.println()都会变成日志输出,可能会受到日志级别和Appender的影响。比如,如果日志级别设置为WARN,那么System.out的INFO级别输出就不会显示。 因此,我们也可以选择不重定向,而是找出为什么System.out.println()没有被输出的真正原因。但考虑到用户希望恢复输出,重定向是一个可行的方案。 根据引用[4]中的配置,我们可以通过`logging.level`来设置不同包的日志级别,所以如果我们重定向了,也可以单独设置System.out的日志级别: ``` logging.level.System.out=INFO ``` 这样,即使根日志级别是WARN,System.out的INFO级别也会输出。 因此,解决方案如下: 步骤1:添加依赖 对于Maven项目,在pom.xml中添加: ```xml <dependency> <groupId>uk.org.lidalia</groupId> <artifactId>sysout-over-slf4j</artifactId> <version>1.0.2</version> </dependency> ``` 步骤2:创建配置类进行重定向 ```java import org.springframework.context.annotation.Configuration; import uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J; import javax.annotation.PostConstruct; @Configuration public class SysoutToLogConfig { @PostConstruct public void redirectSystemOut() { SysOutOverSLF4J.sendSystemOutAndErrToSLF4J(); } } ``` 步骤3:在application.properties中设置日志级别(可选,如果默认级别低于INFO则需要) ``` # 设置System.out的日志级别为INFO(因为重定向后,System.out的输出级别为INFO) logging.level.System.out=INFO ``` 步骤4:确保日志配置中有控制台Appender(默认就有,无需额外配置) 这样,System.out.println()的输出就会出现在控制台,并且格式与日志一致。 注意:如果不想影响System.err(因为System.err默认会重定向为ERROR级别),也可以只重定向System.out。但是,`SysOutOverSLF4J.sendSystemOutAndErrToSLF4J()`方法同时重定向了System.out和System.err。如果只想重定向System.out,可以使用: ```java SysOutOverSLF4J.sendSystemOutToSLF4J(); ``` 但是,通常我们可能希望两者都重定向,以保持一致性。 最后,如果用户不想添加额外的依赖,也可以自行实现重定向,例如: ```java PrintStream originalOut = System.out; System.setOut(new PrintStream(new OutputStream() { @Override public void write(int b) throws IOException { // 重定向到日志 LoggerFactory.getLogger("System.out").info(String.valueOf((char) b)); // 注意:这里只是简单示例,实际需要处理整个字节流,而不是单个字节 } })); ``` 但这种方式效率低且容易出错,因此推荐使用`sysout-over-slf4j`。 综上所述,添加依赖并配置重定向是最可靠的解决方案。 如果用户不想重定向,而是希望恢复原始的System.out输出(即不经过日志框架),那么需要检查是否Spring Boot日志系统做了重定向。在Spring Boot的LoggingSystem中,有一个方法`restoreConsole()`可以恢复控制台输出,但这是内部方法,不建议使用。因此,重定向到日志框架是更合理的做法。 现在,我们来回答用户的问题: 问题:Spring Boot Starter Logging 配置后 System.out 日志无法输出到控制台,如何解决? 回答: 在Spring Boot中,使用`spring-boot-starter-logging`(默认包含在`spring-boot-starter`中)后,您可能会发现`System.out.println()`的输出不再出现在控制台。这是因为Spring Boot日志系统(默认Logback)可能会影响控制台的输出行为。以下是排查和解决方案: ### 1. 确认问题原因 - 首先检查`System.out.println()`语句是否被执行(通过调试或日志记录)。 - 检查运行环境(如IDE或命令行)的控制台设置,确保没有过滤掉输出- 注意:Spring Boot默认不会重定向`System.out`,但可能因为日志框架的初始化导致控制台输出被缓冲或重定向。 ### 2. 解决方案:重定向System.out到SLF4J 推荐将`System.out`重定向到SLF4J,这样输出会通过日志框架输出到控制台,并可以统一管理格式和级别。 **步骤:** (1) 添加依赖`sysout-over-slf4j`(Maven): ```xml <dependency> <groupId>uk.org.lidalia</groupId> <artifactId>sysout-over-slf4j</artifactId> <version>1.0.2</version> </dependency> ``` (2) 创建配置类进行重定向: ```java import org.springframework.context.annotation.Configuration; import uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J; import javax.annotation.PostConstruct; @Configuration public class SysoutConfig { @PostConstruct public void init() { // 重定向System.out和System.err到SLF4J SysOutOverSLF4J.sendSystemOutAndErrToSLF4J(); } } ``` (3) 配置日志级别(可选,确保输出级别): 在`application.properties`中,设置`System.out`的日志级别为`INFO`(因为重定向后`System.out`的输出级别为`INFO`): ```properties logging.level.System.out=INFO ``` (4) 验证:运行程序,`System.out.println()`的输出将显示为: ``` 2023-05-10 14:30:22 [main] INFO System.out - 您的消息 ``` ### 3. 其他注意事项 - **循环重定向问题**:`sysout-over-slf4j`已处理日志框架自身输出与`System.out`的循环依赖,无需担心。 - **仅重定向System.out**:若只需重定向`System.out`,可使用`SysOutOverSLF4J.sendSystemOutToSLF4J()`。 - **恢复原始输出(不推荐)**:若您希望恢复原始输出(不通过日志框架),请检查是否在代码中调用了`System.setOut()`,并尝试移除。但Spring Boot本身不会主动重定向`System.out`,因此此方法可能无效。 通过以上步骤,您可以将`System.out`的输出整合到日志系统中,实现统一管理。 §§相关问题§§ 1. Spring Boot中如何配置日志输出到文件和控制台? 2. 如何自定义Spring Boot日志格式? 3. 如何在Spring Boot中动态更改日志级别? 4. 为什么生产环境推荐使用日志框架而非System.out?[^1][^2] [^1]: 日志框架提供级别控制、异步输出和结构化日志等高级功能,提升系统可维护性。 [^2]: SLF4J作为日志门面支持参数化日志,避免字符串拼接开销,提升性能。</think>### 解决 Spring Boot Starter Logging 中 System.out 日志无法输出到控制台的问题 在 Spring Boot 中使用 Starter Logging 后,`System.out.println()` 的输出可能被日志框架接管,默认不会直接输出到控制台。以下是完整解决方案: --- #### 原因分析 1. **日志框架接管输出**:Spring Boot 默认使用 Logback/Log4j2 作为日志实现,会重定向 `System.out` 到日志系统[^1][^2] 2. **日志级别过滤**:重定向后的 `System.out` 默认以 INFO 级别输出,可能被高级别(如 WARN)过滤[^3] 3. **配置覆盖**:自定义日志配置可能关闭了控制台输出 --- #### 解决方案(二选一) ##### 方法 1:通过配置重定向(推荐) **步骤:** 1. 添加依赖到 `pom.xml`: ```xml <dependency> <groupId>uk.org.lidalia</groupId> <artifactId>sysout-over-slf4j</artifactId> <version>1.0.2</version> </dependency> ``` 2. 在启动类初始化重定向: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J; @SpringBootApplication public class Application { public static void main(String[] args) { // 重定向 System.out/System.err 到 SLF4J SysOutOverSLF4J.sendSystemOutAndErrToSLF4J(); SpringApplication.run(Application.class, args); } } ``` 3. 在 `application.properties` 配置输出级别: ```properties # 确保 System.out 消息可见 logging.level.System.out=INFO # 控制台输出格式(可选) logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n ``` ##### 方法 2:修改日志配置(无需额外依赖) 在 `application.properties` 中强制启用控制台输出: ```properties # 确保控制台 Appender 启用 logging.config=classpath:logback-spring.xml ``` 创建 `src/main/resources/logback-spring.xml`: ```xml <configuration> <!-- 强制输出 System.out 到控制台 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> <!-- 关键配置:重定向 System.out --> <target>System.out</target> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> </configuration> ``` --- #### 验证结果 执行测试代码: ```java System.out.println("测试消息 - 应出现在控制台"); logger.info("普通日志消息"); ``` 正常输出示例: ``` 2023-06-15 10:30:45 [main] INFO System.out - 测试消息 - 应出现在控制台 2023-06-15 10:30:45 [main] INFO com.example.Application - 普通日志消息 ``` --- #### 关键注意事项 1. **日志级别冲突**:确保 `logging.level.System.out=INFO` 不被全局级别覆盖[^4] 2. **启动顺序**:重定向代码(`SysOutOverSLF4J`)必须在 Spring Boot 启动前执行 3. **生产建议**:推荐直接使用 `logger.info()` 替代 `System.out.println()`[^1][^2] - 支持动态日志级别调整 - 避免输出阻塞主线程 - 提供结构化日志和上下文信息 --- ###
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小目标青年

对你有帮助的话,谢谢你的打赏。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值