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

基于java实现规则引擎设计思路

背景

去年底换了公司,目前在做HR招聘系统,产品要求:管理端手动配置发布招聘要求(支持多个招聘条件AND与OR关系编排);当C端用户报名该职位时,系统执行该规则,返回报名成功或失败。根据技术调研,采用db存规则json串。然后报名时,执行该规则的方法。

前端样式

在这里插入图片描述
招聘岗位的多个规则关系是OR关系;同1个条件点击+号,可增加多个规则,是AND条件

代码入口

在这里插入图片描述
比如上述单元测试的场景:招java开发岗,要求:满足本科+35岁以下或本科+P7以上即可。
执行单测:
通过日志就能清晰的分析出,岗位配了什么规则,各规则的执行结果是什么
在这里插入图片描述

代码设计

类图

通过工厂+策略的设计模式,实现该规则,符合开闭原则,方便后续业务规则扩充,代码扩展
在这里插入图片描述

代码介绍

核心接口:InternalPositionRule 定义了规则执行的统一方法。
抽象类:AbstractPositionRule 提供了通用的比较和告警逻辑。
具体规则类:如 AgeRule、SexRule 等,继承自 AbstractPositionRule。
规则包装类:RuleWrapper 用于封装规则信息并动态创建规则实例。
规则组和规则集:RuleGroup 和 RuleSet 用于组织规则的逻辑关系(AND 和 OR)。
规则上下文:PositionRuleContext 是规则引擎的统一入口。
规则工厂:PositionRuleFactory 用于动态创建规则实例。
员工类:Employee 包含员工的基本信息,用于规则匹配。

核心代码

以下是脱敏后的核心代码
InternalPositionRule 岗位规则 接口 最顶层抽象,制定模版方法

* +-----------------------------------+* |  InternalPositionRule (接口)       |* |-----------------------------------|* |  + execute(Employee emp): boolean |* +-----------------------------------+*                 ^*                 |*                 |* +-----------------------------------+* |  AbstractPositionRule<T> (抽象类)  |* |-----------------------------------|* |  + compare(String, T, T): boolean |* |-----------------------------------|* |  - ruleValue: String              |* |  - forceFlag: String              |* |  - compareSymbol: String          |* +-----------------------------------+*                 ^*                 |*                 |* +-----------------------------------+* |  AgeRule                           |* |-----------------------------------|* |  + execute(Employee emp): boolean |* +-----------------------------------+**/
public interface InternalPositionRule {/*** 执行岗位条件规则** @param emp 员工信息* @return true/false*/boolean execute(Employee emp);

AbstractPositionRule 岗位规则 抽象类:业务上再扩展规则,继承该类即可

@Slf4j
@Component
public abstract class AbstractPositionRule<T extends Comparable<? super T>> implements InternalPositionRule {/*** 执行岗位条件规则** @param emp 员工信息* @return*/public abstract boolean execute(Employee emp);/*** 比较方法** @param compareSymbol  比较符号* @param actualValue    实际值* @param thresholdValue 设定阈值* @return*/public boolean compare(String compareSymbol, T actualValue, T thresholdValue) {boolean result;log.info("===比较开始,比较符号【{}】,配置阈值【{}】,实际值【{}】===", compareSymbol, thresholdValue, actualValue);//等于if (SymbolConstant.EQ.equalsIgnoreCase(compareSymbol)) {result = CompareUtil.equals(actualValue, thresholdValue);//大于} else if (SymbolConstant.GT.equalsIgnoreCase(compareSymbol)) {result = CompareUtil.gt(actualValue, thresholdValue);//小于} else if (SymbolConstant.LT.equalsIgnoreCase(compareSymbol)) {result = CompareUtil.lt(actualValue, thresholdValue);//大于等于} else if (SymbolConstant.GE.equalsIgnoreCase(compareSymbol)) {result = CompareUtil.ge(actualValue, thresholdValue);//小于等于} else if (SymbolConstant.LE.equalsIgnoreCase(compareSymbol)) {result = CompareUtil.le(actualValue, thresholdValue);} else {log.error(StrUtil.join("当前类型:", compareSymbol, InternalErrorCode.TYPE_UNSUPPORTED_ERROR.getMsg()));throw new ServiceException(InternalErrorCode.TYPE_UNSUPPORTED_ERROR);}log.info("==比较结束,结果【{}】===", result);return result;}/*** TODO 产品给出告警文案?怎么触达用户?是否持久化落库?* 告警逻辑:要求如果规则配置了告警,即使匹配失败,也允许通过,并返回告警文案** @param compareResult 实际匹配结果* @param forceFlag     禁止或告警* @param ruleTypeEnum  规则类型* @return*/public Optional<String> warn(Boolean compareResult, String forceFlag, RuleTypeEnum ruleTypeEnum) {if (BooleanUtil.isFalse(compareResult) && ForceTypeEnum.WARN.getType().equals(forceFlag)) {StringBuilder warnMsg = new StringBuilder().append("【").append(ruleTypeEnum.getName()).append("】").append("规则不符合;");log.warn("告警文案:::【{}】", warnMsg);return Optional.of(warnMsg.toString());}return Optional.empty();}
}

PositionRuleContext 内部招聘-职位规则上下文,执行规则统一入口

@Slf4j
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class PositionRuleContext {/*** 规则集*/private RuleSet ruleSet;/*** 执行规则(执行规则的统一入口)** @param emp* @return*/public boolean executeRule(Employee emp) {if (Objects.isNull(ruleSet)) {log.info("规则集是空,不走规则引擎");return true;}return ruleSet.execute(emp);}
}

RuleSet 规则集,须知:1个招聘职位对应1个规则集,db存json结构,
1个规则集里含n个规则组,规则组之间是OR关系,每个规则组内含n个规则条件,各个规则条件是AND关系

@Slf4j
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RuleSet {/*** 规则组*/private List<RuleGroup> ruleGroup;public boolean execute(Employee emp) {return ruleGroup.stream().anyMatch(condition -> condition.execute(emp));}
}

RuleGroup 规则组

@Slf4j
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RuleSet {/*** 规则组*/private List<RuleGroup> ruleGroup;public boolean execute(Employee emp) {return ruleGroup.stream().anyMatch(condition -> condition.execute(emp));}
}

RuleWrapper 规则Wrapper类 用于封装规则的配置信息

@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class RuleWrapper extends AbstractPositionRule {/*** 规则类型** @see com.suning.ebrs.module.internal.enums.RuleTypeEnum*/private String ruleType;/*** 比较符号*/private String compareSymbol;//强制条件(1是,0不是)private String forceFlag;/*** 规则值*/private String ruleValue;@Overridepublic boolean execute(Employee emp) {AbstractPositionRule rule = PositionRuleFactory.getRule(ruleType, ruleValue, compareSymbol, forceFlag);return rule.execute(emp);}}

AgeRule 年龄规则

@Slf4j
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class AgeRule extends AbstractPositionRule<Integer> {/*** 规则值(设置阈值)*/private String ruleValue;/*** 强制条件(1是,0不是)* 不强制,也能过通过规则,并有告警提示;* 强制,返回实际通过结果*/private String forceFlag;/*** 比较符号** @see com.suning.ebrs.module.internal.constant.SymbolConstant*/private String compareSymbol;@Overridepublic boolean execute(Employee emp) {log.info("===【{}】开始===", this.getClass().getSimpleName());Integer thresholdValue = Integer.valueOf(ruleValue);//TODO 查SAP,根据员工id查员工实际年龄Integer actualValue = emp.getAge();boolean compareResult = compare(compareSymbol, actualValue, thresholdValue);Optional<String> opt = warn(compareResult, forceFlag, RuleTypeEnum.AGE_RULE);if (opt.isPresent()) {emp.setWarnMsg(StringUtils.isNotBlank(emp.getWarnMsg()) ? emp.getWarnMsg() + opt.get() : opt.get());compareResult = true;}log.info("===【{}】结束,结果【{}】===", this.getClass().getSimpleName(), compareResult);return compareResult;}
}

PostLevelRule 级别规则

@Slf4j
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class PostLevelRule extends AbstractPositionRule<Integer> {//属性值(设置阈值)private String ruleValue;//强制条件(1是,0不是)private String forceFlag;//比较符号(支持:等于,大于,小于,大于等于,小于等于)private String compareSymbol;@Overridepublic boolean execute(Employee emp) {log.info("===【{}】开始===", this.getClass().getSimpleName());Integer thresholdValue = Integer.valueOf(ruleValue);//TODO 根据员工id查员工实际级别Integer actualValue = emp.getLevel();boolean compareResult = compare(compareSymbol, actualValue, thresholdValue);Optional<String> opt = warn(compareResult, forceFlag, RuleTypeEnum.AGE_RULE);if (opt.isPresent()) {emp.setWarnMsg(StringUtils.isNotBlank(emp.getWarnMsg()) ? emp.getWarnMsg() + opt.get() : opt.get());compareResult = true;}log.info("===【{}】结束,结果【{}】===", this.getClass().getSimpleName(), compareResult);return compareResult;}
}

Employee 员工类

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Employee {private String name; //张三private Integer level; //6,7,8private Integer sex; //1男,0女private Integer age; //36private Integer edu; //4本科 5研究生 6博士private Integer topSchool; //重点高校:1是;0不是private Integer political; //政治面貌 3群众,4预备党员,5党员private List<String> certificates; //系统架构师证书,高级软考证书//执行规则后的告警信息private String warnMsg;}

PositionRuleContext 职位规则上下文,执行规则统一入口

@Slf4j
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class PositionRuleContext {/*** 规则集*/private RuleSet ruleSet;/*** 执行规则(执行规则的统一入口)** @param emp* @return*/public boolean executeRule(Employee emp) {if (Objects.isNull(ruleSet)) {log.info("规则集是空,不走规则引擎");return true;}return ruleSet.execute(emp);}
}

PositionRuleFactory 职位规则工厂

@Slf4j
@Component
public class PositionRuleFactory {private static final ConcurrentHashMap<String, AbstractPositionRule> ruleCache = new ConcurrentHashMap<>(16, 1);/*** 获取规则** @param ruleType* @param ruleValue* @param compareSymbol* @param forceFlag* @return*/public static AbstractPositionRule getRule(String ruleType, String ruleValue, String compareSymbol, String forceFlag) {String key = ruleType + "_" + ruleValue + "_" + compareSymbol + "_" + forceFlag;return ruleCache.computeIfAbsent(key, k -> createRule(ruleType, ruleValue, compareSymbol, forceFlag));}/*** 创建规则** @param ruleType* @param ruleValue* @param compareSymbol* @param forceFlag* @return*/public static AbstractPositionRule createRule(String ruleType, String ruleValue, String compareSymbol, String forceFlag) {AbstractPositionRule rule;//年龄规则if (RuleTypeEnum.AGE_RULE.getType().equalsIgnoreCase(ruleType)) {rule = AgeRule.builder().ruleValue(ruleValue).forceFlag(forceFlag).compareSymbol(compareSymbol).build();//出生日期} else if (RuleTypeEnum.DATE_OF_BIRTH_RULE.getType().equalsIgnoreCase(ruleType)) {rule = DateOfBirthRule.builder().ruleValue(ruleValue).forceFlag(forceFlag).compareSymbol(compareSymbol).build();//参加工作日期} else if (RuleTypeEnum.DATE_OF_EMPLOYMENT_RULE.getType().equalsIgnoreCase(ruleType)) {rule = EmployeeSubgroupRule.builder().ruleValue(ruleValue).forceFlag(forceFlag).compareSymbol(compareSymbol).build();//学历形式(在职/全日制)} else if (RuleTypeEnum.EDU_BACKGROUND_FORM_RULE.getType().equalsIgnoreCase(ruleType)) {rule = EduBackgroundFormRule.builder().ruleValue(ruleValue).forceFlag(forceFlag).compareSymbol(compareSymbol).build();//性别规则} else if (RuleTypeEnum.SEX_RULE.getType().equalsIgnoreCase(ruleType)) {rule = SexRule.builder().ruleValue(ruleValue).forceFlag(forceFlag).compareSymbol(compareSymbol).build();} else {log.error("【{}】参数非法!", ruleType);throw new ServiceException(InternalErrorCode.PARAM_ERROR);}return rule;}
}

InternalRuleServiceImplTest 规则的单元测试类

@Slf4j
@SpringBootTest
@ActiveProfiles("local")
public class InternalRuleServiceImplTest {@Resourceprivate InternalPositionRuleService ruleService;@Testpublic void matchTest() {//岗位要求符合:本科+35岁以下 或 本科+P7以上//规则组1: 本科+35岁以下RuleGroup ruleGroup1 = this.mockRuleGroup1();//规则组2:本科+P7以上RuleGroup ruleGroup2 = this.mockRuleGroup2();List<RuleGroup> ruleGroups = Arrays.asList(ruleGroup1, ruleGroup2);RuleSet ruleSet = new RuleSet();ruleSet.setRuleGroup(ruleGroups);Employee emp = getEmployeeByEmpCode("123456");System.err.println("规则匹配,单测,入参 规则信息=====>" + JSON.toJSONString(ruleSet));System.err.println("规则匹配,单测,入参 员工信息=====>" + JSON.toJSONString(emp));boolean result = PositionRuleContext.builder().ruleSet(ruleSet).build().executeRule(emp);System.err.println("规则匹配,单测,匹配结果=====>" + result);System.err.println("规则匹配,单测,告警提示=====>" + emp.getWarnMsg());}private RuleGroup mockRuleGroup1() {RuleGroup ruleGroup = new RuleGroup();List<RuleWrapper> wrappers = new ArrayList<>();RuleWrapper wrapper1 = new RuleWrapper();wrapper1.setForceFlag("0");wrapper1.setRuleValue("35");wrapper1.setRuleType(RuleTypeEnum.AGE_RULE.getType());wrapper1.setCompareSymbol(SymbolConstant.LE);wrappers.add(wrapper1);RuleWrapper wrapper2 = new RuleWrapper();wrapper2.setForceFlag("1");wrapper2.setRuleValue("本科");wrapper2.setRuleType(RuleTypeEnum.EDU_BACKGROUND_RULE.getType());wrapper2.setCompareSymbol(SymbolConstant.GE);wrappers.add(wrapper2);ruleGroup.setRules(wrappers);return ruleGroup;}private RuleGroup mockRuleGroup2() {RuleGroup ruleGroup = new RuleGroup();List<RuleWrapper> wrappers = new ArrayList<>();RuleWrapper wrapper1 = new RuleWrapper();wrapper1.setForceFlag("1");wrapper1.setRuleValue("本科");wrapper1.setRuleType(RuleTypeEnum.EDU_BACKGROUND_RULE.getType());wrapper1.setCompareSymbol(SymbolConstant.GE);wrappers.add(wrapper1);RuleWrapper wrapper2 = new RuleWrapper();wrapper2.setForceFlag("1");wrapper2.setRuleValue("7");wrapper2.setRuleType(RuleTypeEnum.POST_LEVEL_RULE.getType());wrapper2.setCompareSymbol(SymbolConstant.GE);wrappers.add(wrapper2);ruleGroup.setRules(wrappers);return ruleGroup;}/*** mock员工数据** @param employeeCode* @return*/private Employee getEmployeeByEmpCode(String employeeCode) {List<String> list = Arrays.asList("系统架构师证书");return Employee.builder().name("张三")//党员.political(5)//不是重点院校.topSchool(0)//本科.edu(5)//40岁.age(39)//男.sex(1)//系统架构师证书.certificates(list)//岗位6级.level(8).build();}}

相关文章:

基于java实现规则引擎设计思路

背景 去年底换了公司&#xff0c;目前在做HR招聘系统&#xff0c;产品要求:管理端手动配置发布招聘要求(支持多个招聘条件AND与OR关系编排)&#xff1b;当C端用户报名该职位时&#xff0c;系统执行该规则&#xff0c;返回报名成功或失败。根据技术调研&#xff0c;采用db存规则…...

TCP协议:互联网数据传输的守护者

在互联网的浩瀚海洋中&#xff0c;数据如同涓涓细流&#xff0c;无时无刻不在流动。而这些数据的稳定、可靠传输&#xff0c;离不开一个重要的协议——TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;。TCP协议作为互联网协议族中的核心成员…...

2025美国大学生数学建模竞赛(美赛)B题完整思路分析论文(35页)(含模型、可运行代码和运行结果)

2025美国大学生数学建模竞赛B题完整思路分析论文 目录 摘要 一、问题重述 二、问题分析 三、模型假设 四、模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1样例代码&#xff08;仅供参考&#xff09; 4.1.4问题1样例代码运行结…...

InceptionV1_V2

目录 不同大小的感受野去提取特征 经典 Inception 网络的设计思路与运行流程 背景任务&#xff1a;图像分类&#xff08;以 CIFAR-10 数据集为例&#xff09; Inception 网络的设计思路 Inception 网络的运行流程 打个比方 多个损失函数的理解 1. 为什么需要多个损失函数&#…...

面向对象设计原则

面向对象最大的优势是抵御变化 理解隔离变化&#xff1a; 从宏观面来看&#xff0c;面向对象构建方式更能适应软件的变化&#xff0c;能将变化所带来的影响减为最少。 各司其职&#xff1a;从微观层面来看&#xff0c;面向对象的方式更强调各个类的责任。由于需求变化导致的新…...

近年流行的开发技术

Web 开发领域 前端技术 HTML5、CSS3 和 JavaScript HTML5&#xff1a;作为网页结构的基础&#xff0c;引入了新的语义化标签&#xff08;如<header>、<nav>、<article>等&#xff09;&#xff0c;增强了网页的可读性和搜索引擎优化效果&#xff0c;同时支持…...

Go语言中的Select

Select 在 Go 语言中&#xff0c;select 是一种用于处理多个通道操作的控制结构。它允许你同时监听多个通道上的通信操作&#xff08;发送或接收&#xff09;&#xff0c;并根据哪个操作先完成来执行相应的代码块。select 是 Go 并发编程中的一个重要工具&#xff0c;常用于实…...

SQL调优讨论

说明&#xff1a;狭义的SQL调优&#xff0c;指对慢SQL&#xff08;一般是Select语句&#xff0c;或包含Select的语句&#xff09;优化&#xff0c;在不改变查询结果的情况下提高SQL执行效率。广义上的SQL调优&#xff0c;指对某个慢查询优化&#xff0c;通过一些类操作提高查询…...

【STM32】-TTP223B触摸开关

前言 本文章旨在记录博主STM32的学习经验&#xff0c;我自身也在不断的学习当中&#xff0c;如果文章有写的不对的地方&#xff0c;欢迎各位大佬批评指正。 准备工作 今天这篇文章介绍的是触摸开关这一外围硬件。 ST-link调试器STM32最小系统板单路TTP223B触摸传感器模块LE…...

华为数据之道-读书笔记

内容简介 关键字 数字化生产 已经成为普遍的商业模式&#xff0c;其本质是以数据为处理对象&#xff0c;以ICT平台为生产工具&#xff0c;以软件为载体&#xff0c;以服务为目的的生产过程。 信息与通信技术平台&#xff08;Information and Communication Technology Platf…...

Zookeeper(28)Zookeeper的线性化写入和顺序一致性读是什么?

Zookeeper 是一个分布式协调服务&#xff0c;它在设计上提供了强一致性的保证&#xff0c;其中包括线性化写入和顺序一致性读。这两种一致性模型确保了在分布式系统中数据的一致性和操作的确定性。 线性化写入&#xff08;Linearizable Writes&#xff09; 线性化写入保证在任…...

Ubuntu安装GitLab

在 Ubuntu 上安装 GitLab 的步骤如下。这里以 GitLab Community Edition&#xff08;CE&#xff09;为例&#xff1a; 前提条件 确保你的 Ubuntu 系统是 20.04 或更高版本。确保你的系统满足 GitLab 的硬件要求。 步骤 更新系统包&#xff1a; sudo apt update sudo apt upg…...

Stable Diffusion 3.5 介绍

Stable Diffusion 3.5 是由 Stability AI 推出的最新一代图像生成模型&#xff0c;是 Stable Diffusion 系列的重要升级版本。以下是关于 Stable Diffusion 3.5 的详细信息&#xff1a; 版本概述 Stable Diffusion 3.5 包含三个主要版本&#xff1a; Stable Diffusion 3.5 L…...

力扣hot100-->滑动窗口、贪心

你好呀&#xff0c;欢迎来到 Dong雨 的技术小栈 &#x1f331; 在这里&#xff0c;我们一同探索代码的奥秘&#xff0c;感受技术的魅力 ✨。 &#x1f449; 我的小世界&#xff1a;Dong雨 &#x1f4cc; 分享我的学习旅程 &#x1f6e0;️ 提供贴心的实用工具 &#x1f4a1; 记…...

### 2.5.3 二叉树的基本操作

2.5.3 二叉树的基本操作 // 获取树中节点的个数 int size(Node root);// 获取叶子节点的个数 int getLeafNodeCount(Node root);// 子问题思路-求叶子结点个数// 获取第K层节点的个数 int getKLevelNodeCount(Node root,int k);// 获取二叉树的高度 int getHeight(Node root);…...

GAEA 社区:从用户到共同创造者

GAEA 模型最引人注目的方面之一是&#xff0c;它将用户视为共同创造者&#xff0c;而不仅仅是被动的消费者。在许多中心化平台中&#xff0c;用户就是用户。但在 GAEA 的生态系统中&#xff0c;每个人都在推动进步。无论您是贡献计算能力、分享有价值的数据还是帮助改进模型&am…...

记录一个连不上docker中的mysql的问题

引言 使用的debian12,不同发行版可能有些许差异&#xff0c;连接使用的工具是navicat lite 本来是毫无思绪的&#xff0c;以前在云服务器上可能是防火墙的问题&#xff0c;但是这个桌面环境我压根没有使用防火墙。 直到 ying192:~$ mysql -h127.0.0.1 -uroot ERROR 1045 (28…...

doris:MySQL Load

Doris 兼容 MySQL 协议&#xff0c;可以使用 MySQL 标准的 LOAD DATA 语法导入本地文件。MySQL Load 是一种同步导入方式&#xff0c;执行导入后即返回导入结果。可以通过 LOAD DATA 语句的返回结果判断导入是否成功。一般来说&#xff0c;可以使用 MySQL Load 导入 10GB 以下的…...

使用vitepress搭建自己的博客项目

一、介绍can-vitepress-blog 什么是CAN BLOG CAN BLOG是基于vitepress二开的个人博客系统&#xff0c;他能够方便使用者快速构建自己的博客文章&#xff0c;无需繁琐的配置和复杂的代码编写。 CAN BLOG以antdv为UI设计基础&#xff0c;简洁大方&#xff0c;界面友好&#xf…...

Yii框架中的扩展:如何使用外部库

在Yii框架中&#xff0c;扩展功能的一种常见且有效的方式是使用外部库。这些外部库可以帮助开发者实现特定的功能&#xff0c;如调用第三方API、处理图片、生成PDF文件或发送邮件等。以下是使用外部库扩展Yii框架的详细步骤&#xff1a; 一、安装外部库 使用Composer&#xff…...

【Elasticsearch】inference ingest pipeline

Elasticsearch 的 Ingest Pipeline 功能允许你在数据索引之前对其进行预处理。通过使用 Ingest Pipeline&#xff0c;你可以执行各种数据转换和富化操作&#xff0c;包括使用机器学习模型进行推理&#xff08;inference&#xff09;。这在处理词嵌入、情感分析、图像识别等场景…...

Linux的基本指令(上)

1.ls指令 语法&#xff1a;ls [选项] [目录或文件] 功能&#xff1a;对于⽬录&#xff0c;该命令列出该⽬录下的所有⼦⽬录与⽂件。对于⽂件&#xff0c;将列出⽂件名以及其他信息。 常用选项&#xff1a; -a 列出⽬录下的所有⽂件&#xff0c;包括以 . 开头的隐含⽂件。 -d 将…...

【贪心算法】洛谷P1106 - 删数问题

2025 - 01 - 22 - 第 46 篇 【洛谷】贪心算法题单 - 【贪心算法】 - 【学习笔记】 作者(Author): 郑龙浩 / 仟濹(CSND账号名) 目录 文章目录 目录P1106 删数问题题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路代码 P1106 删数问题 题目描述 键盘输入一个高…...

【人工智能】Python中的知识图谱构建与应用

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着人工智能技术的不断发展,知识图谱已成为信息检索、推荐系统、自然语言处理等领域的重要技术之一。本文将详细介绍如何使用Python构建知…...

Spring WebSocket 与 STOMP 协议结合实现私聊私信功能

目录 后端pom.xmlConfig配置类Controller类DTO 前端安装相关依赖websocketService.js接口javascripthtmlCSS 效果展示简单测试连接&#xff1a; 报错解决方法1、vue3 使用SockJS报错 ReferenceError: global is not defined 功能补充拓展1. 安全性和身份验证2. 异常处理3. 消息…...

【Matlab高端绘图SCI绘图模板】第05期 绘制高阶折线图

1.折线图简介 折线图是一个由点和线组成的统计图表&#xff0c;常用来表示数值随连续时间间隔或有序类别的变化。在折线图中&#xff0c;x 轴通常用作连续时间间隔或有序类别&#xff08;比如阶段1&#xff0c;阶段2&#xff0c;阶段3&#xff09;。y 轴用于量化的数据&#x…...

java后端之事务管理

Transactional注解&#xff1a;作用于业务层的方法、类、接口上&#xff0c;将当前方法交给spring进行事务管理&#xff0c;执行前开启事务&#xff0c;成功执行则提交事务&#xff0c;执行异常回滚事务 spring事务管理日志&#xff1a; 默认情况下&#xff0c;只有出现Runti…...

常见的多媒体框架(FFmpeg GStreamer DirectShow AVFoundation OpenMax)

1.FFmpeg FFmpeg是一个非常强大的开源多媒体处理框架&#xff0c;它提供了一系列用于处理音频、视频和多媒体流的工具和库。它也是最流行且应用最广泛的框架&#xff01; 官方网址&#xff1a;https://ffmpeg.org/ FFmpeg 的主要特点和功能&#xff1a; 编解码器支持: FFmpe…...

如何移植ftp服务器到arm板子?

很多厂家提供的sdk&#xff0c;一般都不自带ftp服务器功能&#xff0c; 需要要发人员自己移植ftp服务器程序。 本文手把手教大家如何移植ftp server到arm板子。 环境 sdk&#xff1a;复旦微 Buildroot 2018.02.31. 解压 $ mkdir ~/vsftpd $ cp vsftpd-3.0.2.tar.gz ~/vs…...

牛批,吾爱出品

可能是因为从事IT的原因&#xff0c;我身边的大多数朋友也是从事相关工作的&#xff0c;而IT工作往往需要长时间对着电脑。这样就很容易眼睛疲劳。今天给大家推荐几款&#xff0c;希望有对有需要的小伙伴有所帮助&#xff0c;大家可以收藏以来哦。 CareUEyes CareUEyes是一款绿…...

基于 Android 的日程管理系统的设计与实现

标题:基于 Android 的日程管理系统的设计与实现 内容:1.摘要 基于 Android 的日程管理系统旨在帮助用户更高效地管理个人日程安排。该系统采用了 Android 平台的优势&#xff0c;结合了简洁的界面设计和强大的功能&#xff0c;为用户提供了便捷的日程管理体验。 在设计与实现过…...

Kubectl 与 Helm 详解

在 Kubernetes 生态中,kubectl 和 Helm 是两个核心工具,分别用于直接管理 Kubernetes 资源和简化应用的部署与管理。本文将深入探讨 kubectl 和 Helm 的功能、使用场景、部署与更新方式,并对比它们的优缺点。 1. Kubectl 详解 1.1 什么是 Kubectl? kubectl 是 Kubernetes…...

centos搭建docker registry镜像仓库

centos搭建docker registry镜像仓库 简介 Docker Registry是一个存储和分发Docker镜像的服务。它允许用户上传、下载和管理 Docker 镜像&#xff0c;为容器化应用的部署提供了便利。 拉取镜像 docker image pull registry证书配置 创建镜像仓库的镜像数据目录和证书目录&…...

Pyecharts之饼图与多饼图的应用

在数据可视化领域&#xff0c;饼图是一种常用的图表类型&#xff0c;特别适合展示数据的比例关系。Pyecharts 为我们提供了强大的饼图绘制功能&#xff0c;不仅可以轻松绘制各种饼图&#xff0c;还能对饼图的样式和数据标签进行深度定制&#xff0c;并且可以组合多个饼图以满足…...

51单片机入门_01_单片机(MCU)概述(使用STC89C52芯片;使用到的硬件及课程安排)

文章目录 1. 什么是单片机1.1 微型计算机的组成1.2 微型计算机的应用形态1.3 单板微型计算机1.4 单片机(MCU)1.4.1 单片机内部结构1.4.2 单片机应用系统的组成 1.5 80C51单片机系列1.5.1 STC公司的51单片机1.5.1 STC公司单片机的命名规则 2. 单片机的特点及应用领域2.1 单片机的…...

蓝桥杯LQ1044 求完数

题目描述 因子&#xff1a;因子也叫因数&#xff0c;例如3515&#xff0c;那么3和5是15的因子。 同时15115&#xff0c;那么1和15也是15的因子。 1&#xff0c;3&#xff0c;5&#xff0c;15 这四个因子是15的所有因子。 完数&#xff1a;如果一个数等于不含它本身的其他因子之…...

Django 日志配置实战指南

日志是 Django 项目中不可或缺的一部分,它帮助我们记录应用程序的运行状态、调试信息、错误信息等。通过合理配置日志,我们可以更好地监控和调试应用程序。本文将详细介绍如何在 Django 项目中实现日志文件分割、日志级别控制以及多环境日志配置,并结合最佳实践和代码示例,…...

[笔记] 极狐GitLab实例 : 手动备份步骤总结

官方备份文档 : 备份和恢复极狐GitLab 一. 要求 为了能够进行备份和恢复&#xff0c;请确保您系统已安装 Rsync。 如果您安装了极狐GitLab&#xff1a; 如果您使用 Omnibus 软件包&#xff0c;则无需额外操作。如果您使用源代码安装&#xff0c;您需要确定是否安装了 rsync。…...

php代码审计2 piwigo CMS in_array()函数漏洞

php代码审计2 piwigo CMS in_array()函数漏洞 一、目的 本次学习目的是了解in_array()函数和对项目piwigo中关于in_array()函数存在漏洞的一个审计并利用漏洞获得管理员帐号。 二、in_array函数学习 in_array() 函数搜索数组中是否存在指定的值。 in_array($search,$array…...

随机矩阵投影长度保持引理及其证明

原论文中的引理 2 \textbf{2} 2 1. \textbf{1. } 1. 引理 1 \textbf{1} 1(前提之一) 1.1. \textbf{1.1. } 1.1. 引理 1 \textbf{1} 1的内容 &#x1f449;前提&#xff1a; X ∼ N ( 0 , σ ) X\sim{}N(0,\sigma) X∼N(0,σ)即 f ( x ) 1 2 π σ e – x 2 2 σ 2 f(x)\text{}…...

蓝桥杯真题 - 三国游戏 - 题解

题目链接&#xff1a;https://www.lanqiao.cn/problems/3518/learning/ 个人评价&#xff1a;难度 2 星&#xff08;满星&#xff1a;5&#xff09; 前置知识&#xff1a;贪心 整体思路 先假设魏蜀吴中的某一个势力最终获胜的情况下&#xff0c;如何求出事件发生的最大数量&a…...

Spring 源码学习(七)——注解后处理器-2

五 InitDestroyAnnotationBeanPostProcessor 类 1 属性 InitDestroyAnnotationBeanPostProcessor 类用于处理初始化与销毁注解&#xff1b;其中第一个属性为用于标识初始化方法与销毁方法注解类型的 initAnnotationType 与 destroyAnnotationType 属性、还有一个用于标识执行顺…...

即梦(Dreamina)技术浅析(一)

1.技术架构与核心组件 2.生成模型的具体实现 3.多模态融合技术 4.训练数据与模型优化 5.用户交互与创作流程 6.技术挑战与解决方案 7.未来发展方向 1. 技术架构与核心组件 即梦的技术架构可以分为以下几个核心组件: 1.1 前端用户界面(UI) 功能模块: 文字输入框:用…...

Spring MVC(二)

介绍 Cookie 与 Session Session 类似哈希表&#xff0c;存储了一些键值对结构&#xff0c;Key 就是 SessionID&#xff0c;Vaule 就是用户信息&#xff0c;客户端发起会话的时候&#xff0c;服务器一旦接收&#xff0c;就会创建会话【也就是 Session】&#xff0c;通过 Sessi…...

java求职学习day15

多线程 1 基本概念 1.1 程序和进程的概念 &#xff08;1&#xff09;程序 - 数据结构 算法&#xff0c;主要指存放在硬盘上的可执行文件。 &#xff08;2&#xff09;进程 - 主要指运行在内存中的可执行文件。 &#xff08;3&#xff09;目前主流的操作系统都支持多进程&a…...

Typesrcipt泛型约束详细解读

代码示例&#xff1a; // 如果我们直接对一个泛型参数取 length 属性, 会报错, 因为这个泛型根本就不知道它有这个属性 (() > {// 定义一个接口,用来约束将来的某个类型中必须要有length这个属性interface ILength{// 接口中有一个属性lengthlength:number}function getLen…...

[操作系统] 进程地址空间管理

虚拟地址空间的初始化 缺页中断 缺页中断的概念 缺页中断&#xff08;Page Fault Interrupt&#xff09; 是指当程序访问的虚拟地址在页表中不存在有效映射&#xff08;即该页未加载到内存中&#xff09;时&#xff0c;CPU 会发出一个中断信号&#xff0c;请求操作系统加载所…...

【fly-iot飞凡物联】(20):2025年总体规划,把物联网整套技术方案和实现并落地,完成项目开发和课程录制。

前言 fly-iot飞凡物联专栏&#xff1a; https://blog.csdn.net/freewebsys/category_12219758.html 1&#xff0c;开源项目地址进行项目开发 https://gitee.com/fly-iot/fly-iot-platform 完成项目开发&#xff0c;接口开发。 把相关内容总结成文档&#xff0c;并录制课程。…...

14-6-1C++STL的list

(一&#xff09;list容器的基本概念 list容器简介&#xff1a; 1.list是一个双向链表容器&#xff0c;可高效地进行插入删除元素 2.list不可以随机存取元素&#xff0c;所以不支持at.(pos)函数与[ ]操作符 &#xff08;二&#xff09;list容器头部和尾部的操作 list对象的默…...

vue2和vue3指令

Vue 2 和 Vue 3 的指令系统非常相似&#xff0c;但 Vue 3 在指令方面进行了优化和扩展。以下是 Vue 2 和 Vue 3 中指令的对比&#xff1a; 1. 通用指令 这些指令在 Vue 2 和 Vue 3 中都可以使用&#xff0c;功能一致&#xff1a; 指令说明v-bind绑定 HTML 属性或组件 propsv-…...