SpringBoot热部署及日志

一. SpringBoot热部署

我们在做SpringBoot project的时候,如果启动了服务器,又在原来的代码基础上进行了一些修改,我们想要看到修改后的结果必须得重新启动服务器才可以,这时,SpringBoo为了提高开发效率,给我们提供了热部署.

1.添加pom依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

2.重新编译(ctrl+F9,或者手动重新编译也可)

这样我们可以在已经启动服务器的基础上修改业务逻辑代码,然后重新编译一下即可,就不需要停止服务器再运行了,提高了我们的开发效率.

二.java日志体系

1. 日志门面和日志框架

日志门面和日志框架的关系就好比接口(interface)和接口实现类之间的关系,我们是面向接口编程,同时对应了我们面向日志门面编程.日志门面不提供具体的解决方案,只提供接口,具体的解决方案需要使用到具体的日志框架,常见的日志门面和日志框架如下图:

2. 常见日志门面和框架

2.1 JUL

JUL是JDK自己的,所以在使用时可以不需要引入jar包

java 复制代码
import java.util.logging.Logger;

public class JulTest {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(JulTest.class.getName());
        String name = "张三";
        logger.info(name);
    }
}

2.2 log4j

(1) 导入jar包

xml 复制代码
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.17</version>
</dependency>

(2) 新建log4j.properties文件(约定大于配置),并且配置

ini 复制代码
log4j.rootLogger=trace, first
#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

log4j.appender.first=org.apache.log4j.ConsoleAppender
log4j.appender.first.layout=org.apache.log4j.PatternLayout
log4j.appender.first.layout.ConversionPattern=%d %p [%c] ===log4j=== %m%n

(3) 代码实现日志

arduino 复制代码
import org.apache.log4j.Logger;

public class Log4jTest {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4jTest.class);
        // trace<debug<info<warn<error
        // logger调用的必须比log4j.properties里面的小才可以输出
        logger.info("log4j");
    }
}

2.3 log4j2

(1) 导入jar包

xml 复制代码
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.17.2</version>
</dependency>

(2)添加log4j2.xml(约定大约配置),并且配置

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} ===log4j2=== %msg%n"/>
        </Console>
    </appenders>

    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>

(3) 代码实现日志

arduino 复制代码
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4j2Test {
    public static void main(String[] args) {
        Logger logger = LogManager.getLogger(Log4j2Test.class);
        logger.info("Log4j2Test");
    }
}

2.4 logback

(1) 导入jar包(因为logback是slf4j下面的日志框架,所以在导入jar包的时候最好把slf4j包也导入进来)

xml 复制代码
<!-- slf4j日志门面 -->
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.30</version>
</dependency>

<!-- slf4j日志实现-logback日志框架 -->
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.2.11</version>
</dependency>

(2) 添加logback.xml配置文件(约定大于配置)

xml 复制代码
<configuration>
    <!--appender 追加器   日志以哪种方式进行输出
            name 取个名字
            class 不同实现类会输出到不同地方
                ch.qos.logback.core.ConsoleAppender 输出到控制台
    -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 格式 -->
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{100} ===logback=== %msg%n</pattern>
        </encoder>
    </appender>
    <root level="debug">
        <!-- 将当前日志级别输出到哪个追加器上面 -->
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

(3) 代码实现日志

arduino 复制代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Slf4jTest {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
        logger.info("Slf4Test");
    }
}

2.5 jcl日志门面

xml 复制代码
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.2</version>
</dependency>

jcl日志门面,这个配置了之后会自动寻找,如果有log4j就使用log4j框架,如果没有log4j就使用JDK自带的JUL框架

三 slf4j大一统

我们可以看到,有好几个日志框架可以实现日志功能,我们如果在开发过程中不同的人用不同的日志框架可能会报错,这里就出了一个很好的解决问题--slf4j大一统.

我们可以使用slf4j提供的桥接器,让slf4j日志门面能够和其他的日志框架相兼容,我们在代码中只需要写一个代码接口,到时候想使用那个日志框架直接导入jar包然后添加配置文件即可.

1. slf4j与jcl兼容(其实也是和JUL日志框架相兼容,因为JCL默认先找log4j,如果没有log4就会调用JDK自带的JUL日志框架)

(1) 添加slf4j与jcl桥接器

xml 复制代码
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-jcl</artifactId>
  <version>1.7.30</version>
</dependency>

(2) 因为这个是JDK自带的,所以不需要添加配置文件

(3) 使用统一代码

2. slf4j与log4j兼容

(1) 添加slf4j与log4j桥接器

xml 复制代码
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.30</version>
</dependency>

(2) 添加log4j.properties配置文件(前文已经提过,这里不再重复)

(3) 使用统一代码

3. slf4j与log4j2兼容

(1) 添加slf4j与log4j2桥接器

xml 复制代码
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j-impl</artifactId>
  <version>2.17.2</version>
</dependency>

(2) 添加log4j2.xml配置文件(前文已经提到,这里不再重复)

(3) 使用统一代码

统一代码:

arduino 复制代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Slf4jTest {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
        logger.info("Slf4Test");
    }
}

我这里只是做一个示范,我们可以直接使用这套代码,把slf4jjar包导入进来了然后想使用那个日志框架只需要导入与slf4j的桥接器配置对应文件即可,因为logback是slf4j自己的日志框架,所以在使用logback日志框架只需要导入对应jar包配置文件即可.

四 slf4j实现统一输出

在一个project里面,可能会使用到了很多日志框架,那么怎么在不修改源代码的情况下将他们统一输出呢?答案是使用"适配器"

举个例子: 一个project中模块一使用了log4j,模块二使用了slf4j+log4j2,这是我们为了统一,在不修改源代码的情况下,添加一个log4j和slf4j的适配器,原理就是程序本身要调用log4j的API,但是遇到了log4j和slf4j适配器之后被"拦截",直接调用slf4j日志门面对应框架的API,因为这里假设的是slf4j+log4j2,所以模块一使用日志会直接使用slf4j+log4j2中的API,从而达到了大一统.

1. log4j和slf4j适配器
xml 复制代码
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>log4j-over-slf4j</artifactId>
  <version>1.7.30</version>
</dependency>

切记: 如果使用了log4j适配器,那么要么把适配器放在log4j包的前面,或者把log4j包删除,保证适配器能够拦截到.

2. jcl和slf4j的适配器
xml 复制代码
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jcl-over-slf4j</artifactId>
  <version>1.7.32</version>
</dependency>

在这里使用了jcl,所以必须把jcl包导入进来,同时,因为jcl性质,会先找到log4j,如果log4j不存在,才会去找jul,再把对应的日志API通过适配器拦截到slf4j里面

五 SpringBoot日志

SpringBoot默认是slf4j+logback日志的,在"场景启动器"里面,不需要我们手动导入,可以直接使用

1. 简单使用日志

如果大家导入了lombok包,在使用slf4j日志的时候可以不需要实例化类,通过@Slf4j注解

2. SpringBoot日志框架改变(slf4j+logback--slf4j+log4j2)

(1) 在场景启动器里面修改logback--log4j2

xml 复制代码
 <!--引入Log4j2的场景启动器-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

这一步是将logback依赖踢出去,然后将log4j2场景启动器导入进来

(2) 添加配置文件(log4j2.xml)

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>
3. SpringBoot日志转换(slf4j+logback-->slf4j+log4j)

(1) 排除logback桥接器

xml 复制代码
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>logback-classic</artifactId>
                    <groupId>ch.qos.logback</groupId>
                </exclusion>
            </exclusions>
        </dependency>

(2) 添加log4j桥接器

xml 复制代码
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.30</version>
</dependency>

(3) 添加log4j.properties配置文件(上文已经讲过,不重复)

  1. 自定义日志配置文件(logback.xml,约定大于配置)
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
    <contextName>logback</contextName>
    <property name="log.path" value="d:/data/applogs/xxl-job/xxl-job-executor-sample-springboot.log"/>
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
            </pattern>
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>
    <logger name="com.cctv" level="debug" />
</configuration>

自定义配置文件讲解:

(1) property用来这只变量,name表示变量名,value表示值

(2) appender有两个属性,name和class,name表示输出在控制台还是以文件的形式,class表示对应的类

(3) appender-ref: 表示输出那种,如果只有一个就输出一个,如果有多个就输出多个.比如图中就有file和console,这个就是说明日志输出在控制台同时生成文件.

(4) root level: 表示root是一个什么样的日志级别(trace<debug<info<warn<error),logger可以通过name和level指定对应模块的日志级别

(5) encoder和pattern用来输出日志具体格式

(6) rollingPolicy日志回滚策略: 图中用了TimeBasedRollingPolicy(基于时间的回滚策略),fileNamePattern是必要节点,我们将日志压缩成一个zip包.

相关推荐
许野平1 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
齐 飞2 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
LunarCod3 小时前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
码农派大星。3 小时前
Spring Boot 配置文件
java·spring boot·后端
杜杜的man4 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*4 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu4 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s4 小时前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子4 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
想进大厂的小王4 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构