springboot+logback学习文档

news2024/12/24 6:26:40

目录

  • 1、前提说明
  • 2、引入依赖、将logback配置文件打到classes下
    • 2.1、引入依赖
    • 2.2、将logback配置文件打到classes下
  • 3、使用说明
    • 3.1、配置文件名称和位置
    • 3.2、常规用法
      • 3.2.1、property标签(普通变量)
      • 3.2.2、springProperty标签(spring变量)
      • 3.2.3、conversionRule标签(通过代码来自定义数据规则)
      • 3.2.4、include标签(引入配置文件)
      • 3.2.5、root标签(定义全局的日志输出情况)
      • 3.2.5、logger标签(定义特定包或者类的日志输出情况)
      • 3.2.6、springProfile标签(根据spring环境输出日志)
      • 3.2.7、appender标签(定义日志输出方式)
        • 3.2.7.1、日志格式
        • 3.2.7.2、日志输出策略—控制台输出
        • 3.2.7.3、日志输出策略—文件滚动输出
        • 3.2.7.4、日志输出策略—异步输出(非必须,默认是同步输出)
  • 4、代码用法
  • 5、使用案例
  • 6、参考博客

1、前提说明

  • 默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台。
  • Slf4j(Simple Logging Facade For Java):它是一个针对于各类Java日志框架的统一外观抽象(门面模式)。
  • 日志级别:TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。

2、引入依赖、将logback配置文件打到classes下

2.1、引入依赖

<!-- 启动依赖中包含了spring-boot-starter-logging依赖,进而包含了logback相关依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<!-- 引入@Slf4j注解,方便使用log.XXX()方法 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

2.2、将logback配置文件打到classes下

<!-- 在 -->
<build>
    <resources>
        <!-- 将resources目录中的配置文件统统打包 -->
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
        <!-- 将代码目录中的xml文件一并打包,针对将included标签引入的配置文件放在依赖jar包代码层的情况 -->
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
</build>

3、使用说明

3.1、配置文件名称和位置

名称

  • logback-spring.xml
  • logback-spring.groovy
  • logback.xml
  • logback.groovy
  • 自定义文件名

说明1:Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml),命名为logback-spring.xml的日志配置文件,spring boot可以为它添加一些spring boot特有的配置项(下面会提到)。

说明2:在application.properties配置文件里面通过logging.config属性指定自定义的名字,例如 logging.config=classpath:logging-config.xml

位置:

src > main > resources目录下面,例如:

在这里插入图片描述

3.2、常规用法

3.2.1、property标签(普通变量)

# 语法
<property name="变量名" value="变量值"/>

# 使用范围
在所有logback的xml文件中都可以使用,包括使用include标签引入的文件中;
可以把一个项目中所有位置的logback的xml文件内容理解成一个合体大文件,
所以变量可以在各个文件中随意定义、随意使用,但是注意别重复了。

# 定义示例
<!-- 定义服务名称 -->
<property name="app_name" value="item"/>
<!-- 定义日志输出格式 -->
<property name="log.pattern" value="%date{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | %thread | %logger{56}.%method | %L : %msg%n" />


# 使用示例(即${变量名},此时变量LOG_PATH代表“/opt/log/item”)
<!-- 在其他变量中使用 -->
<property name="LOG_PATH" value="/opt/log/${app_name}"/>
<!-- 将日志按照定义的日志输出格式输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>${log.pattern}</pattern>
        <charset>utf-8</charset>
    </encoder>
</appender>

3.2.2、springProperty标签(spring变量)

# 语法
<springProperty name="变量名" value="spring配置属性"/>

# 使用范围
在spring环境中使用

# 定义示例
<!-- 定义服务名称 -->
<springProperty name="app_name" source="spring.application.name"/>
<!-- 定义端口 -->
<springProperty name="server_port" source="server.port" />

# 使用示例(即${变量名},此时变量LOG_PATH代表“/opt/log/item”)
<!-- 定义日志文件输出路径 -->
<property name="LOG_PATH" value="/opt/log/${app_name}"/>
<!-- 定义日志输出格式 -->
<property name="log.pattern" value="%date{yyyy-MM-dd HH:mm:ss.SSS} | ${app_name} | %-5level | %thread | %logger{56}.%method | %L : %msg%n" />

3.2.3、conversionRule标签(通过代码来自定义数据规则)

# 语法(该变量的值指代该类中convert方法的返回值)
<conversionRule conversionWord="变量名" converterClass="ClassicConverter类的子类全路径"/>

# 定义示例
<!-- 获取本地服务的IP,LogIpConfig类的详细代码在下面 ->
<conversionRule conversionWord="app_ip" converterClass="com.atguigu.base.config.LogIpConfig"/>

# 使用示例(即$变量名,此时变量$app_ip代表真实ip)
<!-- 定义日志输出格式 -->
<property name="log.pattern" value="%date{yyyy-MM-dd HH:mm:ss.SSS} | %app_ip | ${app_name} | %-5level | %thread | %logger{56}.%method | %L : %msg%n" />

# 打印结果
2024-12-19 22:54:32.466 | 192.168.1.6 | item | INFO  | main | com.atguigu.item.init.SystemInit.afterPropertiesSet | 29 : 测试……

LogIpConfig:

import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetAddress;

/**
 * 打印ip类
 * @author 明快de玄米61
 * @date   2024/12/9 9:15
 **/
public class LogIpConfig extends ClassicConverter {

    private static final Logger logger = LoggerFactory.getLogger(LogIpConfig .class);

    private static String webIP;
    static {
        try {
            webIP = InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            logger.error("获取日志Ip异常", e);
            webIP = null;
        }
    }

    @Override
    public String convert(ILoggingEvent event) {
        return webIP;
    }
}

3.2.4、include标签(引入配置文件)

通过include标签可以将依赖jar包中的配置文件引入当前项目,这样所有配置文件内容将组装成一个合体大文件,不过注意被引入文件中标签的书写方式

在这里插入图片描述

3.2.5、root标签(定义全局的日志输出情况)

作用:

  1. 定义日志输出级别(日志级别:TRACE < DEBUG < INFO < WARN < ERROR < FATAL
  2. 引入自定义日志输出规则(等会介绍具体输出规则的定义方式)

示例:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    ……
    <!-- 控制打印输出的内容 -->
    <root level="INFO">
        <!-- 打印ERROR级别日志到文件中 -->
        <appender-ref ref="FILE_ERROR"/>

        <!-- 打印WARN级别日志到文件中 -->
        <appender-ref ref="FILE_WARN"/>

        <!-- 打印INFO级别日志到文件中 -->
        <appender-ref ref="FILE_INFO"/>

        <!-- 打印level以及以上级别的日志到控制台中-->
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

3.2.5、logger标签(定义特定包或者类的日志输出情况)

参数说明:

  1. name(必填):指定受此logger约束的某一个包或者具体的某一个类
  2. level(非必填,默认值:继承root标签的level):日志级别
  3. additivity(非必填,默认值:true):是否向上级logger传递打印信息,也就是让上级也去处理该打印结果,当然与上级的level级别无关

作用:

  1. 定义特定包或者类的日志输出级别(日志级别:TRACE < DEBUG < INFO < WARN < ERROR < FATAL
  2. 引入自定义日志输出规则(等会介绍具体输出规则的定义方式)

示例:

logback-msg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<included>

    <!-- DEBUG日志记录器,日期滚动记录 -->
    <appender name="MSG_PRODUCER_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/mq/producer/log.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/mq/producer/log-%d{yyyy-MM-dd}_%i.log</fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过20M,若超过20M,日志文件会以索引0开始, 命名日志文件,例如log_error_2020-20-20_0.log -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>20MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <MaxHistory>7</MaxHistory>
        </rollingPolicy>

        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志文件的格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${log.pattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
    </appender>

    <logger name="com.atguigu.msg" level="DEBUG" additivity="false">
        <appender-ref ref="MSG_PRODUCER_FILE" />
    </logger>

</included>

在上述logback-msg.xml所在的项目msg代码中有这样一行代码:

log.debug("消息被发送到kafka了");

如果按照logback文件配置情况,将会把日志信息输出到文件中

由于additivity是false,所以日志信息不会向上传递,假设上级日志配置文件中root标签的level是INFO级别,那么这种情况下日志不会输出的

如果additivity是true,或者不设置(默认是true),依然假设上级日志配置文件中root标签的level是INFO级别,并且上级日志配置文件中会将所有日志信息输出到控制台,此时日志将在控制台输出,如下图:

在这里插入图片描述

3.2.6、springProfile标签(根据spring环境输出日志)

根据不同环境(prod:生产环境,test:测试环境,dev:开发环境)来定义不同的日志输出,在 logback-spring.xml中使用 springProfile 节点来定义,方法如下:

文件名称不是logback.xml,想使用spring扩展profile支持,要以logback-spring.xml命名

<!-- 测试环境+开发环境. 多个使用逗号隔开. -->
<springProfile name="test,dev">
    <logger name="com.dudu.controller" level="info" />
</springProfile>
<!-- 生产环境. -->
<springProfile name="prod">
    <logger name="com.dudu.controller" level="ERROR" />
</springProfile>

可以启动服务的时候指定 profile (如不指定使用默认),如指定prod 的方式为:

java -jar xxx.jar –spring.profiles.active=prod

3.2.7、appender标签(定义日志输出方式)

3.2.7.1、日志格式

一般情况下,通过pattern标签定义日志输出格式,如下:

<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | %thread | %logger{56} | %L : %msg%n</pattern>
        <charset>utf-8</charset>
    </encoder>
</appender>

现在来讲解一下上面日志输出格式的含义:

  • %date{yyyy-MM-dd HH:mm:ss.SSS}:年-月-日 时:分:秒 毫秒
  • %-5level:日志级别,一共占用5个字符,并且靠左对齐
  • %thread:线程名称
  • %logger{56}:类全路径名称
  • %L:日志所在代码的行数
  • %msg:日志内容
  • %n:换行符
3.2.7.2、日志输出策略—控制台输出

使用方式:

<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | %thread | %logger{56} | %L : %msg%n</pattern>
        <charset>utf-8</charset>
    </encoder>
</appender>

输出效果:

2024-12-23 12:11:43.947 | INFO  | main | com.atguigu.item.init.SystemInit.afterPropertiesSet | 18 : 测试……

对应输出日志代码,如下所示:

在这里插入图片描述

解释:

  • name:自己取的名字,可以在root标签或者logger标签下面的appender-ref标签中引用
  • class:使用ch.qos.logback.core.ConsoleAppender类可以将日志内容输出到控制台
  • encoder.pattern:日志内容输出格式,在上一章节讲过了
  • encoder.charset:字符编码
3.2.7.3、日志输出策略—文件滚动输出

下面介绍“基于时间和日志文件大小来进行日志滚动输出到文件”

<!-- DEBUG日志记录器,日期滚动记录 -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 正在记录的日志文件的路径及文件名 -->
    <file>${LOG_PATH}/log_error.log</file>
    
    <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <!-- 备份记录的日志文件的路径及文件名,其中%d{yyyy-MM-dd}代表年--日(区分不同日期),而%i代表序号(用来区分同一天的不同文件) -->
        <fileNamePattern>${LOG_PATH}/error/error-%d{yyyy-MM-dd}_%i.log</fileNamePattern>
        <!-- 单个日志文件最大数据量,例如下面代表日志文件不能超过20M,若超过20M,日志文件会以索引0开始来命名日志文件,例如log_error_2020-20-20_0.log -->
        <maxFileSize>20MB</maxFileSize>
        <!-- 日志文件最大容量 -->
        <totalSizeCap>10GB</totalSizeCap>
        <!--日志文件保留天数-->
        <MaxHistory>7</MaxHistory>
    </rollingPolicy>

    <!-- 以追加方式记录日志 -->
    <append>true</append>
    
    <!-- 日志格式 -->
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <!-- 日志输出格式 -->
        <pattern>${log.pattern}</pattern>
        <charset>utf-8</charset>
    </encoder>
    
    <!-- 根据日志级别过滤;此日志文件只记录error级别的 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>ERROR</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
</appender>

其实没有太多可以解释的,在示例中已经注释清晰了,最顶级的appenderclass就是ch.qos.logback.core.rolling.RollingFileAppender,代表滚动输出到文件中,下面介绍一下内部的标签:

  • file:记录实时日志输出文件路径
  • rollingPolicy:定义日志文件备份策略
  • append:定义日志追加方式
  • encoder:定义日志输出格式
  • filter:根据日志级别过滤,控制日志输出级别
3.2.7.4、日志输出策略—异步输出(非必须,默认是同步输出)

logback提供了大量的Appender将日志输出到指定的位置。如ConsoleAppender用于同步地将日志输出到控制台,FileAppender用于同步地将日志输出到指定日志文件,SocketAppender用于同步地将日志通过套接字发送到指定服务器。他们都有一个共同点:同步。

那么如何修改日志配置文件将日志输出改为异步呢?logback提供了一个Appender的异步实现类:AsyncAppender。使用方法也非常简单,同样也是通过在配置文件中添加<appender>标签声明AsyncAppender,然后通过引用属性引用一个同步Appender即可,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <!-- 日志输出格式 -->
    <property name="log.pattern"
              value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/>

    <!-- 同步输出到控制台 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>

    <!-- 异步输出 -->
    <appender name="async-console" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 引用同步,将其包装为异步 -->
        <appender-ref ref="console" />
    </appender>

    <!-- 采用异步输出 -->
    <root level="INFO">
        <appender-ref ref="async-console" />
    </root>
    
</configuration>

虽然示例中是控制台输出,但是也支持配合文件输出使用

为什么给同步Appender包装一层AsyncAppender就可以实现异步输出呢?

AsyncAppender内部维护了一个阻塞队列ArrayBlockingQueuelogback将我们打印日志的代码log.info("第一条日志")封装为一个事件Event,每当我们需要打印一行日志时,logback会将该事件放在阻塞队列中,然后再通过多线程的形式从该阻塞队列中获取一个事件执行。

阻塞队列可以保证日志的输出是有序的,多线程保证日志的输出是异步的。

4、代码用法

  1. 在类上添加@Slf4j注解
  2. 通过静态常量log来调用info、warn、error等方法,例如:log.info("测试……");

5、使用案例

链接: https://pan.baidu.com/s/1eH1ZcaVdqKQuLp7hIq-cgA?pwd=3vd7

提取码: 3vd7

6、参考博客

  • Spring Boot干货系列:(七)默认日志logback配置解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2264578.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Laya ios接入goole广告,开始接入 2

开始使用 | iOS | Google for Developers 谷歌广告的官网&#xff0c;需要搭梯子&#xff0c;API你说详细吧&#xff0c;也就那样&#xff0c;主要是没接过 一步步来吧 0.laya导包 前端出包原生 screenorientation 全部 portrait&#xff0c;我这个是竖屏的 注意这个&a…

详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用

目录 详解js柯里化原理及用法&#xff0c;探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用 一、什么是柯里化&#xff1f; 1、原理解析 2、一个直观的例子 二、如何实现柯里化&#xff1f; 1、底层实现 2、工作原理解析 3…

EDGE浏览器每次关闭时再次打开保存的密码就消失如何解决

文章目录 EDGE浏览器每次重启的时候保存的密码都消失如何解决&#xff1f; 打开EDGE浏览器点击三个点 点击设置 点击隐私、搜索和服务 找到选择每次关闭浏览器时要清除的内容 将开启的关闭即可

数据流图和流程图的区别

在结构化建模中&#xff0c;数据流图和流程图都是非常重要的工具&#xff0c;它们为开发人员提供了强大的手段来分析和设计系统。尽管两者在表面上看起来有些相似&#xff0c;但它们在功能、用途和表达方式上存在显著的区别。本文将详细探讨数据流图和流程图的区别&#xff0c;…

云计算中的容器技术(如Docker)是什么?

今天想和大家聊聊容器技术&#xff0c;特别是Docker这个大家可能经常听到的名词。记得我刚接触容器技术时也觉得挺抽象的&#xff0c;让我用简单的比喻来说明吧。 想象一下你在搬家。传统方式是把所有家具、电器分散装车&#xff0c;到了新家还要重新组装、调试。这就像我们以…

《Opencv》基础操作详解(2)

接上篇&#xff1a;《Opencv》基础操作详解&#xff08;1&#xff09;-CSDN博客 目录 Opencv基础操作 11、B、G、R颜色通道提取 12、显示单个通道颜色 13、 合并颜色通道 14、图像添加马赛克 15、图片区域替换 16、图片的缩放&#xff08;常用&#xff09; 17、图像运算…

STM32——“SPI Flash”

引入 在给单片机写程序的时候&#xff0c;有时会用到显示屏&#xff0c;就拿市面上的0.96寸单色显示器来说&#xff0c;一张全屏的图片就占用8x1281024个字节&#xff0c;即1kb的空间&#xff0c;这对于单片机来说确实有点奢侈&#xff0c;于是我买了一个8Mb的SPI Flash&#x…

深入浅出:AWT的基本组件及其应用

目录 前言 1. AWT简介 2. AWT基本组件 2.1 Button&#xff1a;按钮 2.2 Label&#xff1a;标签 ​编辑 2.3 TextField&#xff1a;文本框 2.4 Checkbox&#xff1a;复选框 2.5 Choice&#xff1a;下拉菜单 2.6 List&#xff1a;列表 综合案例 注意 3. AWT事件处理 …

Flutter组件————PageView

PageView 可以创建滑动页面效果的widget&#xff0c;它允许用户通过水平或垂直滑动手势在多个子页面&#xff08;child widgets&#xff09;之间切换。每个子页面通常占据屏幕的全部空间。 参数 参数名类型描述childrenList<Widget>包含在 PageView 中的所有子部件&am…

三种电子画册制作方法

今天教大家三种电子画册的制作方法&#xff0c;很容易上手&#xff0c;需要的赶紧收藏起来 一、 利用在线平台--FLBOOK 1.注册并登录在线平台。 2.选择喜欢的模板&#xff0c;根据需求进行修改 3.批量上传PDF文件一键转换H5翻页电子画册 4.添加图片、文字等元素&#xff0c…

以太坊账户详解

文章目录 一、账户基本概念1.1 外部账户1.2 合约账户1.3 差异对比 二、帐户创建2.1 外部账户创建2.2 合约账户创建 三、账户数据结构3.1 账户状态3.2 账户状态结构 对比比特币的 “UTXO” 余额模型&#xff0c;以太坊使用“账户”余额模型。 以太坊丰富了账户内容&#xff0c;除…

AWS Transfer 系列:简化文件传输与管理的云服务

在数字化转型的今天&#xff0c;企业对文件传输、存储和管理的需求日益增长。尤其是对于需要大量数据交换的行业&#xff0c;如何高效、可靠地传输数据成为了一大挑战。为了解决这一难题&#xff0c;AWS 提供了一系列的文件传输服务&#xff0c;统称为 AWS Transfer 系列。这些…

基础I/O -> 如何谈文件与文件系统?

文件的基础理解 空文件也要在磁盘上占据空间。文件 文件内容文件属性。文件操作 对内容的操作 对属性的操作或者是对内容和属性的操作。标定一个文件&#xff0c;必须使用&#xff1a;文件路径 文件名&#xff08;具有唯一性&#xff09;。如果没有指明对应的文件路径&…

网络安全检测

实验目的与要求 (1) 帮助学生掌握木马和入侵的防护和检测方法、提高学习能力、应用能力和解决实际问题的能力。 (2) 要求学生掌握方法, 学会应用软件的安装和使用方法, 并能将应用结果展示出来。 实验原理与内容 入侵检测是通过对计算机网络或计算机系统中若干关键点收集信…

谷歌浏览器的资源管理功能详解

谷歌浏览器作为一款广受欢迎的网页浏览器&#xff0c;不仅以其快速、简洁和易用著称&#xff0c;还提供了强大的资源管理功能。本文将详细介绍如何在Chrome浏览器中进行资源管理&#xff0c;包括查看网页的渲染性能、禁用标签页的背景更新以及管理正在下载的文件。&#xff08;…

ARM异常处理 M33

1. ARMv8-M异常类型及其详细解释 ARMv8-M Exception分为两类&#xff1a;预定义系统异常(015)和外部中断(1616N)。 各种异常的状态可以通过Status bit查看&#xff0c;获取更信息的异常原因&#xff1a; CFSR是由UFSR、BFSR和MMFSR组成&#xff1a; 下面列举HFSR、MMFSR、…

Unity2021.3.16f1可以正常打开,但是Unity2017.3.0f3却常常打开闪退或者Unity2017编辑器运行起来就闪退掉

遇到问题&#xff1a; 从今年开始&#xff0c;不知道咋回事&#xff0c;电脑上的Unity2017像是变了个人似得&#xff0c;突然特别爱闪退掉&#xff0c;有时候还次次闪退&#xff0c;真是让人无语&#xff0c;一直以来我都怀疑是不是电脑上安装了什么别的软件了&#xff0c;导致…

SpringBoot核心:自动配置

有使用过SSM框架的&#xff0c;还记得曾经在spring-mybatis.xml配置了多少内容吗&#xff1f;数据源、连接池、会话工厂、事务管理&#xff0c;而现在Spring Boot告诉你这些都不需要了&#xff0c;简单的几个注解统统搞定&#xff0c;是不是很方便&#xff01; 前言 SpringBoo…

重温设计模式--享元模式

文章目录 享元模式&#xff08;Flyweight Pattern&#xff09;概述享元模式的结构C 代码示例1应用场景C示例代码2 享元模式&#xff08;Flyweight Pattern&#xff09;概述 定义&#xff1a; 运用共享技术有效地支持大量细粒度的对象。 享元模式是一种结构型设计模式&#xff0…

Taro小程序开发性能优化实践

我们团队在利用Taro进行秒送频道小程序的同时&#xff0c;一直在探索性能优化的最佳实践。随着需求的不断迭代&#xff0c;项目中的性能问题难免日积月累&#xff0c;逐渐暴露出来影响用户体验。适逢双十一大促&#xff0c;我们趁着这个机会统一进行了Taro性能优化实践&#xf…