热部署与日志
springboot 中 devtools 热部署
1 引言
为了进一步提高开发效率,springboot 为我们提供了全局项目热部署,日后在开发过程中修改部分代码以及相关配置文件后,不需要每次重启使修改生效,在项目中开启了 springboot 全局热部署之后只需要在修改之后等待几秒即可使修改生效。
2 开启热部署
21 项目中引入依赖
<!-- 1. devtools 热部署 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
22 当我们修改了类文件后,idea 不会自动编译,得修改 idea 设置。
File-Setting-Compiler-Build Project automatically
ctrl + shift + alt + /,选择 Registry,勾上 Compiler autoMake allow when app running
带你弄清混乱的 JAVA 日志体系
1 日志框架
日志实现 日志门面 log4j JCL jul java.util.logging SJF4J log4j2 logback(推荐使用) 2 代码实现
21 日志实现
211 jul(注意包名)
package com.springboot; import java.util.logging.Logger; public class JulMain { public static void main(String[] args) { Logger logger = Logger.getLogger(JulMain.class.getName()); logger.info("崇尚官方开发组:Jul"); } }
212 log4j(注意包名)
导包:
<!-- log4j 的核心依赖 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
添加 log4j.properties 文件:
log4j.rootLogger=trace, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
java 代码实现:
package com.springboot; import org.apache.log4j.Logger; public class Log4jMain { public static void main(String[] args) { Logger logger = Logger.getLogger(Log4jMain.class.getName()); logger.info("崇尚开源开发组:Log4j"); } }
22 日志及日志门面实现
开发标准:记录日志不能直接使用日志实现框架,必须通过日志门面来实现。
221 Jul (实现) + JCL (门面)
导包:
<!-- 引入 JCL 门面依赖 --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency>
添加 commons-logging.properties 文件:
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
java 实现:
package com.springboot; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class JulMain { public static void main(String[] args) { Log log = LogFactory.getLog(JulMain.class.getName()); System.out.println(log.getClass()); log.info("崇尚官方开发组:Jul"); } }
222 log4j (实现) + slf4j (门面)
导包:
<!-- slf4j 的核心依赖 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <!-- 加上桥接器 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency>
java 实现:
package com.springboot; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Log4jMain { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(Log4jMain.class); System.out.println(logger.getClass()); logger.info("崇尚开源开发组:Log4j"); } }
3 桥接器
4 将 JCL 转化到 slf4j
使用 jcl-over-slf4j 或者 jul-to-slf4j
<!-- 为了日志统一实现,将 JCL 转化到 slf4j 添加 JCL-slf4j 的适配器 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> </dependency>
logback 日志的集成
SpringBoot 底层也是使用 slf4j + logback 的方式进行日志记录
logback 桥接:logback-calssic
SpringBoot 也把其他的日志都替换成了 slf4j;
- log4j 适配:log4j-over-slf4j
- jul 适配:jul-to-slf4j
- jcl-over-slf4j
SpringBoot 日志使用
日志级别
可以设置 TRACE,DEBUG,INFO,WARN,ERROR 或 OFF 之一
logging: level: root: "warn" org.springframework.web: "debug" org.hibernate: "error"
日志格式
2022-04-29 16:18:09.667 TRACE 78860 --- [ main] com.springboot.Application : 跟踪 2022-04-29 16:18:09.667 DEBUG 78860 --- [ main] com.springboot.Application : 调试 2022-04-29 16:18:09.667 INFO 78860 --- [ main] com.springboot.Application : 信息 2022-04-29 16:18:09.667 WARN 78860 --- [ main] com.springboot.Application : 警告 2022-04-29 16:18:09.667 ERROR 78860 --- [ main] com.springboot.Application : 异常
详细介绍:
可以使用 logging.pattern.console 修改默认的控制台的日志格式:
%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
2022-04-29 16:18:09.667
- 日期和时间:毫秒精度,易于排序。
%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint}
- %clr 代表当前内容的颜色 {faint}
(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}) 括号中表示显示的内容
${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}
使用了 ${value:value2} springboot 的占位符 + null 条件的表达式(如果 value 为 null 则使用 value2)
LOG_DATEFORMAT_PATTERN:系统环境变量中的值,springboot 底层会根据对应的配置项将值设置到对应的环境变量中 LOG_DATEFORMAT_PATTERN=logging.pattern.dateformat 可通过 dateformat: -yyyy-MM-dd 设置
%d{-yyyy-MM-dd HH:mm:ss.SSS}
%d 表示 logback 的日期显示方式
{-yyyy-MM-dd HH:mm:ss.SSS} 表示日期的格式
TRACE
- 日志级别。
%clr(${LOG_LEVEL_PATTERN:-%5p})
- %clr 表示内容的颜色,会根据不同的日志级别输出对应的颜色
${LOG_LEVEL_PATTERN:-%5p}
- %5 代表当前内容所占字符长度
- p 表示输出日志的级别
78860
- 进程 ID。
%clr(${PID:- }){magenta}
- %clr 表示当前内容的颜色为 {magenta}
- ${PID:- } springboot 的占位符 + null 条件的表达式(如果 value 为 null 则使用 value2)
- PID 是系统环境变量中的进程 ID (由系统分配)
---
- 一个 --- 分离器来区分实际日志消息的开始。
[ main]
- 线程名称:用方括号括起来(对于控制台输出可能会被截断)。
com.springboot.Application
- 记录日志的类。
跟踪
- 日志消息
文件输出
默认情况下,Spring Boot 仅记录到控制台,不写日志文件。如果除了控制台输出外还想写日志文件,则需要设置一个 logging.file.name 或 logging.file.path 属性(例如,在中 application.properties)。
下表显示了如何 logging.* 一起使用这些属性:
logging.file.name logging.file.path 实例 描述 (没有) (没有) 仅控制台记录 指定文件名 (没有) my.log 写入指定的日志文件 (没有) 具体目录 /var/log 写入 spring.log 指定的目录 logging.file.name
- 可以设置文件的名称,如果没有设置路径会默认在项目的相对路径下创建
- 还可以指定路径 + 文件名:
D:/my.log
logging.file.path
- 不可以指定文件的名称,必须要指定一个物理文件夹路径,会默认使用 spring.log 为文件名称
Spring Boot 的默认日志级别是 INFO
@SpringBootApplication public class Application { //1. 声明日志记录器 static Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication.run(Application.class, args); logger.trace("跟踪"); logger.debug("调试"); //Spring Boot 的默认日志级别是 INFO logger.info("信息"); logger.warn("警告"); logger.error("异常"); } }
日志迭代(轮转)
如果您使用的是 Logback,则可以使用 application.properties 或 application.yaml 文件微调日志轮播设置。对于所有其他日志记录系统,您需要直接配置轮转设置(例如,如果使用 Log4J2,则可以添加 log4j.xml 文件)。
名称 描述 logging.logback.rollingpolicy.file-name-pattern 归档的文件名 logging.logback.rollingpolicy.clean-history-on-start 如果应在应用程序启动时进行日志归档清理 logging.logback.rollingpolicy.max-file-size 归档前日志文件的最大大小 logging.logback.rollingpolicy.total-size-cap 删除日志档案之前可以使用的最大大小 logging.logback.rollingpolicy.max-history 保留日志存档的天数(默认为7) logging.logback.rollingpolicy.file-name-pattern
${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
- ${LOG_FILE} 对应 logging.file.name
- %d{yyyy-MM-dd} 日期 年-月-日
- %i 索引,当文件超出指定大小后进行的文件索引递增
自定义日志配置文件
可以通过在类路径中包含适日志配置文件来激活各种日志记录系统或使用 logging.config
Logging System Customization Logback logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy log4j2 log4j2-spring.xml or log4j2.xml JDK(Java Util Logging) logging.properties 注意:
- 如果使用自定义日志配置文件,会使 springboot 中全局配置文件的 logging 相关配置失效。
可以结合 springboot 提供的 Profile 来控制日志的生效
要注意的是,一定要将日志配置文件的文件名改成 logback-spring.xml, 因为 logback.xml 会在 springboot 容器加载之前先被 logback 给加载到,那么由于 logback 无法解析 springProfile 将会报错
切换日志框架
将 logback 切换成 log4j2
添加 spring-boot-starter-log4j2 依赖(场景启动器)
<!-- log4j2 的场景启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
排除 logback 的场景启动器
<!-- starter-web 里面自动添加了 starter-logging 也就是 logback 的依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!-- 排除 starter-logging 也就是 logback 的依赖 --> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> </exclusion> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jul</artifactId> </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> <exclusions> <exclusion> <groupId>*</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency>
添加 log4j2.xml 文件
<?xml version="1.0" encoding="UTF-8" ?> <configuration status="OFF"> <appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} +++++++ %msg%n"/> </Console> </appenders> <loggers> <root level="info"> <appender-ref ref="Console"/> </root> </loggers> </configuration>
- 将 logback 切换成 log4j
1. 首先将 logback 的桥接器排除
```xml
<!-- starter-web 里面自动添加了 starter-logging 也就是 logback 的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
```
2. 添加 log4j 的桥接器
```xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
```
3. 添加 log4j 的配置文件
```properties
log4j.rootLogger=trace, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] ======== %m%n
```