SLF4J的介绍与使用(有logback和log4j2的具体实现案例)

目录

1.日志门面的介绍

常见的日志门面 :

常见的日志实现:

日志门面和日志实现的关系:

2.SLF4J 的介绍

业务场景(问题):

SLF4J的作用

SLF4J 的基本介绍

 日志框架的绑定(重点)

桥接旧的日志框架

SLF4J原理解析

3.SLF4J 的使用

非Springboot项目

 Springboot项目(重点)

Springboot中使用logback

Springboot中使用log4j2


1.日志门面的介绍

当我们的系统变的更加复杂的时候,我们的日志就容易发生混乱。随着系统开发的进行,可能会更新不同的日志框架,造成当前系统中存在不同的日志依赖,让我们难以统一的管理和控制。就算我们强制要 求所有的模块使用相同的日志框架,系统中也难以避免使用其他类似spring,mybatis等其他的第三方框 架,它们依赖于我们规定不同的日志框架,而且他们自身的日志系统就有着不一致性,依然会出来日志 体系的混乱。

所以我们需要借鉴JDBC的思想,为日志系统也提供一套门面,那么我们就可以面向这些接口规范来开 发,避免了直接依赖具体的日志框架。这样我们的系统在日志中,就存在了日志的门面和日志的实现。

常见的日志门面 :

JCL、slf4j

常见的日志实现:

JUL、log4j、logback、log4j2

日志门面和日志实现的关系:

通过这关系图,就大概知道了其实日志门面就类似于一套标准的接口,然后不同的日志实现框架基于这套标准的接口去实现具体的功能。 

简单来说,它仅仅是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如JDBC一样,只是一种规则而已。所以单独的slf4j是不能工作的,必须搭配其他具体的日志实现方案

日志框架出现的历史顺序:

log4j -->JUL-->JCL--> slf4j --> logback --> log4j2

2.SLF4J 的介绍

业务场景(问题):

现在开发项目都是使用maven进行构建开发,假设架构师a开发了一个通用组件A,他在程序中使用的是log4j组件进行日志输出;程序员b自己之前一直在开发自己的业务模块,并且他在程序中使用的是logback日志组件,突然有一天程序员b需要在自己的业务系统中使用架构师a的通用组件A,这个时候问题就出现了,由于两套程序使用了不同的日志组件,程序员b除了要维护自己的logback日志组件配置,还需要维护通用组件A的日志配置,如何让他们的日志输出整合到一起,这个问题是很头疼的。这时候,使用slf4j就可以完美解决问题

SLF4J的作用

* 1. 使用SLF4J框架,可以在部署时迁移到所需的日志记录框架。

* 2. SLF4J提供了对所有流行的日志框架的绑定,例如log4j,JUL,Simple logging和NOP。因此可以 在部署时切换到任何这些流行的框架。

* 3. 无论使用哪种绑定,SLF4J都支持参数化日志记录消息。由于SLF4J将应用程序和日志记录框架分离, 因此可以轻松编写独立于日志记录框架的应用程序。而无需担心用于编写应用程序的日志记录框架。

* 4. SLF4J提供了一个简单的Java工具,称为迁移器。使用此工具,可以迁移现有项目,这些项目使用日志 框架(如Jakarta Commons Logging(JCL)或log4j或Java.util.logging(JUL))到SLF4J。

SLF4J 的基本介绍

简单日志门面(Simple Logging Facade For Java) SLF4J主要是为了给Java日志访问提供一套标准、规范 的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等。 当然slf4j自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的Java项目而言,日志框架 会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。

官方网站: https://www.slf4j.org/

SLF4J是目前市面上最流行的日志门面。现在的项目中,基本上都是使用SLF4J作为我们的日志系统。

SLF4J日志门面主要提供两大功能:

1. 日志框架的绑定

2. 日志框架的桥接

 日志框架的绑定(重点)

如前所述,SLF4J支持各种日志框架。SLF4J发行版附带了几个称为“SLF4J绑定”的jar文件,每个绑定对应 一个受支持的框架。

 要切换日志框架,只需替换类路径上的slf4j绑定。例如,要从java.util.logging切换到log4j,只需将 slf4j-jdk14-1.7.27.jar替换为slf4j-log4j12-1.7.27.jar即可。

SLF4J不依赖于任何特殊的类装载。实际上,每个SLF4J绑定 在编译时 都是硬连线的 , 以使用一个且只有一个特定的日志记录框架。例如,slf4j-log4j12-1.7.27.jar绑定在编译时绑定以使用log4j。在您的代码 中,除了slf4j-api-1.7.27.jar 之外 ,您只需将您选择的一个且只有一个绑定放到相应的类路径位置。不要在类路径上放置多个绑定。以下是一般概念的图解说明。

 

注意点:在springboot项目中,如果项目中有多个实现类的话,项目是会直接报错,无法运行,如下图

桥接旧的日志框架

通常,您依赖的某些组件依赖于SLF4J以外的日志记录API。您也可以假设这些组件在不久的将来不会切 换到SLF4J。为了解决这种情况,SLF4J附带了几个桥接模块,这些模块将对log4j,JCL和 java.util.logging API的调用重定向,就好像它们是对SLF4J API一样。

桥接解决的是项目中日志的遗留问题,当系统中存在之前的日志API,可以通过桥接转换到slf4j的实现

1. 先去除之前老的日志框架的依赖

2. 添加SLF4J提供的桥接组件

3. 为项目添加SLF4J的具体实现

迁移的方式:

如果我们要使用SLF4J的桥接器,替换原有的日志框架,那么我们需要做的第一件事情,就是删除掉原 有项目中的日志框架的依赖。然后替换成SLF4J提供的桥接器。

注意问题:

1. jcl-over-slf4j.jar和 slf4j-jcl.jar不能同时部署。前一个jar文件将导致JCL将日志系统的选择委托给 SLF4J,后一个jar文件将导致SLF4J将日志系统的选择委托给JCL,从而导致 无限循环 。

2. log4j-over-slf4j.jar和slf4j-log4j12.jar不能同时出现

3. jul-to-slf4j.jar和slf4j-jdk14.jar不能同时出现

4. 所有的桥接都只对Logger日志记录器对象有效,如果程序中调用了内部的配置类或者是 Appender,Filter等对象,将无法产生效果。

桥接其实就是原来项目是使用的其他日志门面或者框架作为日志管理,现在像切换到使用slf4j来作为日志门面好做统一的日志管理,在不修改代码的前提下,提出了桥接这种方式来兼容原来的老项目

SLF4J原理解析

1. SLF4J通过LoggerFactory加载日志具体的实现对象。

2. LoggerFactory在初始化的过程中,会通过performInitialization()方法绑定具体的日志实现。

3. 在绑定具体实现的时候,通过类加载器,加载org/slf4j/impl/StaticLoggerBinder.class

4. 所以,只要是一个日志实现框架,在org.slf4j.impl包中提供一个自己的StaticLoggerBinder类,在 其中提供具体日志实现的LoggerFactory就可以被SLF4J所加载

3.SLF4J 的使用

非Springboot项目

建项目

导入依赖

<!--slf4j core 使用slf4j必須添加-->  
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.27</version>
 </dependency>
 <!--slf4j 自带的简单日志实现 -->
 <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.27</version>
 </dependency>

 编写代码

public void testQuick() throws Exception {//打印日志信息LOGGER.error("error");LOGGER.warn("warn");LOGGER.info("info");LOGGER.debug("debug");LOGGER.trace("trace");// 使用占位符输出日志信息String name = "jack";Integer age = 18;LOGGER.info("用户:{},{}", name, age);// 将系统异常信息写入日志try {int i = 1 / 0;} catch (Exception e) {// e.printStackTrace();LOGGER.info("出现异常:", e);}
}

 输出结果

这种非springboot的项目大概流程是这样子,具体更多的使用细节这里我就不做讲解了,在开发中更多的是springboot项目,我重点介绍springboot项目

 Springboot项目(重点)

知识铺垫:

SpringBoot支持多种日志框架,包括Logback、Log4j2和Java Util Logging(JUL)。默认情况下,如果你使用SpringBoot的starters启动器,它将使用Logback作为日志框架。

  • Logback:Logback是SpringBoot默认的日志框架,它是Log4j的继任者,提供了更好的性能和可靠性。你可以通过在资源目录下创建一个logback-spring.xml文件来配置Logback。
  • Log4j2:Log4j2是Log4j的升级版,它在性能和功能上都有所提升,支持异步日志和插件机制。如果你想在SpringBoot中使用Log4j2,你需要添加相应的依赖并在配置文件中指定Log4j2作为日志框架。
  • Java Util Logging(JUL):JUL是Java SE的默认日志框架,SpringBoot可以配置使用JUL作为日志框架,但一般不推荐使用,因为它的性能和灵活性相对较差。

简单来说就是springboot项目已经帮我们内置好的日志框架,默认实现是SLF4J+logback

所以如果我们项目中没有做任何关于日志框架的处理,那么就会使用默认的组合

但在实际的开发中,往往需要对项目日志框架进行处理。开发中常用日志门面是SLF4J,常用到日志实现是logback和log42这二个具体的实现类。因为springboot项目默认使用的就是SLF4J,所以我们不需要在引入依赖的,只需要针对实现类做处理。

Springboot中使用logback

springboot项目默认的日志实现就是logback,所以我们不需要在引入依赖,如何配置logback相关的配置,有二种方式,一种在项目的配置文件种配置,一种是单独建一个文件配置(方便管理)。我这里采用单独第二种

logback会依次读取以下类型配置文件:

logback.groovy

logback-test.xml

logback.xml 如果均不存在会采用默认配置

这里我建一个logback.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration><!--日志输出格式:%-5level%d{yyyy-MM-dd HH:mm:ss.SSS}日期%c类的完整名称%M为method%L为行号%thread线程名称%m或者%msg为信息%n换行--><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%-5level] %c %M %L [%thread] %m%n"/><!--Appender: 设置日志信息的去向,常用的有以下几个ch.qos.logback.core.ConsoleAppender (控制台)ch.qos.logback.core.rolling.RollingFileAppender (文件大小到达指定尺寸的时候产生一个新文件)ch.qos.logback.core.FileAppender (文件)--><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><!--输出流对象 默认 System.out 改为 System.err--><target>System.out</target><!--日志格式配置--><encoderclass="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!-- 日志文件存放目录 --><property name="log_dir" value="./logs"></property><!--日志文件输出appender对象--><appender name="file" class="ch.qos.logback.core.FileAppender"><!--日志格式配置--><encoderclass="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><!--日志输出路径--><file>${log_dir}/logback.log</file></appender><!-- 生成html格式appender对象 --><appender name="htmlFile" class="ch.qos.logback.core.FileAppender"><!--日志格式配置--><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="ch.qos.logback.classic.html.HTMLLayout"><pattern>%level%d{yyyy-MM-ddHH:mm:ss}%c%M%L%thread%m</pattern></layout></encoder><!--日志输出路径--><file>${log_dir}/logback.html</file></appender><!-- 日志文件拆分和归档的appender对象--><appender name="rollFile"class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志格式配置--><encoderclass="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><!--日志输出路径--><file>${log_dir}/roll_logback.log</file><!--指定日志文件拆分和压缩规则--><rollingPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--通过指定压缩文件名称,来确定分割文件方式--><fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd}-%i.log</fileNamePattern><!--文件拆分大小--><maxFileSize>50MB</maxFileSize></rollingPolicy></appender><!--用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<loger>仅有一个name属性,一个可选的level和一个可选的addtivity属性name:用来指定受此logger约束的某一个包或者具体的某一个类。level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和OFF,如果未设置此属性,那么当前logger将会继承上级的级别。additivity:是否向上级loger传递打印信息。默认是true。<logger>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个logger--><!--也是<logger>元素,但是它是根logger。默认debuglevel:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和 OFF,<root>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个logger。--><root level="INFO"><appender-ref ref="console"/><appender-ref ref="rollFile"/></root>
</configuration>

编写测试类

public class LogbackTest {public static final Logger LOGGER = LoggerFactory.getLogger(Slf4jTest.class);@Testpublic void logbackTest(){LOGGER.error("error");  //错误信息,不会影响程序运行LOGGER.warn("warn");    //警告信息,表示系统运行可能出现的异常LOGGER.info("info");    //提示信息,记录系统运行,io操作等LOGGER.debug("debug");  //调试信息,一般在开发中使用LOGGER.trace("trace");  //追踪信息,记录程序所有的流程信息// 占位符输出日志String name = "jack";Integer age = 18;LOGGER.info("用户姓名:{},年龄:{}",name,age);int i = 1;try {i = i/0;} catch (Exception e) {LOGGER.info("出现异常",e);}}
}

运行效果:

未配置logback.xml前的输出效果

配置后的输出效果

总结:在springboot 使用logback非常的简单,你只需要通过配置文件去配置它就好了

Springboot中使用log4j2

 因为springboot项目内置日志实现是logback,所以如果我们要使用log42的话,需要移除默认的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!--排除默认spring-boot-starter-logging启动器-->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

加入 log4j2的依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

 

在src/main/resources目录下创建一个名为log4j2-spring.xml的配置文件,Spring Boot会默认加载这个配置文件。Spring Boot官方推荐优先使用带有-spring的文件名作为日志配置。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><!-- 定义全局变量,日志文件路径和格式 --><Properties><Property name="log.path">./dev</Property><Property name="log.name">log4j2</Property><Property name="file.pattern">%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{50} - %msg%n</Property></Properties><!-- 控制台输出配置 --><Appenders><Console name="STDOUT" target="SYSTEM_OUT"><PatternLayout pattern="${file.pattern}"/><ThresholdFilter level="DEBUG"/></Console><!-- 文件输出配置 --><RollingFile name="INFO_FILE" fileName="${log.path}/${log.name}.log4j2.log"filePattern="${log.path}/%d{yyyy-MM-dd}/${log.name}.info.%d{yyyy-MM-dd}-%i.log"><PatternLayout pattern="${file.pattern}"/><LevelMatchFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/><!-- 每个文件最大10MB --><SizeBasedTriggeringPolicy size="10MB"/><!-- 最多保留30天的历史记录 --><DefaultRolloverStrategy max="30"/></RollingFile><!-- 文件输出配置 --><RollingFile name="ERROR_FILE" fileName="${log.path}/${log.name}.error.log"filePattern="${log.path}/%d{yyyy-MM-dd}/${log.name}.error.%d{yyyy-MM-dd}-%i.log"><PatternLayout pattern="${file.pattern}"/><LevelMatchFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/><!-- 每个文件最大10MB --><SizeBasedTriggeringPolicy size="10MB"/><!-- 最多保留30天的历史记录 --><DefaultRolloverStrategy max="30"/></RollingFile></Appenders><!-- 设置root logger --><Loggers><Root level="INFO"><AppenderRef ref="STDOUT"/><AppenderRef ref="INFO_FILE"/><AppenderRef ref="ERROR_FILE"/></Root></Loggers>
</Configuration>

 运行效果

 如何是出现如上图,就代表使用的是log4j2这个日志实现了

总的来说,推荐使用Logback,配置简单,性能也还不错,而且是SpringBoot的默认日志框架

这里对于logback和log4j2的使用只是基本的使用,对于更多的使用细节,后续我会分别出对应实现框架的文章,文章到这里就结束了,如有不足,欢迎指正

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

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

相关文章

跨越界限的温柔坚守

跨越界限的温柔坚守 —— 郑乃馨与男友的甜蜜抉择在这个光怪陆离、瞬息万变的娱乐圈里&#xff0c;每一段恋情像是夜空中划过的流星&#xff0c;璀璨短暂。然而&#xff0c;当“郑乃馨与男友甜蜜约会”的消息再次跃入公众视野&#xff0c;它不仅仅是一段简单的爱情故事&#xf…

iOS中多个tableView 嵌套滚动特性探索

嵌套滚动的机制 目前的结构是这样的&#xff0c;整个页面是一个大的tableView, Cell 是整个页面的大小&#xff0c;cell 中嵌套了一个tableView 通过测试我们发现滚动的时候&#xff0c;系统的机制是这样的&#xff0c; 我们滑动内部小的tableView, 开始滑动的时候&#xff0c…

C/C++ 代码注释规范及 doxygen 工具

参考 谷歌项目风格指南——注释 C doxygen 风格注释示例 ubuntu20 中 doxygen 文档生成 doxygen 官方文档 在 /Doxygen/Special Command/ 章节介绍 doxygen 的关键字 注释说明 注释的目的是提高代码的可读性与可维护性。 C 风格注释 // 单行注释/* 多行注释 */ C 风格注…

【论文阅读笔记】Meta 3D AssetGen

【论文阅读笔记】Meta 3D AssetGen: Text-to-Mesh Generation with High-Quality Geometry, Texture, and PBR Materials Info摘要引言创新点 相关工作T23D基于图片的3d 重建使用 PBR 材料的 3D 建模。 方法文本到图像:从文本中生成阴影和反照率图像Image-to-3D:基于pbr的大型重…

搭建NEMU与QEMU的DiffTest环境(动态库方式)

搭建NEMU与QEMU的DiffTest环境&#xff08;动态库方式&#xff09; 1 DiffTest原理简述2 编译NEMU3 编译qemu-dl-difftest3.1 修改NEMU/scripts/isa.mk3.2 修改NEMU/tools/qemu-dl-diff/src/diff-test.c3.3 修改NEMU/scripts/build.mk3.4 让qemu-dl-difftest带调试信息3.5 编译…

安卓的组件

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

【Linux】打包命令——tar

打包和压缩 虽然打包和压缩都涉及将多个文件组合成单个实体&#xff0c;但它们之间存在重要差异。 打包和压缩的区别&#xff1a; 打包是将多个文件或目录组合在一起&#xff0c;但不对其进行压缩。这意味着打包后的文件大小可能与原始文件相同或更大。此外&#xff0c;打包…

数字化精益生产系统--APS 排程管理系统

APS&#xff08;Advanced Planning and Scheduling&#xff09;排程管理系统&#xff0c;即高级生产计划与排程系统&#xff0c;是一种高度智能化的计划和排程系统。它通过整合各种生产和供应链数据&#xff0c;运用先进的算法和数据模型&#xff0c;根据各种约束条件&#xff…

MySQL篇三:数据类型

文章目录 前言1. 数值类型1.1 tinyint类型1.2 bit类型1.3 小数类型1.3.1 float1.3.2 decimal 2. 字符串类型2.1 char2.2 varchar2.3 char和varchar比较 3. 日期类型4. enum和set 前言 数据类型分类&#xff1a; 1. 数值类型 1.1 tinyint类型 在MySQL中&#xff0c;整型可以指…

【Java13】包

“包”这个机制&#xff0c;类似于分组。主要作用是区分不同组内的同名类。例如&#xff0c;高三三班有一个“王五”&#xff0c;高二八班也有一个“王五”。高三三班和高三八班就是两个不同的包。 Java中的包&#xff08;package&#xff09;机制主要提供了类的多层命名空间&…

HTTP长连接

长连接优点 HTTP为什么要开启长连接呢? 主要是为了节省建立的时间,请求可以复用同一条TCP链路,不用重复进行三握+四挥 如果没有长连接,每次请求都做三握+四挥 如果有长链接,在一个 TCP 连接中可以持续发送多份数据而不会断开连接,即请求可以复用TCP链路 长连接缺点 …

第六十八回 东平府误陷九纹龙 宋公明义释双枪将-文心大模型ernie-speed免费使用方法

宋江和卢俊义抓阄儿&#xff0c;宋江打东平府&#xff0c;卢俊义打东昌府&#xff0c;谁先打下谁做梁山泊主。宋江带领林冲、花荣、刘唐等二十八人&#xff0c;卢俊义带领吴用、公孙胜、关胜等二十八人。 宋江等人到了东平府外安山镇&#xff0c;郁保四和王定六自告奋勇去下战…

代码随想录第45天|动态规划

300.最长递增子序列 参考 dp[i] 表示以 i 为结尾的最长递增子序列长度递推公式: 使用 i 和 j 判断 dp[i] max(dp[j] 1, dp[i])每次 j 都需要从头遍历 初始化: dp[i] 1 class Solution { public:int lengthOfLIS(vector<int>& nums) {vector<int> dp(nums…

国产化新标杆:TiDB 助力广发银行新一代总账系统投产上线

随着全球金融市场的快速发展和数字化转型的深入推进&#xff0c;金融科技已成为推动银行业创新的核心力量。特别是在当前复杂多变的经济环境下&#xff0c;银行业务的高效运作和风险管理能力显得尤为重要。总账系统作为银行会计信息系统的核心&#xff0c;承载着记录、处理和汇…

2024年06月CCF-GESP编程能力等级认证Python编程二级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证…

云动态摘要 2024-07-07

给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新优惠与活动 数据库上云优选 阿里云 2024-07-04 RDS、PolarDB、Redis、MongoDB 全系产品新用户低至首年6折起! [免费体验]智能助手ChatBI上线 腾讯云 2024-07-02 基于混元大模型打造,可通过对话方式生成可视化…

18_特征金字塔网络FPN结构详解

1.1 简介 在深度学习领域&#xff0c;尤其是计算机视觉和目标检测任务中&#xff0c;Feature Pyramid Networks (FPN) 是一种革命性的架构设计&#xff0c;它解决了多尺度特征检测和融合的关键问题。FPN最初由何凯明等人在2017年的论文《Feature Pyramid Networks for Object …

ansible常见问题配置好了密码还是报错

| FAILED! > { “msg”: “Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host’s fingerprint to your known_hosts file to manage this host.” } 怎么解决&#xf…

Stable Diffusion图像的脸部细节控制——采样器全解析

文章目录 艺术地掌控人物形象好易智算原因分析为什么在使用Stable Diffusion生成全身图像时&#xff0c;脸部细节往往不够精细&#xff1f; 解决策略 局部重绘采样器总结 艺术地掌控人物形象 在运用Stable Diffusion这一功能强大的AI绘图工具时&#xff0c;我们往往会发现自己…

ESP32 步进电机精准控制:打造高精度 DIY 写字机器人,实现流畅书写体验

摘要: 想让你的 ESP32 不再仅仅是控制灯光的工具吗&#xff1f; 本文将带你使用 ESP32 开发板、步进电机和简单的机械结构打造一个能够自动写字的机器人。我们将深入浅出地讲解硬件连接、软件代码以及控制逻辑&#xff0c;并提供完整的项目代码和电路图&#xff0c;即使是 Ardu…