【业务功能篇56】SpringBoot 日志SLF4J Logback
3.5.1 日志框架分类与选择
3.5.1.1 日志框架的分类
日志门面 (日志抽象) | 日志实现 |
---|---|
JCL(Jakarta Commons Logging) SLF4J(Simple Logging Facade for Java) | Jul(Java Util Logging) , Log4j , Log4j2 , Logback |
记录型日志框架
- Jul (Java Util Logging):JDK中的日志记录工具,也常称为JDKLog、jdk-logging,自Java1.4以来的官方日志实现。
- Log4j:Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一。
- Log4j2:一个具体的日志实现框架,是Log4j 1的下一个版本,与Log4j 1发生了很大的变化,Log4j 2不兼容Log4j 1
- Logback:一个具体的日志实现框架,和Slf4j是同一个作者,但其性能更好(推荐使用)。
门面型日志框架
- JCL:Apache基金会所属的项目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名为Commons Logging
- SLF4J:是一套简易Java日志门面,本身并无日志的实现。(Simple Logging Facade for Java,缩写Slf4j)
3.5.1.2 日志框架的选择
选择日志框架的方式,就是先选择一个门面(抽象层) ,然后再选择一个实现
- **日志门面: SLFJ **
- 日志实现: LogBack
Spring默认使用JCL
SpringBoot默认选用的是SLF4J和 Logback.
Slf4j的设计思想比较简洁,使用了Facade设计模式,Slf4j本身只提供了一个slf4j-api-version.jar包,这个jar中主要是日志的抽象接口,jar中本身并没有对抽象出来的接口做实现。
对于不同的日志实现方案(例如Logback,Log4j…),封装出不同的桥接组件(例如logback-classic-version.jar,slf4j-log4j12-version.jar),这样使用过程中可以灵活的选取自己项目里的日志实现。
3.5.2 SLF4J日志框架
3.5.2.1 如何使用SLF4j
日志方法的调用,不要直接调用日志的实现类, 而是调用日志抽象层里的方法 (面向抽象编程).
阿里的开发手册上有一条关于日志的规范:
- **强制:应用中不可直接使用日志系统(log4j、logback)中的 API ,而应依赖使用日志框架 SLF4J 中的 API 。使用门面模式的日志框架,有利于维护和各个类的日志处理方式的统一。 **
日志框架之间的关系
- Slf4j的设计思想比较简洁,使用了Facade设计模式,Slf4j本身只提供了一个slf4j-api-version.jar包,这个jar中主要是日志的抽象接口,jar中本身并没有对抽象出来的接口做实现。
代码示例
import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class HelloWorld {public static void main(String[] args) {Logger logger = LoggerFactory.getLogger(HelloWorld.class);logger.info("Hello World");}}
配置文件
- **每一个日志实现框架都有自己的配置文件,使用slf4j之后,**配置文件还是选用具体日志实现框架的配置文件.
3.5.2.2 其他日志框架转换为slf4j
- Slf4j的设计思想比较简洁,使用了Facade设计模式,Slf4j本身只提供了一个slf4j-api-version.jar包,这个jar中主要是日志的抽象接口,jar中本身并没有对抽象出来的接口做实现。
- 对于不同的日志实现方案(例如Log4j…),封装出不同的桥接组件(例如: slf4j-log4j12-version.jar),这样使用过程中可以灵活的选取自己项目里的日志实现。
SLF4j与其它日志组件集成
应用调了sl4j-api,日志门面接口。日志门面接口本身通常并没有实际的日志输出能力,它底层还是需要去调用具体的日志框架API的,也就是实际上它需要跟具体的日志框架结合使用。由于具体日志框架比较多,而且互相也大都不兼容,日志门面接口要想实现与任意日志框架结合可能需要对应的桥接器,上图红框中的组件即是对应的各种桥接器!
3.5.3 SpringBoot结合logback输出日志
3.5.3.1 SpringBoot日志关系
在SpringBoot中,底层是Spring框架,Spring框架默认使用JCL,而****SpringBoot默认集成的日志框架使用的是SLF4j+Logback组合。
**因为 **spring-boot-starter-logging
是Logback的日志实现,而Spring Boot启动项spring-boot-starter又依赖了spring-boot-starter-logging,所以Spring Boot就默认集成了Logback。
SpringBoot默认集成了Logback,可以开箱即用,非常方便。在基于SpringBoot实现的系统中,使用SLF4j方法如下:
日志记录方法的调用,不应该来直接调用日志的实现类,而是应该调用日志抽象层的方法,即直接使用SLF4j日志门面。
在代码中使用的方式如下:
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class LogDemo {private final Logger logger = LoggerFactory.getLogger(LogDemo.class);@Testpublic void testLog(){Logger logger = LoggerFactory.getLogger(LogDemo.class);logger.info("Hello LogBack!");}
}//打印结果15:16:26.759 [main] INFO c.m.h.log.LogDemo - [main,15] - Hello LOG !
3.5.3.2 logback配置文件
在resources文件夹下创建 logback.xml
,logback会自动在该目录下加载该配置文件,在该文件中对打印日志的级别、形式、保存路径等进行配置。
https://www.springcloud.cc/spring-boot.html#boot-features-logging-format
如果可能,我们建议您使用
-spring
变体进行日志记录配置(例如,logback-spring.xml
而不是logback.xml
)。如果使用标准配置位置,Spring无法完全控制日志初始化。
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!-- 日志存放路径 --><property name="log.path" value="/home/hejiayun/logs" /><!-- 日志输出格式 -->
<!-- <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />--><property name="log.pattern"value="%red(%date{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %red([%thread]) %boldMagenta(%logger{50}) - [%method,%line] - %cyan(%msg%n)"/><!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统日志输出 --><appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-info.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>INFO</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-error.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>ERROR</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><!-- 用户访问日志输出 --><appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-user.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按天回滚 daily --><fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统模块日志级别控制 --><logger name="com.msb" level="info" /><!-- Spring日志级别控制 --><logger name="org.springframework" level="warn" /><root level="info"><appender-ref ref="console" /></root><!--系统操作日志--><root level="info"><appender-ref ref="file_info" /><appender-ref ref="file_error" /></root><!--系统用户操作日志--><logger name="sys-user" level="info"><appender-ref ref="sys-user"/></logger>
</configuration>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
3.5.3.2.1 configuration 根节点
configuration 根节点包含的属性:
- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
<configuration> 的子节点有contextName、property、appender、logger、root等,其中contextName和property是属性节点,appender、root、logger是
3.5.3.2.2 property节点
property标签可用于自定义属性,比如定义一个property name=“log.pattern”,然后使用${log.pattern}去引用它。
<!-- 日志存放路径 --><property name="log.path" value="/home/hejiayun/logs" /><!-- 日志输出格式 --><property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
日志输出格式说明
%d表示时间%thread表示线程名%-5level 表示日志级别,允许以五个字符长度输出%logger{20}表示具体的日志输出者,比如类名,括号内表示长度%method:表示方法名字%line:表示第几行%msg表示具体的日志消息,就是logger.info("xxx")中的xxx%n表示换行
3.5.3.2.3 appender节点
是负责写日志的组件,在这里可以理解为一个日志的渲染器,比如console日志选择器、文件渲染器。有两个必要属性name和class:
- name指定的名称,表示该渲染器的名字。
- class指定的全限定名,表示使用的输出策略,常见的有控制台输出策略和文件输出策略。
appender日志输出方式实现类:ConsoleAppender、FileAppender、RollingFileAppender、SocketAppender、SMTPAppender、DBAppender、SyslogAppender、SiftingAppender等.
平时主要使用的是 ConsoleAppender
和 RollingFileAppender
,其中 ConsoleAppender
是往控制台打印日志,RollingFileAppender
是往磁盘文件追加日志,而且可以按照一定的设置方式动态分割日志
1) 控制台输出–ConsoleAppender
<!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender>
encoder表示输出格式
2) 文件输入RollingFileAppender
文件输出主要包括配置:以指定格式将日志输出到指定文件夹下的文件中,可以配置该文件的名称、最大大小、保存时间等。
<!-- 系统日志输出 --><appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-info.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>INFO</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender>
<rollingPolicy>
:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名(重命名文件)。<rollingPolicy>
的作用是当发生滚动时,定义RollingFileAppender的行为,其中上面的TimeBasedRollingPolicy是最常用的滚动策略,它根据时间指定滚动策略,既负责滚动也负责触发滚动,有以下节点:<fileNamePattern>
,必要节点,包含文件名及"%d"转换符,"%d"可以包含一个Java.text.SimpleDateFormat指定的时间格式,如%d{yyyy-MM},如果直接使用%d那么格式为yyyy-MM-dd。RollingFileAppender的file子节点可有可无,通过设置file可以为活动文件和归档文件指定不同的位置。<maxHistory>
,可选节点,控制保留的归档文件的最大数量,如果超出数量就删除旧文件,假设设置每个月滚动且<maxHistory>
是6,则只保存最近6个月的文件。<filter>
logbcak允许给日志记录器appender配置一个或多个Filter(或者给整体配置一个或多个TurboFilter),来控制:当满足过滤器指定的条件时,才记录日志(或不满足条件时,拒绝记录日志)只记录ERROR级别的日志,其他级别的日志拒绝记录<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>ERROR</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter>
3.5.2.3.3 logger节点
<logger>
用来设置某一个包或者具体某一个类的日志打印级别、以及指定 <appender>
。<logger>
可以包含零个或者多个 <appender-ref>
元素,标识这个appender将会添加到这个logger。<logger>
仅有一个name属性、一个可选的level属性和一个可选的additivity属性:
<!-- 系统模块日志级别控制 --><logger name="com.msb" level="info" /><!-- Spring日志级别控制 --><logger name="org.springframework" level="warn" />
- name:用来指定受此logger约束的某一个包或者具体的某一个类
- level:用来设置打印级别,五个常用打印级别从低至高依次为TRACE、DEBUG、INFO、WARN、ERROR,如果未设置此级别,那么当前logger会继承上级的级别
- additivity:是否向上级logger传递打印信息,默认为true。
3.5.2.3.4 root节点
root节点实际上是配置启用哪种appender,可以添加多个appender。<root>
也是 <logger>
元素,但是它是根logger,只有一个level属性,因为它的name就是ROOT。 如果没有指定logger,则那么所有的logger都会继承根logger的level。
<root level="info"><appender-ref ref="console" /></root><!--系统操作日志--><root level="info"><appender-ref ref="file_info" /><appender-ref ref="file_error" /></root>
appender-ref : 表示level为info级别,启用渲染器`CONSOLE
3.5.3.3 如何进行日志打印
3.5.3.3.1 日志打印级别
TRACE < DEBUG < INFO < WARN < ERROR
- TRACE : 级别最小,打印最详细,使用较少
- DEBUG:主要用于调试阶段输出,此日志应尽可能详尽。DEBUG日志应该以调试人员满足调试需求为主,生产环境不应输出debug级别日志。
- INFO:主要用来反馈系统当前状态的输出,应视为系统产品最终呈现给用户的一部分,因此不可滥用。INFO级别通常用来进行日常运维以及错误回溯时查看上下文场景。通过INFO日志可以了解系统的运行情况,对系统进行监控。
- WARN:主要针对可预知,有解决预案的错误,如下单数量超过该用户所持总量的情况。WARN级别打印关键信息即可,事后用于分析错误原因。
- ERROR:主要针对不可预知的信息,比如异常和错误。ERROR级别通常指一些较为严重的异常发生,所以需要尽可能多的打印出详细信息,如方法的入参,执行过程产生数据等。
详解:
- 项目中设置的日志级别为:TRACE,包括 TRACE / DEBUG / INFO / WARN / ERROR 的日志级别都打印
- 项目中设置的日志级别为:DEBUG ,包括 DEBUG / INFO / WARN / ERROR 的日志级别都打印
- 项目中设置的日志级别为:INFO ,包括 INFO / WARN / ERROR 的日志级别都打印
- 项目中设置的日志级别为:WARN,包括 WARN / ERROR 的日志级别都打印
- 项目中设置的日志级别为:ERROR ,只打印 ERROR 的日志级别都打印
3.5.3.3.2 日志打印方式
@RunWith(SpringRunner.class)@SpringBootTest@Slf4jpublic class LogDemo {private final Logger logger = LoggerFactory.getLogger(LogDemo.class);/*** 传统方式实现日志*/@Testpublic void test1(){logger.error("发生了严重错误,程序阻断了,需要立即处理,发送警报");logger.warn("这个错误很少见,不影响程序继续运行,酌情处理");logger.info("没有什么问题,单纯想打印个日志");logger.debug("你经常写BUG,测试的时候,多打点日志");logger.trace("这个级别很少用,为了追踪");}/*** Slf4j注解方式实现日志* 每次写新的类,就需要重新写logger,麻烦,可以使用@Slf4j注解简化:*/@Testpublic void test2(){log.error("发生了严重错误,程序阻断了,需要立即处理,发送警报");log.warn("这个错误很少见,不影响程序继续运行,酌情处理");log.info("没有什么问题,单纯想打印个日志");log.debug("你经常写BUG,测试的时候,多打点日志");log.trace("这个级别很少用,为了追踪");}}
3.5.3.3.2 日志打印实操
日志打印的规范介绍
- 输出Exceptions的全部Throwable信息
- 出于日志文件储存和性能的考虑,建议为可能会大量出现的低级别日志添加判断
- 尽量使用占位符而不是拼接来打印日志,这样的可读性更高,而且只有打印时才会处理函数,提升效率
@Testpublic void logNorm(){//使用{}作为占位符,而不是字符串拼接String name = "我是大佬";log.info("hello {}",name);log.debug("hello " + name);String userId = "10010";String orderId = "3242343253253535";log.debug("order is paying with userId:[{}] and orderId : [{}]",userId, orderId);// e.printStackTrace();不使用这种,打印堆栈日志与业务日志混合try {int i = 1 / 0;} catch (Exception e) {// e.printStackTrace();log.error("/ by zero",e);}//先拼接字符串“hello”和“name”。然后执行debug方法,判断日志级别。log.debug("hello" + name);//不提前拼接,先判断日志级别, 然后选择是否执行debug方法,拼接字符串“hello”和“world”//isDebugEnabled() 可以避免无用的字符串操作,提高性能if(log.isDebugEnabled()){log.debug("hello" + name);}}
日志打印的注意事项
- 尽量不要在日志中调用方法获取值,否则会因为日志而报出空指针异常。(日志不能打断业务逻辑)
- 上线后除了进行常规的测试外,应可以通过对日志进行观察来判断新功能是否工作正常。
- 对不同类型的日志进行分类输出,比如ERROR日志单独输出,防止日志数量过大时不利于分析错误信息。
- 日志文件一般保留周期为15天,防止以周为单位的错误出现,应设置定时任务删除过期日志(如15天前)。
相关文章:

【业务功能篇56】SpringBoot 日志SLF4J Logback
3.5.1 日志框架分类与选择 3.5.1.1 日志框架的分类 日志门面 (日志抽象)日志实现JCL(Jakarta Commons Logging) SLF4J(Simple Logging Facade for Java)Jul(Java Util Logging) , Log4j , Log4j2 , Logback 记录型日志框架 Jul (Java Util Logging):JDK中的日志…...

leetcode 53. 最大子数组和
2023.7.28 要求找最大和的 连续子数组, 我的思路是用一个temp记录局部最优值,用ans记录全局最优值。 然后在每次for循环进行一个判断:当前遍历元素temp值 是否大于当前遍历元素的值,如果大于,说明temp值是帮了正忙的&a…...

js 下载url返回的excel数据,并解析为json
XLSX GitHub地址:https://github.com/SheetJS/sheetjs/blob/github/dist/xlsx.full.min.js 需要先引入:XLSX.full.min.js // 下载文件的请求 fetch(downloadFileUrl).then(response > {return rsp.blob() }).then(data > {let reader new FileR…...

图文教程:使用 Photoshop、3ds Max 和 After Effects 创建被风暴摧毁的小屋
推荐: NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 在 Photoshop 中设置图像 步骤 1 打开 Photoshop。 打开 Photoshop 步骤 2 我已经将小屋的图像导入到Photoshop中以演示 影响。如果您愿意,可以使用其他图像。 图片导入 步骤 3 由于小…...

学习Maven Web 应用
Maven Web 应用 本章节我们将学习如何使用版本控制系统 Maven 来管理一个基于 web 的项目,如何创建、构建、部署已经运行一个 web 应用。 创建 Web 应用 我们可以使用 maven-archetype-webapp 插件来创建一个简单的 Java web 应用。 打开命令控制台,…...

page allocation stalls for 问题调研
一.现象分析和内存管理基本概念介绍 最近有一台linux出现卡死的状态,系统不反应,无法ssh登录,只能通过电源关机重启操作恢复,重启后登录系统后台,拉取kernel日志,如下 Jul 12 18:48:06 kernel: [141294.374983] send process: page allocation stalls for 10108ms, orde…...

JUC并发工具类
一、ReentrantLock 特点:独占、可重入、公平/非公平、可中断、支持多个条件变量 1、常用api ReentrantLock实现了Lock接口,Lock类规范定义了如下方法 lock():获取锁,调用该方法的线程会获取锁,当锁获得后࿰…...

【雕爷学编程】MicroPython动手做(10)——零基础学MaixPy之神经网络KPU
早上百度搜“神经网络KPU”,查到与非网的一篇文章《一文读懂APU/BPU/CPU/DPU/EPU/FPU/GPU等处理器》,介绍各种处理器非常详细,关于“KPU”的内容如下: KPU Knowledge Processing Unit。 嘉楠耘智(canaan)号…...

MySQL~SQL语句
一、SQL 1.什么是SQL? Structured Query Language:结构化查询语言 每一种数据库操作的方式存在不一样的地方,称为“方言”。 2.SQL通用语法 SQL 语句可以单行或多行书写,以分号结尾 可使用空格和缩进来增强语句的可读性 MyS…...

从零开始构建基于YOLOv5的目标检测系统
本博文从零开始搭建基于YOLOv5模型的目标检测系统(具体系统参考本博主的其他博客),手把手保姆级完成环境的搭建。 (1)首先Windows R输入cmd命令后打开命令窗口,进入项目目录,本博文以野生动物…...

PDF尺寸修改:等比绽放(标准面单100*150mm)
PDF修改尺寸 需要注意:第一个方法返回的是转换后PDF的base64。第二个方法返回的是文件流,这个方法才是转的核心。 /*** 修改PDF尺寸** param pdfUrl PDF链接* param pdfWidthInMillimeters 指定宽 mm* param pdfHeightInMillimeters 指…...

C++ - list介绍 和 list的模拟实现
list介绍 list 是一个支持在常数范围内,任意位置进行插入删除的序列式容器,且这个容器可以前后双向迭代。我们可以把 list 理解为 双向循环链表的结构。 于其他结构的容器相比,list在 任意位置进行插入和函数的效率要高很多;而li…...

干翻Dubbo系列第四篇:Dubbo3第一个应用程序细节补充
前言 不从恶人的计谋,不站罪人的道路,不坐亵慢人的座位,惟喜爱耶和华的律法,昼夜思想,这人便为有福!他要像一棵树栽在溪水旁,按时候结果子,叶子也不枯干。凡他所做的尽都顺利。 如…...

深度学习初探
1.深度学习模型训练过程 1)数据(数据清洗标注) 2)模型(模型的构建和初始化) 3)损失(前向传播的过程,得到模型的输出和真实标签的差异值,称之为损失&#x…...

nn.BCELoss与nn.CrossEntropyLoss
BCELoss与CrossEntropyLoss都是用于分类问题。可以知道,BCELoss是Binary CrossEntropyLoss的缩写,BCELoss是CrossEntropyLoss的一个特例,只用于二分类问题,而CrossEntropyLoss可以用于二分类,也可以用于多分类…...

CSDN浏览如何解决
一、对于平时我们苦恼csdn数据不够好看 当面试等各个场合需要我们装*或者秀技术无法拿出亮眼的时候,刚好我闲时间编译的在线模块适合你 二、如何操作(虚拟平台我已给大家放到最后直接使用即可) 重点:pc端必须拥有python环境 win…...

web前端开发小知识
当今互联网技术迅猛发展,web前端开发也成为了非常热门的职业之一。作为一个web前端开发者,不仅需要掌握各种前端开发技术,还需要了解一些小技巧和小知识。下面,我们将介绍一些web前端开发小知识,希望对你的工作有所帮助…...

Java泛型的简单认识
泛型的认识 自定义泛型,定义了String类型,随后这个泛型就是String类型 于是他的方法都是字符串的类型 泛型接口 泛型方法 所有车可以进行比赛,定义了一个BMW和BENZ两个车类,都继承car,当使用泛型的 如果你顶一个狗对象…...

视频转化为图片或灰度视频
1.视频转化为图片 import cv2video_pathr"D:\Dataset\video/7.mp4" capturecv2.VideoCapture(video_path) # print(capture.get(5))if capture.isOpened():ret,imgcapture.read()index0while ret:if index%200:imgidr"D:\Dataset\image/6/""%07d&quo…...

【动态规划刷题 2】使⽤最⼩花费爬楼梯 解码⽅法
使⽤最⼩花费爬楼梯 746 . 使用最小花费爬楼梯 链接: 746 . 使用最小花费爬楼梯 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 …...

Python的基本语法
“有人说,写python就像是坐在一个没有安全带的车上, 我认为这个说法很欠妥当, 应该是一辆没有外壳和座椅, 只有发动机和轮子的车, 并且车上摆满了轮子” python既然是作为一个工具,那么就不需要去深入…...

Kubernetes那点事儿——存储之存储卷
Kubernetes那点事儿——存储之存储卷 前言一、K8s数据卷一、临时存储卷emptyDir二、节点存储卷hostPath三、网络存储NFS 前言 在K8s中用Volume为容器提供了外部的存储能力。 Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeM…...

Go语言中‘String’包中的‘Cut‘函数的实现
Go语言中‘String’包中的’Cut’函数的实现 Cut函数用于在字符串**‘s’中查找子串’sep’,并将字符串’s’在子串 ‘sep’ 第一次出现的位置分割成两部分:before和after** package main import("fmt" "strings" ) func main(…...

【JAVASE】顺序和选择结构
⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈Java 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 顺序和选择 1. 顺序结构2. 分支结构2.1 …...

Oracle恢复删除的数据
不下心删除了生产库的数据或者不小心删除了一部分数据,如何恢复找回。 Oracle恢复删除数据的方法 方案一 利用oracle提供的闪回方法进行数据恢复,适用于delete删除方式 首先获取删除数据的时间点: select * from v$sql where sql_text l…...

(无人机方向)ros小白之键盘控制无人机(终端方式)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一:配置pycharm的ros开发环境二:核心代码讲解三 效果演示XTDrone 四 完整代码 前言 ubuntu 18.04 pycharm ros melodic 做一个在终端中…...

【python学习笔记】argparse --- 命令行选项、参数和子命令解析器
argparse 是 Python 的标准库中的一个模块,用于解析命令行参数。它提供了一种简单而灵活的方式来处理命令行输入,并生成易于使用的帮助文档。 使用 argparse 模块可以轻松地定义命令行参数和选项,并自动生成用法帮助和错误消息。示例&#x…...

【Java框架】RPC远程调用
RPC架构 一、RPC概述 RPC(Remote Procedure Call)叫作远程过程调用,它是利用网络从远程计算机上请求服务,可以理解为把程序的一部分放在其他远程计算机上执行。通过网络通信将调用请求发送至远程计算机后,利用远程计…...

云原生全栈体系(一)
云平台核心 第一章 为什么用云平台 环境统一按需付费即开即用稳定性强 一、国内常见云平台 阿里云、百度云、腾讯云、华为云、青云… 二、国外常见云平台 亚马逊 AWS、微软 Azure … 三、公有云 购买云服务商提供的公共服务器 公有云是最常见的云计算部署类型。公有云资…...

【【51单片机直流电机调速】】
学会电机调速,掌握中国速度 PWM的生成方法 先用户设定一个比较值,然后计数器定时自增。 当计数器<比较值,输出0 当计数器>比较值,输出1 main.c #include <REGX52.H> #include"delay.h" #include"…...