4.JoranConfigurator解析logbak.xml
文章目录
- 一、前言
- 二、源码解析
- GenericXMLConfigurator
- logback.xml解析
- 通过SaxEvent构建节点model
- 解析model节点
- DefaultProcessor解析model
- 三、总结
一、前言
上一篇介绍了logback模块解析logback.mxl文件的入口, 我们可以手动指定logback.xml文件的位置, 也可以使用其它的名字, 本节我们继续讨论logback是如何解析logback.xml文件的。
二、源码解析
拿出我们上一节的继承图

其中ContextAware和ContextAwareBase是有关日志上下文LoggerContext注入与打印启动日志的, 我们不介绍。
看到这个Aware结尾的有的同学可能会感觉到很有亲切感, 没错, spring中有很多这种Aware结尾的类, 例如ApplicationContextAware、EnvironmentAware等xxxAware, 它们都会提供一个setXxx的方法, 用来在框架启动的时候注入一个xxx对象。
GenericXMLConfigurator
public abstract class GenericXMLConfigurator extends ContextAwareBase {/*** SaxEvent解析器*/protected SaxEventInterpreter saxEventInterpreter;/*** model解析器的上下文*/protected ModelInterpretationContext modelInterpretationContext;/*** 配置文件节点路径和action的映射* 默认是SimpleRuleStore*/private RuleStore ruleStore;public final void doConfigure(URL url) throws JoranException {InputStream in = null;try {// 1.给Context设置ConfigurationWatchList; 用于配置文件热更新informContextOfURLUsedForConfiguration(getContext(), url);URLConnection urlConnection = url.openConnection();// per http://jira.qos.ch/browse/LOGBACK-117 LBCORE-105// per http://jira.qos.ch/browse/LOGBACK-163 LBCORE-127urlConnection.setUseCaches(false);in = urlConnection.getInputStream();// 2.解析配置; url.toExternalForm():返回url表示的绝对路径的字符串形式doConfigure(in, url.toExternalForm());} catch (IOException ioe) {String errMsg = "Could not open URL [" + url + "].";// 打印解析异常日志addError(errMsg, ioe);throw new JoranException(errMsg, ioe);} finally {if (in != null) {try {// 3.关闭流in.close();} catch (IOException ioe) {String errMsg = "Could not close input stream";addError(errMsg, ioe);throw new JoranException(errMsg, ioe);}}}}
}
这个方法就是开始解析logback.xml文件真正的入口了public final void doConfigure(URL url) throws JoranException
- informContextOfURLUsedForConfiguration方法用来设置动态热加载的配置文件, 也就是我们
<configuration debug="true" scan="true" scanPeriod="10 second">这里动态刷新的默认文件 - doConfigure: 进一步解析
doConfigure(final InputSource inputSource)
直接从doConfigure跳过来看这个方法即可
public final void doConfigure(final InputSource inputSource) throws JoranException {// 发布配置开始事件context.fireConfigurationEvent(newConfigurationStartedEvent(this));long threshold = System.currentTimeMillis();// 1.解析日志配置文件; 例如logback.xmlSaxEventRecorder recorder = populateSaxEventRecorder(inputSource);// 获取解析节点的结果; 每个节点都会解析成StartEvent, BodyEvent, EndEventList<SaxEvent> saxEvents = recorder.getSaxEventList();if (saxEvents.isEmpty()) {addWarn("Empty sax event list");return;}// 2.根据xml节点的解析生成对应的model对象, top默认是configuration的modelModel top = buildModelFromSaxEventList(recorder.getSaxEventList());if (top == null) {addError(ErrorCodes.EMPTY_MODEL_STACK);return;}// 3.语法检查sanityCheck(top);// 4.解析model节点(核心)processModel(top);// no exceptions at this levelStatusUtil statusUtil = new StatusUtil(context);// 5.发布配置解析结束事件if (statusUtil.noXMLParsingErrorsOccurred(threshold)) {// xml解析无异常addInfo("Registering current configuration as safe fallback point");registerSafeConfiguration(top);context.fireConfigurationEvent(newConfigurationEndedSuccessfullyEvent(this));} else {// xml解析发生异常context.fireConfigurationEvent(newConfigurationEndedWithXMLParsingErrorsEvent(this));}}
方法小结
这里就是解析logback.xml的整个流程了, 编排了5个点
- populateSaxEventRecorder方法用来解析文件, 然后返回解析对象
- 根据解析logback.xml的结果生成对应的model
- 检查语法(不介绍)
- 解析model节点(核心)
- 发布解析完成事件(成功/失败)
logback.xml解析
populateSaxEventRecorder
public SaxEventRecorder populateSaxEventRecorder(final InputSource inputSource) throws JoranException {SaxEventRecorder recorder = new SaxEventRecorder(context);// sax解析配置文件, 每一个节点都会解析成SaxEvent, 分为StartEvent, BodyEvent, EndEventrecorder.recordEvents(inputSource);return recorder;
}
SaxEventRecorder
public class SaxEventRecorder extends DefaultHandler implements ContextAware {// 节点路径final ElementPath elementPath;// 解析节点得到的结果对象List<SaxEvent> saxEventList = new ArrayList<SaxEvent>();public void recordEvents(InputSource inputSource) throws JoranException {// 创建sax解析器SAXParser saxParser = buildSaxParser();try {// sax解析; 当前类SaxEventRecorder也是个DefaultHandlersaxParser.parse(inputSource, this);return;} catch (xxxException ie) {// ...异常处理}throw new IllegalStateException("This point can never be reached");}// 解析节点的起始标签public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {// ...}// 解析标签内容部分public void characters(char[] ch, int start, int length) {// ...}// 解析到标签结尾部分时触发public void endElement(String namespaceURI, String localName, String qName) {// ... }
}
方法小结
- SaxEventRecorder对象用来封装解析logback.xml的逻辑, 同时它也是一个
DefaultHandler对象, 负责处理每个节点的具体解析逻辑 - 使用sax解析logback.xml文件
- 每个节点解析结果存放在实例变量saxEventList中
关于常见的xml解析框架的对比如下
| 特性 | DOM4J | SAX | JSOUP |
|---|---|---|---|
| 解析方式 | 基于树模型,加载整个文档到内存 | 基于事件驱动,逐行解析 | 类似 DOM 树模型,专注于 HTML/XML |
| 性能 | 性能较高,但文件过大时内存消耗明显 | 性能最高,适合大文件解析 | 性能适中,适合中小型 XML 或 HTML 文档 |
| 内存占用 | 较高,依赖于内存加载整个文档 | 最低,仅在解析时占用较少内存 | 较高,但通常适合处理网页等较小文件 |
| 功能支持 | 强大的 XPath 支持,支持修改和生成 XML | 只支持读取,不能修改文档 | 支持解析和修改文档,HTML/XML 均适用 |
| 易用性 | 较高,API 友好 | 较低,需要手动处理事件逻辑 | 非常高,简洁的 API,类似 jQuery 操作 |
| 修改能力 | 支持动态修改 | 不支持修改 | 支持动态修改,灵活度高 |
| 适用场景 | 适合处理中小型 XML 文件 | 适合处理超大文件或流式读取 | 适合处理 HTML/XML 文件,尤其是网页解析 |
| 依赖性 | 需要引入额外依赖(如 dom4j jar 包) | 无需额外依赖,Java 内置支持 | 需要引入 jsoup jar 包 |
-
DOM4J:功能全面,支持 XPath,适合需要频繁修改 XML 的场景,但处理超大文件时会占用大量内存。
-
SAX:性能最佳,占用内存最少,适合超大文件的解析,但使用复杂且无法修改文档内容。
-
JSOUP:偏向网页内容解析,API 简单易用,支持 XML 和 HTML 的解析和修改,适合中小型文件处理。
通过SaxEvent构建节点model
buildModelFromSaxEventList
// 通过节点的saxEvent构建节点的model
public Model buildModelFromSaxEventList(List<SaxEvent> saxEvents) throws JoranException {// 构建saxEvent解析器buildSaxEventInterpreter(saxEvents);// 解析节点, 解析节点的顺序是StartEvent, BodyEvent, EndEvent, 最终使用playSaxEvents();Model top = saxEventInterpreter.getSaxEventInterpretationContext().peekModel();return top;
}// 构建saxEvent解析器, 并添加标签路径对应的action
protected void buildSaxEventInterpreter(List<SaxEvent> saxEvents) {// 1.创建ruleStore, 默认是SimpleRuleStoreRuleStore rs = getRuleStore();// 2.将路径和对应的解析对象action绑定addElementSelectorAndActionAssociations(rs);// 3.构建saxEvent解析器this.saxEventInterpreter = new SaxEventInterpreter(context, rs, initialElementPath(), saxEvents);// 给saxEvent解析器上下文添加contextSaxEventInterpretationContext interpretationContext = saxEventInterpreter.getSaxEventInterpretationContext();interpretationContext.setContext(context);// 4.给没有指定action的标签路径添加默认action; 这里是ImplicitModelAction, 用来解析ruleStore规则之外的标签, 给父标签对象添加属性用setImplicitRuleSupplier(saxEventInterpreter);
}
方法小结
- 创建ruleStore, 默认是SimpleRuleStore
- 将路径和对应的解析对象action绑定
- 构建saxEvent解析器
- 给没有指定action的标签路径添加默认action; 这里是ImplicitModelAction, 用来解析ruleStore规则之外的标签, 给父标签对象添加属性用
具体的解析逻辑在saxEvent解析器SaxEventInterpreter中, saxEvent经过action处理之后会得到对应标签节点的model对象
解析model节点
public void processModel(Model model) {// 1.创建ModelInterpretationContext并添加默认对象; 当一个标签没有指定class时, 会从这里尝试获取buildModelInterpretationContext();// configuration节点this.modelInterpretationContext.setTopModel(model);modelInterpretationContext.setConfiguratorHint(this);// 2.创建解析model的核心类DefaultProcessor defaultProcessor = new DefaultProcessor(context, this.modelInterpretationContext);// 3.将model与modelHandler和Analyser关联addModelHandlerAssociations(defaultProcessor);// disallow simultaneous configurations of the same contextReentrantLock configurationLock = context.getConfigurationLock();try {configurationLock.lock();// 开始解析modeldefaultProcessor.process(model);} finally {configurationLock.unlock();}
}
方法小结
- 构建model解析时的上下文ModelInterpretationContext, 并添加默认标签的class类(如下面的表格)
- 创建解析model的核心类DefaultProcessor
- 将model和对应的处理类(modelHandler)关联起来
- 使用DefaultProcessor解析model
默认标签的属性对应的类
通过buildModelInterpretationContext方法添加在ModelInterpretationContext.DefaultNestedComponentRegistry属性中
| 类 | 属性 | 默认值 |
|---|---|---|
| AppenderBase | layout | PatternLayout.class |
| UnsynchronizedAppenderBase | layout | PatternLayout.class |
| AppenderBase | encoder | PatternLayoutEncoder |
| UnsynchronizedAppenderBase | encoder | PatternLayoutEncoder |
| SSLComponent | ssl | SSLConfiguration |
| SSLConfiguration | parameters | SSLParametersConfiguration |
| SSLConfiguration | keyStore | KeyStoreFactoryBean |
| SSLConfiguration | trustStore | KeyStoreFactoryBean |
| SSLConfiguration | keyManagerFactory | KeyManagerFactoryFactoryBean |
| SSLConfiguration | trustManagerFactory | TrustManagerFactoryFactoryBean |
| SSLConfiguration | secureRandom | SecureRandomFactoryBean |
例如下面的配置, 由于FileAppender是UnsynchronizedAppenderBase的子类, 并且encoder节点没有指定class, 而encoder是UnsynchronizedAppenderBase的一个属性, 所以这里取默认值PatternLayoutEncoder
<appender name="FILE" class="ch.qos.logback.core.FileAppender"><file>logs/app.log</file><!-- encoder不指定class的时候, 默认使用的是PatternLayoutEncoder --><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n</pattern></encoder>
</appender>
我们常用的也就appender标签下的这两个layout和encoder属性
各标签节点路径以及其对应的model和modelHandler如下表格
一般情况下我们看节点路径和action以及handler就行, 这个handler就是用来处理logback.xml中各个标签的类。
这里的节点路径就是我们logback.xml文件中所有可以定义的节点了。
| 标签节点路径 | 解析路径节点的Action | action解析之后生成的model | 解析model的Handler |
|---|---|---|---|
| configuration | ConfigurationAction | ConfigurationModel | ConfigurationModelHandlerFull |
| configuration/contextName | ContextNameAction | ContextNameModel | ContextNameModelHandler |
| configuration/contextListener | LoggerContextListenerAction | LoggerContextListenerModel | LoggerContextListenerModelHandler |
| configuration/insertFromJNDI | InsertFromJNDIAction | InsertFromJNDIModel | InsertFromJNDIModelHandler |
| configuration/logger | LoggerAction | LoggerModel | LoggerModelHandler |
| configuration/logger/level | LevelAction | LevelModel | LevelModelHandler |
| configuration/root | RootLoggerAction | RootLoggerModel | RootLoggerModelHandler |
| configuration/root/level | RootLoggerAction | RootLoggerModel | RootLoggerModelHandler |
| configuration/logger/appender-ref | AppenderRefAction | AppenderRefModel | AppenderRefModelHandler |
| configuration/root/appender-ref | AppenderRefAction | AppenderRefModel | AppenderRefModelHandler |
| configuration/include | IncludeAction | IncludeModel | IncludeModelHandler |
| configuration/propertiesConfigurator | PropertiesConfiguratorAction | PropertiesConfiguratorModel | PropertiesConfiguratorModelHandler |
| configuration/consolePlugin | ConsolePluginAction | 无 | 无 |
| configuration/receiver | ReceiverAction | ReceiverModel | ReceiverModelHandler |
| */variable | PropertyAction | PropertyModel | PropertyModelHandler |
| */property | PropertyAction | PropertyModel | PropertyModelHandler |
| configuration/import | ImportAction | ImportModel | ImportModelHandler |
| configuration/timestamp | TimestampAction | TimestampModel | TimestampModelHandler |
| configuration/shutdownHook | ShutdownHookAction | ShutdownHookModel | ShutdownHookModelHandler |
| configuration/sequenceNumberGenerator | SequenceNumberGeneratorAction | SequenceNumberGeneratorModel | SequenceNumberGeneratorModelHandler |
| configuration/serializeModel | SerializeModelAction | SerializeModelModel | SerializeModelModelHandler |
| configuration/define | DefinePropertyAction | DefineModel | DefineModelHandler |
| configuration/evaluator | EventEvaluatorAction | EventEvaluatorModel | EventEvaluatorModelHandler |
| configuration/conversionRule | ConversionRuleAction | ConversionRuleModel | ConversionRuleModelHandler |
| configuration/statusListener | StatusListenerAction | StatusListenerModel | StatusListenerModelHandler |
| */appender | AppenderAction | AppenderModel | AppenderModelHandler |
| configuration/appender/appender-ref | AppenderRefAction | AppenderRefModel | AppenderRefModelHandler |
| configuration/newRule | NewRuleAction | 无 | 无 |
| */param | ParamAction | ParamModel | ParamModelHandler |
| */if | IfAction | IfModel | IfModelHandler |
| */if/then | ThenAction | ThenModel | ThenModelHandler |
| */if/else | ElseAction | ElseModel | ElseModelHandler |
| */appender/sift | SiftAction | SiftModel | SiftModelHandler |
| 其它属性标签 | ImplicitModelAction | ImplicitModel | ImplicitModelHandler |
DefaultProcessor解析model
public void process(Model model) {// 根节点为空, 直接异常if (model == null) {addError("Expecting non null model to process");return;}// 1.将LoggerContext添加到ModelInterpretationContext中, 这是第一个也是最底层的initialObjectPush();// 2.使用第一阶段过滤器过滤model, 将满足条件的model使用handler处理mainTraverse(model, getPhaseOneFilter());// 3.处理依赖analyseDependencies(model);// 4.使用第二阶段过滤器过滤model, 将满足条件的model使用handler处理traversalLoop(this::secondPhaseTraverse, model, getPhaseTwoFilter(), "phase 2");// 配置解析完成addInfo("End of configuration.");// 5.将LoggerContext从ModelInterpretationContext中弹出finalObjectPop();
}
方法小结
- 将日志上下文loggerContext放到model解析器中
- 使用第一阶段过滤器过滤model, 将满足条件的model使用handler处理, 不满足第一阶段过滤器的model有下面四个, 为什么这四个model这么特殊呢?? 因为它们需要依赖别的model(appender-ref标签)
- LoggerModel
- RootLoggerModel
- AppenderModel
- AppenderRefModel
- 确定依赖顺序
- 使用第二阶段过滤器过滤model, 将满足条件的model使用handler处理; 上面四个model将会在这里处理
- 弹出loggerContext节点
具体的model节点解析将会在下节挑出几个重点来介绍, 到这里, logback解析logback.xml文件的整体流程就介绍完了
关于一些细节以及JoranConfigurator和JoranConfiguratorBase中相关的内容没有详细介绍, 读者想要了解的更多建议看下源码
三、总结
- JoranConfigurator 是logback框架用来解析配置文件的核心类(logback.xml配置文件)
- logback.xml文件中每个节点都会被解析成一个saxEvent, 解析过程中借助解析器上下文SaxEventInterpretationContext保存相关信息
- RuleStore中映射了每个节点路径对应的action, action会创建对应节点的model
- DefaultProcessor中记录了每个model和modelHandler的映射关系
- DefaultProcessor借助上下文对象ModelInterpretationContext将model分为两个阶段使用modelHandler进行处理
- 最后将处理结果都放到了日志上下文LoggerContext中(这是我们打印日志的重要对象)
- 流程就是(eg. configuration/appender/encoder -> saxEvent -> action -> model -> modelHandler -> loggerContext)
相关文章:
4.JoranConfigurator解析logbak.xml
文章目录 一、前言二、源码解析GenericXMLConfiguratorlogback.xml解析通过SaxEvent构建节点model解析model节点DefaultProcessor解析model 三、总结 一、前言 上一篇介绍了logback模块解析logback.mxl文件的入口, 我们可以手动指定logback.xml文件的位置, 也可以使用其它的名…...
React 19 新特性总结
具体详见官网: 中文:React 19 新特性 英文:React 19 新特性 核心新特性 1. Actions 解决问题:简化数据变更和状态更新流程 以前需要手动处理待定状态、错误、乐观更新和顺序请求需要维护多个状态变量(isPending, error 等) 新…...
kafka学习笔记6 ACL权限 —— 筑梦之路
在Kafka中,ACL(Access Control List)是用来控制谁可以访问Kafka资源(如主题、消费者组等)的权限机制。ACL配置基于Kafka的kafka-acls.sh工具,能够管理对资源的读取、写入等操作权限。 ACL介绍 Kafka的ACL是…...
【Java】Java抛异常到用户界面公共封装
前言 在Java中处理代码运行异常是常见的技术点之一,我们大部分会使用封装的技巧将异常进行格式化输出,方便反馈给用户界面,也是为了代码复用 看看这行代码是怎么处理异常的 CommonExceptionType.SimpleException.throwEx("用户信息不…...
基于Redis实现短信验证码登录
目录 1 基于Session实现短信验证码登录 2 配置登录拦截器 3 配置完拦截器还需将自定义拦截器添加到SpringMVC的拦截器列表中 才能生效 4 Session集群共享问题 5 基于Redis实现短信验证码登录 6 Hash 结构与 String 结构类型的比较 7 Redis替代Session需要考虑的问题 8 …...
步入响应式编程篇(二)之Reactor API
步入响应式编程篇(二)之Reactor API 前言回顾响应式编程Reactor API的使用Stream引入依赖Reactor API的使用流源头的创建 reactor api的背压模式发布者与订阅者使用的线程查看弹珠图查看形成新流的日志 前言 对于响应式编程的基于概念,以及J…...
Oracle SQL: TRANSLATE 和 REGEXP_LIKE 的知识点详细分析
目录 前言1. TRANSLATE2. REGEXP_LIKE3. 实战 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 1. TRANSLATE TRANSLATE 用于替换字符串中指定字符集的每个字符,返回替换后的字符串 逐一映射输入字…...
RabbitMQ 在实际应用时要注意的问题
1. 幂等性保障 1.1 幂等性介绍 幂等性是数学和计算机科学中某些运算的性质,它们可以被多次应⽤,⽽不会改变初始应⽤的结果. 应⽤程序的幂等性介绍 在应⽤程序中,幂等性就是指对⼀个系统进⾏重复调⽤(相同参数),不论请求多少次,这些请求对系统的影响都是相同的效果. ⽐如数据库…...
算法日记8:StarryCoding60(单调栈)
一、题目 二、解题思路: 题意为让我们找到每个元素的左边第一个比它小的元素,若不存在则输出-1 2.1法一:暴力(0n2) 首先,我们可以想到最朴素的算法:直接暴力两层for达成目标核心代码如下&…...
大象机器人发布首款穿戴式数据采集器myController S570,助力具身智能数据收集!
myController S570 具有较高的数据采集速度和远程控制能力,大大简化了人形机器人的编程。 myController S570 是一款可移动的轻量级外骨骼,具有 14 个关节、2 个操纵杆和 2 个按钮,它提供高数据采集速度,出色的兼容性,…...
【银河麒麟高级服务器操作系统】业务访问慢网卡丢包现象分析及处理过程
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:product.kylinos.cn 开发者专区:developer.kylinos.cn 文档中心:document.kylinos.cn 交流论坛:forum.kylinos.cn 服务器环境以及配置 【内核版本…...
C语言之饭店外卖信息管理系统
🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 C语言之饭店外卖信息管理系统 目录 设计题目设计目的设计任务描述设计要求输入和输出要求验…...
记一次 .NET某数字化协同管理系统 内存暴涨分析
一:背景 1. 讲故事 高级调试训练营里的一位朋友找到我,说他们跑在linux上的.NET程序出现了内存泄露的情况,上windbg观察发现内存都是IMAGE给吃掉了,那些image都标记了 doublemapper__deleted_ 字样,问我为啥会这样&a…...
部门管理查询部门,nginx反向代理,前端如何访问到后端Tomcat 注解@RequestParam
接口开发 增删改通常是不用返回data数据,返回null 列表查询-结果封装,时间 前后端联调测试 nginx反向代理,前端如何访问到后端Tomcat服务器 删除部门...
JS通过ASCII码值实现随机字符串的生成(可指定长度以及解决首位不出现数值)
在之前写过一篇“JS实现随机生成字符串(可指定长度)”,当时写的过于简单和传统,比较粗放。此次针对此问题,对随机生成字符串的功能进行优化处理,对随机取到的字符都通过程序自动来完成。 在写之前ÿ…...
速通Docker === 快速部署Redis主从集群
目录 镜像仓库介绍 持久化你的数据库 连接到其他容器 创建自定义网络 部署主节点 部署从节点 验证部署 总结 在现代应用架构中,Redis作为一个高性能的内存数据库,被广泛应用于缓存、会话存储、实时分析等多个领域。为了提高Redis的可用性和数据的…...
论文笔记(六十三)Understanding Diffusion Models: A Unified Perspective(一)
Understanding Diffusion Models: A Unified Perspective(一) 文章概括引言:生成模型背景:ELBO、VAE 和分层 VAE证据下界(Evidence Lower Bound)变分自编码器 (Variational Autoencoders&#x…...
stm32使用MDK5.35时遇到*** TOOLS.INI: TOOLCHAIN NOT INSTALLED
mdk5.35出现*** TOOLS.INI: TOOLCHAIN NOT INSTALLED的问题!!!! 以管理员身份重新打开MDK5.35.0.0,用keygen破解密码,但是一直提示我是没有破解成功。 解决办法: target 改成ARM...
在Ubuntu上安装RabbitMQ教程
1、安装erlang 因为rabbitmq是基于erlang开发的,所以要安装rabbitmq,首先需要安装erlang运行环境 apt-get install erlang执行命令查是否安装成功:erl,疯狂 Ctrlc 就能退出命令行 2、安装rabbitmq 1、查看erlang与rabbitmq版本…...
【算法】集合List和队列
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 零:集合,队列的用法 一:字母异位词分组 二:二叉树的锯…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
对象回调初步研究
_OBJECT_TYPE结构分析 在介绍什么是对象回调前,首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例,用_OBJECT_TYPE这个结构来解析它,0x80处就是今天要介绍的回调链表,但是先不着急,先把目光…...
