当前位置: 首页 > news >正文

4.JoranConfigurator解析logbak.xml

文章目录

  • 一、前言
  • 二、源码解析
    • GenericXMLConfigurator
      • logback.xml解析
      • 通过SaxEvent构建节点model
      • 解析model节点
      • DefaultProcessor解析model
  • 三、总结

一、前言

上一篇介绍了logback模块解析logback.mxl文件的入口, 我们可以手动指定logback.xml文件的位置, 也可以使用其它的名字, 本节我们继续讨论logback是如何解析logback.xml文件的。

二、源码解析

拿出我们上一节的继承图
在这里插入图片描述

其中ContextAwareContextAwareBase是有关日志上下文LoggerContext注入与打印启动日志的, 我们不介绍。

看到这个Aware结尾的有的同学可能会感觉到很有亲切感, 没错, spring中有很多这种Aware结尾的类, 例如ApplicationContextAwareEnvironmentAware等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

  1. informContextOfURLUsedForConfiguration方法用来设置动态热加载的配置文件, 也就是我们<configuration debug="true" scan="true" scanPeriod="10 second"> 这里动态刷新的默认文件
  2. 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个点

  1. populateSaxEventRecorder方法用来解析文件, 然后返回解析对象
  2. 根据解析logback.xml的结果生成对应的model
  3. 检查语法(不介绍)
  4. 解析model节点(核心)
  5. 发布解析完成事件(成功/失败)

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) {// ...   }
}

方法小结

  1. SaxEventRecorder对象用来封装解析logback.xml的逻辑, 同时它也是一个DefaultHandler对象, 负责处理每个节点的具体解析逻辑
  2. 使用sax解析logback.xml文件
  3. 每个节点解析结果存放在实例变量saxEventList中

关于常见的xml解析框架的对比如下

特性DOM4JSAXJSOUP
解析方式基于树模型,加载整个文档到内存基于事件驱动,逐行解析类似 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);
}

方法小结

  1. 创建ruleStore, 默认是SimpleRuleStore
  2. 将路径和对应的解析对象action绑定
  3. 构建saxEvent解析器
  4. 给没有指定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();}
}

方法小结

  1. 构建model解析时的上下文ModelInterpretationContext, 并添加默认标签的class类(如下面的表格)
  2. 创建解析model的核心类DefaultProcessor
  3. 将model和对应的处理类(modelHandler)关联起来
  4. 使用DefaultProcessor解析model

默认标签的属性对应的类

通过buildModelInterpretationContext方法添加在ModelInterpretationContext.DefaultNestedComponentRegistry属性中

属性默认值
AppenderBaselayoutPatternLayout.class
UnsynchronizedAppenderBaselayoutPatternLayout.class
AppenderBaseencoderPatternLayoutEncoder
UnsynchronizedAppenderBaseencoderPatternLayoutEncoder
SSLComponentsslSSLConfiguration
SSLConfigurationparametersSSLParametersConfiguration
SSLConfigurationkeyStoreKeyStoreFactoryBean
SSLConfigurationtrustStoreKeyStoreFactoryBean
SSLConfigurationkeyManagerFactoryKeyManagerFactoryFactoryBean
SSLConfigurationtrustManagerFactoryTrustManagerFactoryFactoryBean
SSLConfigurationsecureRandomSecureRandomFactoryBean

例如下面的配置, 由于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文件中所有可以定义的节点了。

标签节点路径解析路径节点的Actionaction解析之后生成的model解析model的Handler
configurationConfigurationActionConfigurationModelConfigurationModelHandlerFull
configuration/contextNameContextNameActionContextNameModelContextNameModelHandler
configuration/contextListenerLoggerContextListenerActionLoggerContextListenerModelLoggerContextListenerModelHandler
configuration/insertFromJNDIInsertFromJNDIActionInsertFromJNDIModelInsertFromJNDIModelHandler
configuration/loggerLoggerActionLoggerModelLoggerModelHandler
configuration/logger/levelLevelActionLevelModelLevelModelHandler
configuration/rootRootLoggerActionRootLoggerModelRootLoggerModelHandler
configuration/root/levelRootLoggerActionRootLoggerModelRootLoggerModelHandler
configuration/logger/appender-refAppenderRefActionAppenderRefModelAppenderRefModelHandler
configuration/root/appender-refAppenderRefActionAppenderRefModelAppenderRefModelHandler
configuration/includeIncludeActionIncludeModelIncludeModelHandler
configuration/propertiesConfiguratorPropertiesConfiguratorActionPropertiesConfiguratorModelPropertiesConfiguratorModelHandler
configuration/consolePluginConsolePluginAction
configuration/receiverReceiverActionReceiverModelReceiverModelHandler
*/variablePropertyActionPropertyModelPropertyModelHandler
*/propertyPropertyActionPropertyModelPropertyModelHandler
configuration/importImportActionImportModelImportModelHandler
configuration/timestampTimestampActionTimestampModelTimestampModelHandler
configuration/shutdownHookShutdownHookActionShutdownHookModelShutdownHookModelHandler
configuration/sequenceNumberGeneratorSequenceNumberGeneratorActionSequenceNumberGeneratorModelSequenceNumberGeneratorModelHandler
configuration/serializeModelSerializeModelActionSerializeModelModelSerializeModelModelHandler
configuration/defineDefinePropertyActionDefineModelDefineModelHandler
configuration/evaluatorEventEvaluatorActionEventEvaluatorModelEventEvaluatorModelHandler
configuration/conversionRuleConversionRuleActionConversionRuleModelConversionRuleModelHandler
configuration/statusListenerStatusListenerActionStatusListenerModelStatusListenerModelHandler
*/appenderAppenderActionAppenderModelAppenderModelHandler
configuration/appender/appender-refAppenderRefActionAppenderRefModelAppenderRefModelHandler
configuration/newRuleNewRuleAction
*/paramParamActionParamModelParamModelHandler
*/ifIfActionIfModelIfModelHandler
*/if/thenThenActionThenModelThenModelHandler
*/if/elseElseActionElseModelElseModelHandler
*/appender/siftSiftActionSiftModelSiftModelHandler
其它属性标签ImplicitModelActionImplicitModelImplicitModelHandler

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();
}

方法小结

  1. 将日志上下文loggerContext放到model解析器中
  2. 使用第一阶段过滤器过滤model, 将满足条件的model使用handler处理, 不满足第一阶段过滤器的model有下面四个, 为什么这四个model这么特殊呢?? 因为它们需要依赖别的model(appender-ref标签)
  • LoggerModel
  • RootLoggerModel
  • AppenderModel
  • AppenderRefModel
  1. 确定依赖顺序
  2. 使用第二阶段过滤器过滤model, 将满足条件的model使用handler处理; 上面四个model将会在这里处理
  3. 弹出loggerContext节点

具体的model节点解析将会在下节挑出几个重点来介绍, 到这里, logback解析logback.xml文件的整体流程就介绍完了

关于一些细节以及JoranConfigurator和JoranConfiguratorBase中相关的内容没有详细介绍, 读者想要了解的更多建议看下源码

三、总结

  1. JoranConfigurator 是logback框架用来解析配置文件的核心类(logback.xml配置文件)
  2. logback.xml文件中每个节点都会被解析成一个saxEvent, 解析过程中借助解析器上下文SaxEventInterpretationContext保存相关信息
  3. RuleStore中映射了每个节点路径对应的action, action会创建对应节点的model
  4. DefaultProcessor中记录了每个model和modelHandler的映射关系
  5. DefaultProcessor借助上下文对象ModelInterpretationContext将model分为两个阶段使用modelHandler进行处理
  6. 最后将处理结果都放到了日志上下文LoggerContext中(这是我们打印日志的重要对象)
  7. 流程就是(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文件的位置, 也可以使用其它的名…...

JavaWeb开发(十六)实战-生鲜后台管理系统(三)BeanUtils介绍、Servlet的抽取

1. 生鲜后台管理系统-BeanUtils的使用 1.1. BeanUtils介绍 BeanUtils 是 Apache commons组件的成员之一&#xff0c;主要用于简化JavaBean封装数据的操作。它可以给JavaBean封装一个字符串数据&#xff0c;也可以将一个表单提交的所有数据封装到JavaBean中。使用第三方工具&am…...

人形机器人将制造iPhone!

前言 优必选机器人和富士康通过一项突破性的合作伙伴关系&#xff0c;正在将先进的人形机器人&#xff08;如Walker S1及其升级版Walker S2&#xff09;整合到制造流程中&#xff0c;以改变iPhone的生产方式。这一合作旨在通过提升机器人能力、优化工作流程以及实现更智能的自动…...

Oracle 深入学习 Part 14:Managing Password Security and Resources(管理密码安全性和资源)

Profiles Profile 是一个以名称标识的集合&#xff0c;用于管理 密码 和 资源限制。 每个用户都对应一个profiles&#xff0c;可以通过 CREATE USER 或 ALTER USER 命令分配给用户。 Profiles 可以启用或禁用。 Profiles 可以关联到默认的 DEFAULT Profile。 密码管理&…...

202209 青少年软件编程等级考试C/C++ 二级真题答案及解析(电子学会)

第 1 题 统计误差范围内的数 统计一个整数序列中与指定数字m误差范围小于等于X的数的个数。 时间限制:5000 内存限制:65536 输入 输入包含三行: 第一行为N,表示整数序列的长度(N <= 100); 第二行为N个整数,整数之间以一个空格分开; 第三行包含2个整数,为指定…...

qt中透明度表示

透明度的表示方法 在 Qt 样式表中&#xff0c;使用 rgba 或 argb 颜色表示法时&#xff0c;透明度通常用一个介于 0 和 1 之间的小数表示。 rgba 表示法&#xff1a;rgba(red, green, blue, alpha)&#xff0c;其中 alpha 是透明度&#xff0c;例如 rgba(255, 0, 0, 0.5) 表示…...

Mybatis 进阶 / Mybatis—Puls (详细)

目录 一.动态SQL 1.1标签 1.2 标签 1.3标签 1.4标签 1.5标签 1.6标签 mybatis总结&#xff1a; 二.Mybatis-Puls 2.1准备工作 2.2CRUD单元测试 2.2.1创建UserInfo实体类 2.2.2编写Mapper接⼝类 2.2.3 测试类 2.3 常见注解 2.3.1TableName 2.3.2TableField 2.4打印日…...

opencv在图片上添加中文汉字(c++以及python)

opencv在图片上添加中文汉字&#xff08;c以及python&#xff09;_c opencv绘制中文 知乎-CSDN博客 环境&#xff1a; ubuntu18.04 desktopopencv 3.4.15 opencv是不支持中文的。 这里C代码是采用替换原图的像素点来实现的&#xff0c;实现之前我们先了解一下汉字点阵字库。…...

js截取video视频某一帧为图片

1.代码如下 <template><div class"box"><div class"video-box"><video controls ref"videoRef" preload"true"src"https://qt-minio.ictshop.com.cn:9000/resource-management/2025/01/08/7b96ac9d957c45a…...

Observability:最大化可观察性 AI 助手体验的 5 大提示(prompts)

作者&#xff1a;来自 Elastic Zoia_AUBRY 在过去三年担任客户工程师期间&#xff0c;我遇到了数百名客户&#xff0c;他们最常问的问题之一是&#xff1a;“我的数据在 Elastic 中&#xff1b;我该如何利用它获得最大优势&#xff1f;”。 如果这适用于你&#xff0c;那么本…...

HDFS的架构优势与基本操作

目录 写在前面一、 HDFS概述 1.1 HDFS简介1.2 HDFS优缺点 1.2.1 优点1.2.2 缺点 1.3 HDFS组成架构1.4 HDFS文件块大小 二、HDFS的Shell操作&#xff08;开发重点&#xff09; 2.1 基本语法2.2 命令大全2.3 常用命令实操 2.3.1 上传2.3.2 下载2.3.3 HDFS直接操作 三、HDFS的AP…...

hive表修改字段类型没有级连导致历史分区报错

一&#xff1a;问题背景 修改hive的分区表时有级连概念&#xff0c;指字段的最新状态&#xff0c;默认只对往后的分区数据生效&#xff0c;而之前的分区保留历史元数据状态。好处就是修改语句的效率很快&#xff0c;坏处就是如果历史分区的数据还有用&#xff0c;那就回发生分…...

023:到底什么是感受野?

本文为合集收录&#xff0c;欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请查看这里。 在前面介绍卷积算法时&#xff0c;一直在强调一个内容&#xff0c;那就是卷积算法的运算过程是—— 卷积核在输入图像上滑动扫描的过程。 在每一次扫描时&#xff0c;可以…...

GoFrame g.* 方法和数据类型

GoFrame g.* 方法和数据类型 GoFrame 框架通过 g.* 方法提供了一系列常用的数据类型和对象获取方法。这个模块采用强耦合设计&#xff0c;目的是为开发者提供便捷的类型和对象调用方式。 使用方式 import "github.com/gogf/gf/v2/frame/g"数据类型 基础类型别名 …...

分苹果,若a ^ b ^ c = 0意味着:a 和 (b ^ c) 的值相等,或者 b 和 (a ^ c) 的值相等,以及 c 和 (a ^ b) 的值相等。

若a ^ b ^ c faultSum&#xff0c;那么faultSum 0时&#xff0c;即可产生上面的平分方案。说明可以满足二进制平分 #include<bits/stdc.h> using namespace std; int main() { int n; cin>>n; vector<int> weight(n); for(int i0;i<n;i) {…...

深入解析人工智能中的协同过滤算法及其在推荐系统中的应用与优化

目录 什么是协同过滤算法核心原理基本步骤相似度计算代码实现详解1.流程图2.创建基础的数据结构存储用户评分数据3.计算用户相似度4.获取相似用户5.推荐方法 算法优化建议1. 数据预处理优化去除异常值和噪声数据进行数据标准化使用稀疏矩阵优化存储 2. 相似度计算优化使用局部敏…...

电梯系统的UML文档04

这个版本的类图是直接从4.2节中用例图的描述得来的&#xff0c;这个视图中的类覆盖了系统所有的功能。我们用电梯类和电梯控制器类&#xff08;ElevatorControl&#xff09;移动或停止电梯&#xff1b;用门类开门或关门&#xff1b;用指示器类让乘客知道电梯的位置和方向&#…...

《自动驾驶与机器人中的SLAM技术》ch4:预积分学

目录 1 预积分的定义 2 预积分的测量模型 ( 预积分的测量值可由 IMU 的测量值积分得到 ) 2.1 旋转部分 2.2 速度部分 2.3 平移部分 2.4 将预积分测量和误差式代回最初的定义式 3 预积分的噪声模型和协方差矩阵 3.1 旋转部分 3.2 速度部分 3.3 平移部分 3.4 噪声项合并 4 零偏的…...

海量数据的处理

一般来说都是针对数据量特别大&#xff0c;内存有限制的。 第一类&#xff1a;topk问题 比如&#xff0c;在海量数据中找前50大的数据怎么办&#xff1f; 方法一&#xff1a;使用小顶堆&#xff0c;用小顶堆维护这50个元素&#xff0c;当有新元素到来时&#xff0c;直接与堆…...

Python人脸识别库DeepFace使用教程及源码解析

目录 一、DeepFace介绍 1、人脸库设计 2、DeepFace.find 3、DeepFace.verify 4、DeepFace.analyze 5、DeepFace.extract_faces 6、DeepFace.represent 7、DeepFace.stream 二、DeepFace二次开发 1、开发活体检测API 2、模型权重持久化 三、总结 一、DeepFace介绍 …...

Nacos:使用PgSQL数据源

数据源插件开源仓库地址&#xff1a;nacos-datasource-extend-plugins 一、PostgreSQL数据库安装 1、本文使用Docker进行数据库的安装&#xff0c;使用docker命令拉取的PG14版本的数据库&#xff1a; docker pull postgres:14.6 2、创建PG容器并启动&#xff0c;映射了5432…...

基于Python的多元医疗知识图谱构建与应用研究(下)

五、基于医疗知识图谱的医疗知识图谱程序构建 5.1 数据层构建 5.1.1 数据源选择与获取 在构建基于医疗知识图谱的医疗知识图谱数据层时,数据源的选择与获取至关重要。数据源的质量和丰富度直接决定了知识图谱的可靠性和实用性。医学文献是重要的数据源之一,包括学术期刊论…...

JAVA:Spring Boot 实现责任链模式处理订单流程的技术指南

1、简述 在复杂的业务系统中&#xff0c;订单流程往往需要一系列的操作&#xff0c;比如验证订单、检查库存、处理支付、更新订单状态等。责任链模式&#xff08;Chain of Responsibility&#xff09;可以帮助我们将这些处理步骤分开&#xff0c;并且以链式方式处理每一个操作…...

SpringBoot多级配置文件

1.问题先导 有这样的场景&#xff0c;我们开发完毕后需要测试人员进行测试&#xff0c;由于测试环境和开发环境的很多配置都不相同&#xff0c;所以测试人员在运 行我们的工程时需要临时修改很多配置&#xff0c;如下 java –jar springboot.jar –-spring.profiles.activete…...

阿里云安装mikrotik7配置内网互通

阿里云近期推出了200M不限量机器&#xff0c;对于没有公网接入的中小企业可以借助这个机器对多地分支机构进行内网互通。目前已经有很多机构用这个搞跨云k8s,跨云集群了。 mikrotik作为一个商用的软件&#xff0c;操作性比一些开源的软件好用不少。 本文使用的网段为172.16.1…...

std::forward实现原理与应用场景

std::forward 是 C11 引入的一个函数模板&#xff0c;用于实现完美转发&#xff08;Perfect Forwarding&#xff09;。它的核心作用是根据传入的参数&#xff0c;决定将参数以左值引用还是右值引用的方式进行转发&#xff0c;从而保持参数的原始值类别。 实现原理 template&l…...

TiDB 在市面上的热门应用领域

TiDB 在市面上的热门应用领域 TiDB 作为一款分布式数据库&#xff0c;凭借其高可扩展性和强一致性&#xff0c;逐渐成为多个行业和领域的热门选择。那么&#xff0c;TiDB 在市面上主要应用在哪些领域呢&#xff1f;今天我们来看看 TiDB 在几个热门领域的应用场景。 1. 互联网…...

“深入浅出”系列之C++:(11)推荐一些C++的开源项目

1. SQLiteCpp - 简单易用的Sqlite C封装库 仓库地址&#xff1a;https://github.com/SRombauts/SQLiteCpp 简介&#xff1a;SQLiteCpp是一个对Sqlite数据库进行C封装的开源库&#xff0c;代码行数约2,500行。它提供了简洁易用的接口&#xff0c;使得在C项目中操作Sqlite数据库…...

高等数学学习笔记 ☞ 定积分的积分方法

1. 定积分的换元积分法 1. 换元积分公式&#xff1a;设函数在闭区间上连续&#xff0c;令&#xff0c;若满足&#xff1a; ①&#xff1a;当时&#xff0c;&#xff1b;当时&#xff0c;。 此时的大小关系不一定&#xff0c;但与最好对应着写&#xff0c;否则就要留意变号的问…...

KVA教程-插件开发

“如果结果不如你所愿&#xff0c;就在尘埃落定前奋力一搏。”——《夏目友人帐》 “有些事不是看到了希望才去坚持&#xff0c;而是因为坚持才会看到希望。”——《十宗罪》 “维持现状意味着空耗你的努力和生命。”——纪伯伦 KVA 技术教程 * 插件开发 简介 插件开发是KVA&a…...

AI守护煤矿安全生产:基于视频智能的煤矿管理系统架构解析

前言 本文我将介绍我和我的团队自主研发设计的一款AI产品的成果展示——“基于视频AI识别技术的煤矿安全生产管理系统”。 这款产品是目前我在创业阶段和几位矿业大学的博士共同从架构设计、开发到交付的全过程中首次在博客频道发布, 我之前一直想写但没有机会来整理这套系统的…...

AI编程工具横向评测--Cloudstudio塑造完全态的jupyter notebook助力数据分析应用开发

AI编程工具横向评测–Cloudstudio塑造完全态的jupyter notebook助力数据分析应用开发 数据分析类应用的开发&#xff0c;指的是首先进行数据分析&#xff0c;比如统计学分析、机器学习模型的构建等&#xff0c;然后将分析的流程开发成数据分析类的工具&#xff0c;或者将数据分…...

04JavaWeb——Maven-SpringBootWeb入门

Maven 课程内容 初识Maven Maven概述 Maven模型介绍 Maven仓库介绍 Maven安装与配置 IDEA集成Maven 依赖管理 01. Maven课程介绍 1.1 课程安排 学习完前端Web开发技术后&#xff0c;我们即将开始学习后端Web开发技术。做为一名Java开发工程师&#xff0c;后端Web开发…...

ThreeJS能力演示——界面点选交互能力

1、支持界面点选 点选模型整体思路是&#xff1a;根据camera位置作为起始点&#xff0c;叠加鼠标相对位置作为偏置&#xff0c;摄像头方向作为射线方向。 根据射线方向中的遇到的3D物体列表&#xff0c;第一个遇到的物体作为被点选的物体。 // 鼠标事件处理let selectedObjec…...

Linux:常用命令--文件与目录操作

ls命令 功能&#xff1a;&#xff08;list&#xff09;列出当前目录的文件信息 语法&#xff1a;ls [-l -h -a] [参数] 参数&#xff1a;被查看的文件夹&#xff0c;不提供参数&#xff0c;表示查看当前工作目录-l&#xff0c;以列表形式查看每个文件的属性&#xff0c;包含…...

Node.js NativeAddon 构建工具:node-gyp 安装与配置完全指南

Node.js NativeAddon 构建工具&#xff1a;node-gyp 安装与配置完全指南 node-gyp Node.js native addon build tool [这里是图片001] 项目地址: https://gitcode.com/gh_mirrors/no/node-gyp 项目基础介绍及主要编程语言 Node.js NativeAddon 构建工具&#xff08;node-gyp…...

docker运行Java项目,Kaptcha因为字体缺失没法显示验证码图片

2015工作至今&#xff0c;10年资深全栈工程师&#xff0c;CTO&#xff0c;擅长带团队、攻克各种技术难题、研发各类软件产品&#xff0c;我的代码态度&#xff1a;代码虐我千百遍&#xff0c;我待代码如初恋&#xff0c;我的工作态度&#xff1a;极致&#xff0c;责任&#xff…...

C++otlv4连接sql serveer使用记录(注意点)

C使用otlv4在做插入时&#xff0c;有一些设计的坑需要注意 插入数据&#xff1a; 当要给表中插入单个字符时&#xff0c;数据库表设计使用varchar(1)是合理的&#xff0c;但是otlv4一直报错char。 后续查很久才知道&#xff0c;otlv4所写的绑定的字符数组的长度应该实际数组…...

[思考记录]认知和思考

在以前&#xff0c;具备一定的技能和经验就能轻易找到自己的一席之地。但在AI时代下&#xff0c;这些东西很容易就被抹平&#xff0c;那么我们的竞争力又在哪里&#xff1f;“认知和思考”是一个方向&#xff0c;帮助我们能去应对复杂情境、帮我们更容易去看到真相。 1.很多时…...

前端开发Web

Ajax 概念:Asynchronous JavaScriptAnd XML&#xff0c;异步的JavaScript和XML 作用: 数据交换:通过Ajax可以给服务器发送请求&#xff0c;并获取服务器响应的数据。 异步交互:可以在不重新加载整个页面的情况下&#xff0c;与服务器交换数据并更新部分网页的…...

【C++提高篇】—— C++泛型编程之模板基本语法和使用的详解

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、模板的概念二、函数模板2.1 函数模板的使用2.2 函数模板注意事项2.3 普通函数与函数模板的区别2.4 普通函数与函数模板的调用规则2.5 模板的局限性 三、类模…...

WPS计算机二级•高效操作技巧

听说这里是目录哦 斜线表头 展示项目名称&#x1f34b;‍&#x1f7e9;横排转竖排&#x1f350;批量删除表格空白行&#x1f348;方法一方法二建辅助列找空值 能量站&#x1f61a; 斜线表头 展示项目名称&#x1f34b;‍&#x1f7e9; 选中单元格&#xff0c;单击右键➡️“设…...

【Maui】视图界面与数据模型绑定

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;3.1 创建模型3.2 视图界面3.3 控制器逻辑层 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架&#xff0c;用于使用 C# 和 XAML 创建本机移动和桌面应用。 使用 .NET MAUI&…...

vue3-sfc-loader 加载远程.vue文件(sfc)案例

注意事项 style标签如果增加了lang比如&#xff1a;lang“scss”&#xff0c;需要提供scss-loader的处理器&#xff0c;这个暂时没研究&#xff0c;我的处理方式是将动态模版的css放在了全局打包暂时还没有测试&#xff0c;后面测试了会同步更新 安装vue3-sfc-loader npm inst…...

Hadoop美食推荐系统 爬虫1.8w+数据 协同过滤余弦函数推荐美食 Springboot Vue Element-UI前后端分离

Hadoop美食推荐系统 爬虫1.8w数据 协同过滤余弦函数推荐美食 Springboot Vue Element-UI前后端分离 【Hadoop项目】 1. data.csv上传到hadoop集群环境 2. data.csv数据清洗 3.MapReducer数据汇总处理, 将Reducer的结果数据保存到本地Mysql数据库中 4. SpringbootEchartsMySQL 显…...

使用Linux驱动程序的fasync(文件异步通知机制)向用户空间发送SIGIO信号的学习记录

前言 本文学习使用Linux驱动程序的fasync(文件异步通知机制)向用户空间发送SIGIO信号。 fasync(文件异步通知机制)名字的来历 fasync 是 “file asynchronous” 的缩写&#xff0c;意思是 文件异步通知。 这里的文件是指文件结构体struct file *file &#xff0c;关于文件结…...

面试经验分享-回忆版某小公司

说说你项目中数据仓库是怎么分层的&#xff0c;为什么要分层&#xff1f; 首先是ODS层&#xff0c;连接数据源和数据仓库&#xff0c;数据会进行简单的ETL操作&#xff0c;数据来源通常是业务数据库&#xff0c;用户日志文件或者来自消息队列的数据等 中间是核心的数据仓库层&a…...

【算法学习笔记】35:扩展欧几里得算法求解线性同余方程

线性同余方程问题 线程同余方程问题是指 a x ≡ b ( m o d m ) ax \equiv b~(mod~m) ax≡b (mod m)&#xff0c;给定 a a a、 b b b和 m m m&#xff0c;找到一个整数 x x x使得该方程成立&#xff0c;即使得 a x m o d m b ax~mod~mb ax mod mb&#xff0c;随便返回任何一个…...

ent.SetDatabaseDefaults()

在 AutoCAD 的 .NET API 中&#xff0c;ent.SetDatabaseDefaults() 这句代码通常用于将一个实体&#xff08;Entity&#xff09;对象的属性设置为与其所在的数据库&#xff08;Database&#xff09;的默认设置相匹配。这意味着&#xff0c;该实体将采用数据库级别的默认颜色、图…...

使用docker部署tomcat服务器和mysql数据库

使用docker部署tomcat服务器 1、拉去tomcat镜像 [rootlocalhost yum.repos.d]# sudo docker pull docker.io/tomcat:9 9: Pulling from library/tomcat de44b265507a: Pull complete 4c2afd91a87d: Pull complete 89e9bbcfa697: Pull complete 11be3e613582: Pull complet…...