Logback日志框架使用详解以及如何Springboot快速集成

news2025/1/11 2:23:11

Logback简介

日志系统是用于记录程序的运行过程中产生的运行信息、异常信息等,一般有8个级别,从低到高为All < Trace < Debug < Info < Warn < Error < Fatal < OFF

  1. off 最高等级,用于关闭所有日志记录
  2. fatal 指出每个严重的错误事件将会导致应用程序的退出。
  3. error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
  4. warn 表明会出现潜在的错误情形。
  5. info 一般和在粗粒度级别上,强调应用程序的运行全程。
  6. debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
  7. trace 该级别日志,默认情况下,既不打印到终端也不输出到文件。此时,对程序运行效率几乎不产生影响
  8. all 最低等级,用于打开所有日志记录。

Logback和Log4j都是为Java应用程序提供的比较流行的开源日志框架,它们都由同一个开发者创建和维护,但在功能和性能上存在一些差异,Logback可以认为是log4j的改进版,在性能、配置应用上都要优于log4j,Logback主要由三个模块构成:logback-core,logback-classic和logback-access。其中,logback-core是其他两个模块的基础,提供了Logback的核心功能。logback-classic模块实现了简单日志门面SLF4J,而logback-access模块则主要作为一个与Servlet容器交互的模块,提供与HTTP访问相关的一些功能。

Logback配置详解

Spring Boot默认是使用Logback的,并且提供了自动配置,默认使用logback-spring.xml作为配置文件的名称,当然,也可以在application.properties或application.yml中配置。下面分享一下logback-spring.xml中常用的一些标签。

configuration

configuration为根节点,有scan、scanPeriod、debug三个属性;

  1. scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
  2. scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
  3. debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
<configuration scan="true" scanPeriod="60 seconds" debug="false">  
      <!-- 其他配置省略-->  
</configuration>

property

property是configuration的子标签,有两个属性name和value:name变量的名称,value变量的值。

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- logback项目名称 -->
    <property name="appName" value="logback-demo"></property>
    <!-- 日志级别 DEBUGER INFO WARN ERROR -->
    <property name="logLevel" value="trace"></property>
    <!-- 日志路径-->
    <property name="logPath" value="/logs"></property>
    <!-- 最大保存时间 60天-->
    <property name="maxHistory" value="60"/>
</configuration>

logger

logger节点,可选节点,作用是指明具体的包或类的日志输出级别,以及要使用的;

  1. name:必写属性,指定具体包或类,被指定的包或类中的日志输出将遵从该logger规定配置;
  2. level:非必写属性,指定日志输出级别,该级别将覆盖root配置的输出级别;
  3. addtivity:非必写属性,是否向上级loger传递打印信息,默认是true;
  4. appender-ref:引用的appender,引用后将实现appender中定义的行为。一个logger可以有多个引用,互不影响;

root

root节点,必选节点,用来指定最基础的日志输出级别并指定,可以理解为根logger。

appender

appender是configuration的子节点,也是非常关键的一个节点,它有两个必要属性name和class,name指定appender名称,class指定appender的全限定名。

appender有四种类型,如下(其中第四种比较特殊,后面再说):

  1. ConsoleAppender(控制台日志)
  2. FileAppender(文件日志)
  3. RollingFileAppender(滚动文件日志)
  4. AsyncAppender(异步日志)

appender内的有一个子标签encoder,有两个作用,一是把日志信息转换成字节数组,二是把字节数组写入到输出流,可以用于定义输出日志内容的编码格式、日志格式;其中endcoder内的子标签charset用于定义输出日志内容的编码格式,子标签pattern用于定义输出日志的具体格式;

  1. %date:表示日期
  2. %thread:表示线程名
  3. %-5level:表示级别从左显示 5 个字符宽度
  4. %logger{36}:表示 Logger 名字最长 36 个字符
  5. %msg:表示日志消息
  6. %n:换行符
  7. %line:表示当前日志事件的行号
ConsoleAppender
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- logback项目名称 -->
    <property name="appName" value="logback-demo"></property>
    <!-- 日志级别 DEBUGER INFO WARN ERROR -->
    <property name="logLevel" value="INFO"></property>
    <!-- lOGGER  PATTERN 根据个人喜好选择匹配  -->
    <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n"></property>
    <!-- 控制台的标准输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${logPattern}</pattern>
        </encoder>
    </appender>
    <root level="${logLevel}">
        <appender-ref ref="console"/>
    </root>
</configuration>
FileAppender与RollingFileAppender

FileAppender与RollingFileAppender都是用于将日志写入文件的组件,配置属性基本相同,因此这里放在一起来说,但是需要注意的是二者在日志文件处理方式上有所不同,FileAppender将所有的日志信息写入一个指定的文件中,当文件达到一定大小或时间点时,它会被新的日志文件所替代。而RollingFileAppender则会在日志文件达到指定大小时,创建新的日志文件继续写入,并且保留一定数量的旧日志文件。

以下是RollingFileAppender和FileAppender的主要区别:

RollingFileAppender:

  1. 日志滚动:当日志文件达到指定大小时,RollingFileAppender会自动创建一个新的日志文件,并将当前日志文件中的内容复制到新文件中。新创建的日志文件的名称会加上一个时间戳或索引号,以便区分。
  2. 日志文件保留:RollingFileAppender可以设置保留的日志文件数量。当超过这个数量时,最早创建的日志文件会被自动删除。
  3. 日志索引:RollingFileAppender还可以生成一个索引文件,用于记录所有滚动日志文件的名称和位置信息。这样可以在需要查看历史日志时,快速定位到需要的日志文件。

FileAppender:

  1. 日志输出:FileAppender将日志输出到一个指定的文件中,不进行滚动操作。当文件达到一定大小限制时,FileAppender会停止写入新的日志信息,并创建一个新的日志文件继续写入。
  2. 日志文件命名:FileAppender可以设置日志文件的名称和位置,但不会像RollingFileAppender那样添加时间戳或索引号。
  3. 需要注意的是,RollingFileAppender和FileAppender在配置上略有不同。例如,RollingFileAppender需要指定日志文件的最大大小和保留数量,而FileAppender则需要指定日志文件的最大大小和文件数量等参数。

另外这里着重说一下maxFileSize和maxHistory,以及filter标签,maxFileSize 是用来限制单个日志文件的最大大小。例如,如果你设置 maxFileSize 为 10MB,那么当日志文件达到 10MB 时,Logback 会开始创建新的日志文件(例如,app.log.1,app.log.2,等等)。旧的日志文件将被保留,直到达到配置的 maxHistory 天数。

而 totalSizeCap 是用来限制所有日志文件的总大小。例如,如果你设置 totalSizeCap 为 1GB,那么当所有日志文件的总大小达到 1GB 时,Logback 会开始删除旧的日志文件,以便为新的日志文件腾出空间。这个属性对于防止日志文件占用过多的磁盘空间非常有用。

注意,totalSizeCap 和 maxFileSize 不建议同时使用。如果同时设置,totalSizeCap 将优先于 maxFileSize。也就是说,当达到 totalSizeCap 时,将删除旧的日志文件,无论这些文件是否达到了 maxFileSize。

在Logback中,filter标签用于过滤日志消息。通过在filter标签中定义条件,可以实现对日志消息的筛选和拦截,实现根据指定的条件来控制哪些日志消息应该被记录。

  1. filter标签有三种类型:onMatch、onMismatch和always。这些类型决定了在过滤器匹配或不匹配时应该执行的操作。
  2. onMatch:当过滤器条件匹配时执行的操作。通常,你可以将其设置为记录匹配的日志消息或采取其他所需的操作。
  3. onMismatch:当过滤器条件不匹配时执行的操作。通常情况下,你可以将其设置为记录不匹配的日志消息或采取其他所需的操作。
  4. always:无论过滤器条件是否匹配,都会执行的操作。这通常用于对日志消息进行一些通用的处理或记录。

在下面的示例中,我们使用了一个名为ThresholdFilter的过滤器,它根据日志级别进行过滤。我们将level属性设置为info,这意味着只有级别为info及以上的日志消息会被记录到文件中,其他级别的日志消息将被拦截。

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- logback项目名称 -->
    <property name="appName" value="logback-demo"></property>
    <!-- 日志级别 DEBUGER INFO WARN ERROR -->
    <property name="logLevel" value="info"></property>
    <!-- lOGGER  PATTERN 根据个人喜好选择匹配  -->
    <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n"></property>
    <!-- 日志路径-->
    <property name="logPath" value="./logs"></property>
    <!-- 最大保存时间 60天-->
    <property name="maxHistory" value="60"/>
    <!-- 控制台的标准输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${logPattern}</pattern>
        </encoder>
    </appender>
    <!-- INFO 级别的日志记录  -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logPath}/${appName}_info.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${logPath}/${appName}_info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 限制单个日志文件的大小-->
            <maxFileSize>10MB</maxFileSize>
           <!--最大保存时间-->
            <maxHistory>${maxHistory}</maxHistory>
            <!-- 所有日志文件总大小的限制-->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>${logPattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <root level="${logLevel}">
        <appender-ref ref="console"/>
        <appender-ref ref="file_info"/>
    </root>
</configuration>
AsyncAppender

上面已经说了,四种类型的appender,AsyncAppender比较特殊,特殊就在于记录日志时从同步或异步的角度来看,前三者属于同步日志,后者属于异步日志。Logback的同步日志是立即写入磁盘的日志,而异步日志是通过线程池异步处理写入磁盘的日志。

Logback异步输出的原理是:先写入到缓冲区,当缓冲区满了或者达到一定时间,再把缓冲区的数据一次性写入磁盘,这样可以减少磁盘IO操作,提高性能。

Logback异步输出的配置是:配置一个,例如,然后在中配置一个,表示缓冲区的大小,再配置一个,表示缓冲区达到这个阈值时,会触发一个强制写入磁盘的操作。

  1. queueSize:控制阻塞队列大小,使用的ArrayBlockingQueue阻塞队列,默认容量256:内存中最多保存256条日志
  2. discardingThreshold:丢弃日志的阈值,为防止队列满后发生阻塞。默认队列剩余容量 < 队列长度的20%,就会丢弃TRACE、DEBUG和INFO级日志;若discardingThreshold = 0,那么队列满时再有日志写入就会阻塞。若discardingThreshold != 0,也只丢弃≤INFO级日志,出现大量错误日志时,还是会阻塞。
  3. neverBlock:控制队列满时,加入的数据是否直接丢弃,不会阻塞等待,默认是false;队列满时:offer不阻塞,而put会阻塞;neverBlock为true时,使用offer

在《基于Redis实现消息队列的实践》遇到的明明程序执行结果正常,就是看不到过程日志,最后的解决办法就使用了logback的异步日志,有兴趣的小伙伴可移步参考一下。

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- logback项目名称 -->
    <property name="appName" value="logback-demo"></property>
    <!-- 日志级别 DEBUGER INFO WARN ERROR -->
    <property name="logLevel" value="info"></property>
    <!-- lOGGER  PATTERN 根据个人喜好选择匹配  -->
    <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n"></property>
    <!-- 日志路径-->
    <property name="logPath" value="./logs"></property>
    <!-- 最大保存时间 60天-->
    <property name="maxHistory" value="60"/>
    <!-- 异步缓冲队列的深度,该值会影响性能.默认值为256 -->
    <property name="queueSize" value="512"></property>

    <!-- 控制台的标准输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <pattern>${logPattern}</pattern>
        </encoder>
    </appender>
    <!-- INFO 级别的日志记录  -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logPath}/${appName}_info.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${logPath}/${appName}_info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 限制单个日志文件的大小-->
            <maxFileSize>10MB</maxFileSize>
           <!--最大保存时间-->
            <maxHistory>${maxHistory}</maxHistory>
            <!-- 所有日志文件总大小的限制-->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>${logPattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <appender name="async_log_info" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>${queueSize}</queueSize>
        <!-- 设置该属性 logback 会使用 ArrayBlockingQueue 的非阻塞方法 offer 代替 put, 防止在队列满时阻塞业务线程 -->
        <neverBlock>true</neverBlock>
        <appender-ref ref="file_info"/>
    </appender>
    <root level="${logLevel}">
        <appender-ref ref="console"/>
        <appender-ref ref="file_info"/>
        <appender-ref ref="async_log_info"/>
    </root>
</configuration>

Logback与Springboot

引入依赖

如果项目是Springboot项目,默认已经引入,不需要额外引入依赖,如果确实需要,可参考:

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.11</version>        
    </dependency>

配置文件

配置文件命名

在Springboot项目中,默认的配置文件名称是logback-spring.xml,官方也推荐使用这样的命名方式,logback本身默认的配置文件名称是logback.xml

配置文件加载顺序

在工程resources目录下建立logback.xml,配置文件的加载顺序是:

  1. logback首先会试着查找logback.groovy文件;
  2. 当没有找到时,继续试着查找logback-test.xml文件;
  3. 当没有找到时,继续试着查找logback.xml文件,如果是Springboot项目,则找logback-spring.xml;
  4. 如果仍然没有找到,则使用默认配置(打印到控制台);

程序中注入logger

在程序中注入logger有两种方式:

  1. final static Logger logger = LoggerFactory.getLogger(“名称”);
@Component
public class DemoTask {
    private final static Logger logger= LoggerFactory.getLogger(DemoTask.class);

    @Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
    public void test() {
        logger.info("-------------");
        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
        logger.warn("warn");
        logger.error("error");
        logger.info("-------------");
    }
}
  1. @Sl4j注解:如果引入了lombok可以在类上标记@Sl4j,Lombok会在类中自动生成一个名为log的静态final成员变量;
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
@Component
@Slf4jj
public class DemoTask {
    @Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
    public void test() {
        log.info("-------------");
        log.trace("trace");
        log.debug("debug");
        log.info("info");
        log.warn("warn");
        log.error("error");
        log.info("-------------");
    }
}

文章中展示了关键性代码,示例全部代码地址:凡夫贩夫 / logback-demo · GitCode

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

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

相关文章

LSM-Tree笔记

假设Level 0为内存中的Buffer&#xff0c;容量为 B B B&#xff0c;层与层之间的条目数量差 T T T 倍 Tiered Level 1共有 T T T 个runs&#xff0c;每个run的容量均为 B B BLevel 2共有 T T T 个runs&#xff0c;每个run的容量均为 T ⋅ B T\cdot B T⋅BLevel n共有 …

周记学习总结

10.3 今天加载出来了一下歌词&#xff0c;并且画了一下旁边的简单动画&#xff0c;然后画了一下下面的评论&#xff0c;今天主要是看了好多歌词滚动并且让它居中的&#xff0c;一直用的是scrollIntoView这个函数&#xff0c;但是这个函数似乎一直没有用&#xff0c;今天了解了…

多自由度工业机械臂机电系统

经过数百万年的进化创造了最通用和完善的工具——人类手臂。我们现代世界中的一切都得益于这个工具。即使到今天&#xff0c;工业界也没有找到比机器人手臂更多功能的工具来在三维空间中操纵物体&#xff0c;机器人手臂本质上是人类手臂的机电复制品。机器人手臂的多功能性确实…

企业关于低代码的需求——PDM 元数据电子审批流

企业关于低代码的需求 PDM 元数据电子审批流 审批流业务场景是现代企业运营中不可或缺的一环。业务流程从某个特定点开始,然后经过一系列的审批节点,完成流程的审批。这些节点通常由不同级别的人员担任,例如主管、经理、财务、法务和总经理等,每个人都扮演着特定的角色和…

阿里云数据库MongoDB恢复到本地

共两种方式&#xff0c;建议使用第二种的逻辑恢复&#xff0c;比较方便快捷 一、下载物理备份文件 下载的格式是xb的&#xff0c;主要跟实例创建时间有关&#xff0c;2019年03月26日之前创建的实例&#xff0c;物理备份文件格式为tar&#xff0c;后面全部都是xb的格式了&#…

DownloadingImages 下载缓存图片,显示图片文字列表

1. 用到的技术点: 1) Codable : 可编/解码 JSON 数据 2) background threads : 后台线程 3) weak self : 弱引用 4) Combine : 取消器/组合操作 5) Publishers and Subscribers : 发布者与订阅者 6) FileManager : 文件管理器 7) NSCache : 缓存 2. 网址: 2.1 测试接口网址: …

docker入门加实战—docker安装并配置阿里云加速

docker入门加实战—docker安装并配置阿里云加速 为什么要学习docker 在开发和部署项目的过程中&#xff0c;经常会遇到如下问题&#xff1a; 软件安装包名字复杂&#xff0c;不知道去哪里找安装软件和部署项目步骤复杂&#xff0c;容易出错 这就是我们今天要学习Docker技术…

7个在Github上的flutter开源程序

阅读大量代码是提高开发技能的最佳方法之一。该开源项目是了解最佳实践、编码风格和许多其他主题的最佳场所。 软件开发最受欢迎的领域之一是跨平台移动应用程序开发。Flutter 是您可以使用的最流行的跨平台移动应用程序开发工具之一。今天&#xff0c;我们将了解 7 个开源 Flu…

sqlalchemy 连接池

报错 sqlalchemy.exc.TimeoutError: QueuePool limit of size 100 overflow 10 reached, connection timed out, timeout 30 (Background on this error at: http://sqlalche.me/e/3o7r) 查看数据库未活动超时时间 show variables like "interactive_timeout";一般…

R可视乎|灯芯柱状图代码解读

简介 这篇推文代码来源于&#xff1a;TidyTuesday&#xff0c;主要想学习如何绘制灯芯柱状图&#xff08;名字小编瞎取的&#xff09;&#xff0c;最终结果如下&#xff1a; 注释&#xff1a;与普通柱状图相比&#xff0c;灯芯柱状图不仅可以展示随时间变化的总体趋势&#xf…

AQS内部的体系架构

AQS本质上是一个双向队列&#xff0c;加一个状态位state。内部靠Node节点形成队列。 AQS由state和CLH变体的虚拟双端队列组成。 AQS的内部类Node类 属性说明&#xff1a; 内部结构&#xff1a;

继续改进 另外一种方法 还是可以用CourseExend类

优势&#xff1a;可以映射许多类上 很强大 用在名称不统一上 原理 1.先把查询结果包装 取新别名&#xff08;&#xff08; 就是结果集的映射&#xff08;&#xff09; 2.把中结果集映射相应的pojo类上 第一步基于类创建 第二步 注意字属性的写法 teacher 是属性 属性的属性 …

手机待办事项app哪个好?

手机是日常很多人随身携带的设备&#xff0c;手机除了拥有通讯功能外&#xff0c;还能帮助大家高效管理日常工作&#xff0c;借助手机上的待办事项提醒APP可以快速地帮助大家规划日常事务&#xff0c;提高工作的效率。 过去&#xff0c;我也曾经在寻找一款能够将工作任务清晰罗…

33 WEB漏洞-逻辑越权之水平垂直越权全解

目录 前言水平&#xff0c;垂直越权&#xff0c;未授权访问Pikachu-本地水平垂直越权演示(漏洞成因)墨者水平-身份认证失效漏洞实战(漏洞成因)原理越权检测-Burpsuite插件Authz安装测试(插件使用)修复防御方案 前言 越权漏洞文章分享&#xff1a;https://www.cnblogs.com/zhen…

LockSupport是做什么的?深入理解Java的三种线程等待通知机制

文章目录 一、LockSupport概述1、LockSupport是什么2、三种等待唤醒机制3、其他线程等待唤醒方式&#xff08;了解&#xff09; 二、代码实例分析1、使用wait()notify()&#xff08;1&#xff09;代码实例&#xff08;2&#xff09;分析总结 2、使用await()signal()&#xff08…

乌班图20.04简易部署k8s+kuboard第三方面板

1. 问题&#xff1a; 使用官方只能说步骤挺全。 &#x1f604;出错&#xff1f;出错不管&#xff0c;无论是系统问题&#xff0c;版本兼容问题&#xff0c;网络插件问题&#xff0c;还是防火墙问题&#xff0c;我只能说特异性问题分析检索起来很难很难。 新人很难搞懂&#x…

基于指数趋近律的机器人滑模轨迹跟踪控制算法及MATLAB仿真

机械手是工业制造领域中应用最广泛的自动化机械设备&#xff0c;广泛应用于工业制造、医疗、军工、半导体制造、太空探索等领域。它们虽然形式不同&#xff0c;但都有一个共同的特点&#xff0c;即能够接受指令&#xff0c;并能准确定位到三维(或二维)空间的某一点进行工作。由…

RabbitMQ之topic(主题)Exchange解读

目录 基本介绍 使用场景 演示架构 工程概述 RabbitConfig配置类&#xff1a;创建队列及交换机并进行绑定 MessageService业务类&#xff1a;发送消息及接收消息 主启动类RabbitMq01Application&#xff1a;实现ApplicationRunner接口 基本介绍 在rabbitmq中&#xff0c;…

【目标检测】大图包括标签切分,并转换成txt格式

前言 遥感图像比较大&#xff0c;通常需要切分成小块再进行训练&#xff0c;之前写过一篇关于大图裁切和拼接的文章【目标检测】图像裁剪/标签可视化/图像拼接处理脚本&#xff0c;不过当时的工作流是先将大图切分成小图&#xff0c;再在小图上进行标注&#xff0c;于是就不考…

[NewStarCTF 2023 公开赛道] week1 Crypto

brainfuck 题目描述&#xff1a; [>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<-]>>>>>>>.>----.<-----.>-----.>-----.<<<-.>>..…