【Spring Boot】过滤敏感词的两种实现
文章目录
- 项目场景
- 前置知识
- 前缀树
- 实现方式
- 解决方案一:读取敏感词文件生成前缀树+构建敏感词过滤器
- 1. 导入敏感词文件 `src/main/resources/sensitive_words.txt`
- 2. 构建敏感词过滤器 `SensitiveFilter`
- 3. 测试与使用
- 解决方案二:使用第三方插件 `houbb/sensitive-word`(推荐)
- 1. 添加依赖
- 2. 测试与使用(使用默认过滤策略)
- 3. 构建配置类`SensitiveWordConfig`(使用自定义过滤策略)
- 4. 测试与使用(使用自定义过滤策略)
- 两种实现方式的对比
项目场景
基于 Spring Boot 的论坛系统:用户发布的内容需进行敏感词过滤。
前置知识
前缀树
- Q:前缀树和普通N叉树的区别?
- A:前缀树(Trie,也称字典树、单词查找树或键树)。
- 设计目的:
- 前缀树:专门设计用于高效地存储和检索字符串集合中的键(字符串)。它的结构允许快速的查找、插入和删除操作,特别适合于字符串前缀匹配,如自动补全、拼写检查、敏感词过滤等场景。
- 普通N叉树:是一种更通用的树形数据结构,其中每个节点可以有任意数量(包括零)的子节点,最多可达N个。它没有特定于字符串处理的特性,广泛应用于各种需要多路分支的数据结构场景,如文件系统的目录结构、表达式树等。
- 节点结构:
- 前缀树:每个节点通常包含一个字符和一个映射到其子节点的字符到节点的映射(如HashMap或数组)。根节点通常不表示任何字符,而从根到任意叶节点的路径上的字符序列组成一个字符串,叶节点或标记为关键词结束的节点代表一个完整的字符串。
- 普通N叉树:节点可能包含数据以及指向其子节点的指针数组或列表,但这些子节点之间的关系不一定有特定的字符关联,节点的数据结构和含义更多样。
- 查找效率:
- 前缀树:由于其特殊的结构设计,前缀树支持高效的前缀匹配,可以在O(L)时间内(L为关键词长度)查找到所有具有相同前缀的字符串,或者确定某个字符串是否在集合中。
- 普通N叉树:查找效率依赖于树的具体形态和查找算法,一般情况下不如前缀树在字符串前缀匹配上的效率高。
- 空间利用率:
- 前缀树:可能会有较高的空间消耗,因为它存储了所有字符串的公共前缀,特别是当存储的字符串有很多相似前缀时。
- 普通N叉树:空间使用更加灵活,取决于树的形状,但通常不会为了存储前缀信息而额外消耗空间。
- 设计目的:
总之,前缀树是一种针对字符串处理优化的特殊N叉树,强调了字符串前缀的高效存储和查询,而普通N叉树则是一种更为通用的结构,适用于多种类型的多路分支数据组织。
实现方式
解决方案一:读取敏感词文件生成前缀树+构建敏感词过滤器
参考:雨下一整晚Real’s Blog - 【Java项目】社区论坛项目 - 敏感词过滤
前缀树
- 名称:Trie 、字典树、查找树
- 特点:查找效率高,消耗内存大
- 应用:字符串检索、词频统计、字符串排序等
敏感词过滤器
- 定义前缀树
- 根据敏感词,初始化前缀树
- 编写过滤敏感词的方法
1. 导入敏感词文件 src/main/resources/sensitive_words.txt
此处为示例文件内容。
元
购物车
fuck
abc
bf
be
2. 构建敏感词过滤器 SensitiveFilter
package com.example.filter;import com.example.constant.SensitiveConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;/*** 敏感词过滤器*/
@Slf4j
@Component
public class SensitiveFilter {// 创建前缀树的根节点private final TrieNode rootNode = new TrieNode();/*** 初始化,读取敏感词*/@PostConstruct // 确保在Bean初始化后执行public void init() {// 1. 从类路径加载敏感词文件: 使用文件存储敏感词库可以直接进行一次性读取和处理,无需依赖数据库系统,并且保证离线可用。try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(SensitiveConstant.SENSITIVE_WORDS_FILE);InputStreamReader inputStreamReader = new InputStreamReader(inputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);// Java 7及以后的版本中,引入了一项称为"try-with-resources"的新特性,它允许自动管理资源,确保在try语句块执行完毕后,不论是否发生异常,都会正确关闭或释放资源) {// 2. 逐行读取敏感词并加入到前缀树中String keyword;while ((keyword = bufferedReader.readLine()) != null) {this.addKeyWord(keyword);}} catch (IOException ex) {log.error("敏感词文件读取失败: " + ex.getMessage());}}/*** 将敏感词添加到前缀树中* @param keyword 待添加的敏感词*/private void addKeyWord(String keyword) {// 1. 初始化操作,将当前处理节点设为根节点TrieNode tempNode = rootNode;// 2. 将待添加的敏感词字符串转换为字符数组以便遍历char[] chars = keyword.toCharArray();// 3. 遍历字符数组,逐个字符构建前缀树for (int i = 0; i < chars.length; i++) {// 3.1. 从当前处理节点的子节点Map中获取当前字符对应的节点TrieNode childrenNode = tempNode.getChildrenNode(chars[i]);// 3.1.1 若当前字符没有对应的节点,则创建一个新节点,并放入当前处理节点的子节点Map中if (childrenNode == null) {childrenNode = new TrieNode();tempNode.setChildrenNode(chars[i], childrenNode);}// 3.2. 若当前字符为敏感词字符串的最后一个字符,则标记当前字符的对应节点为敏感词的结尾节点if (i == chars.length - 1) {childrenNode.setKeywordEnd(true);}// 3.3. 移动到下一层,使当前字符对应的节点成为新的当前处理节点,继续构建或遍历过程tempNode = childrenNode;}}/*** 过滤文本,移除或替换其中的敏感词,并返回处理后的文本* @param text 待过滤的文本* @return 过滤后的文本*/public String filter(String text) {// 1. 检查输入文本是否为空或仅包含空白字符,如果是,则直接返回null,表示无内容无需过滤if (StringUtils.isBlank(text)) {return null;}// 2. 初始化变量TrieNode tempNode = rootNode; // 2.1. 初始化为前缀树的根节点,用于遍历查找。int begin = 0, end = 0; // 2.2. 分别用于标记待检查文本区间的起始和结束位置StringBuilder result = new StringBuilder(); // 2.3. 累积过滤后的文本// 3. 遍历整个文本进行过滤处理while (begin < text.length()) {char c = text.charAt(end);// 3.1. 遇到符号字符if (isSymbol(c)) {// 3.1.1. 如果当前处于根节点,即没有匹配到任何敏感词的开始,直接保留符号,并移动beginif (tempNode == rootNode) {result.append(c);begin++;}// 3.1.2. 跳过当前符号,并继续检查下一个字符end++;continue;}// 3.2. 检查当前字符区间text[begin...end]是否是某个敏感词的一部分tempNode = tempNode.getChildrenNode(c);// 3.2.1. 如果当前字符没有对应的子节点,即text[begin...end]不是敏感词的组成部分if (tempNode == null) {result.append(text.charAt(begin)); // 3.2.1.1. 保存begin位置的字符到结果end = ++begin; // 3.2.1.2. 移动begin和end指针,准备检查下一个可能的敏感词 begin++; end = begin;tempNode = rootNode; // 3.2.1.3. 重置tempNode为根节点准备下一轮匹配}// 3.2.2. 如果当前字符路径已到达一个敏感词的结尾,即text[begin...end]是敏感词else if (tempNode.isKeywordEnd()) {result.append(StringUtils.repeat(SensitiveConstant.REPLACEMENT, end - begin + 1)); // 3.2.2.1. 替换敏感词区间begin = ++end; // 3.2.2.2. 移动begin和end指针,准备检查下一个可能的敏感词 end++; begin = end;tempNode = rootNode; // 3.2.2.3. 重置tempNode为根节点准备下一轮匹配}// 3.2.3. 如果当前字符区间text[begin...end]是潜在敏感词的一部分但不是结尾,继续匹配下一个字符else {// 3.2.3.1. 检查下一个字符是否存在,存在则移动end指针;否则,回退begin到当前位置,准备重新匹配if (end < text.length() - 1) {end++;} else {end = begin;}}}// 4. 将剩余未检查的文本(若有)添加到结果中result.append(text.substring(begin));// 5. 返回过滤后的文本return result.toString();}/*** 判断字符是否为符号字符* @param character 待判断的字符* @return true表示是符号字符,需要跳过;false表示不是符号字符,不跳过*/private boolean isSymbol(Character character) {// 0x2E80~0x9FFF是东亚文字: 判断字符是否不属于ASCII字母数字且不在东亚文字范围内return !CharUtils.isAsciiAlphanumeric(character) && (character < 0x2E80 || character > 0x9FFF);}/*** 内部类,定义前缀树的节点*/private static class TrieNode {private boolean isKeywordEnd = false; // 当前节点是否为敏感词的末尾节点private final Map<Character, TrieNode> childrenNode = new HashMap<>(); // 当前节点的子节点// Getter和Setter方法public boolean isKeywordEnd() {return isKeywordEnd;}public void setKeywordEnd(boolean keywordEnd) {isKeywordEnd = keywordEnd;}public TrieNode getChildrenNode(Character c) {return childrenNode.get(c);}public void setChildrenNode(Character c, TrieNode node) {childrenNode.put(c, node);}}}
这里我把敏感词过滤器的相关常量都写到一个常量类里了,也可以直接写在过滤器里。
package com.example.constant;/*** 敏感词过滤器的相关常量*/
public class SensitiveConstant {/*** 敏感词文件名称*/public static final String SENSITIVE_WORDS_FILE = "sensitive_words.txt";/*** 用于替换敏感词的字符*/public static final Character REPLACEMENT = '*';
}
3. 测试与使用
创建一个测试类测一下就行。
package com.example.filter;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
class SensitiveFilterTest {@Autowiredprivate SensitiveFilter sensitiveFilter;@Testvoid filter() {String result = sensitiveFilter.filter("accfuckxx元bitch购物车bitchjwbc");System.out.println(result);}
}
运行结果:
acc****xx*bitch***bitchjwbc
可以实现过滤,但是完全基于敏感词文件内容,需要自行完善文件。也许可以结合正则表达式扩展?不是很灵活,没研究过了。
解决方案二:使用第三方插件 houbb/sensitive-word
(推荐)
参考(更多介绍见):常见的敏感词过滤方案汇总以及高效工具sensitive-word快速实践!
houbb/sensitive-word
项目源码:https://github.com/houbb/sensitive-word
1. 添加依赖
<dependency><groupId>com.github.houbb</groupId><artifactId>sensitive-word</artifactId><version>0.17.0</version>
</dependency>
2. 测试与使用(使用默认过滤策略)
package com.example.filter;import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
class SensitiveFilterTest {@Autowiredprivate SensitiveFilter sensitiveFilter;@Testvoid filter() {String result = sensitiveFilter.filter("accfuckxx元bitch购物车bitchjwbc");System.out.println(result);System.out.println("-------------------------------");result = SensitiveWordHelper.replace("accfuckxx元bitch购物车bitchjwbc");System.out.println(result);result = SensitiveWordHelper.replace("Ⓕⓤc⒦ the bad words");System.out.println(result);result = SensitiveWordHelper.replace("ⒻⒻⒻfⓤuⓤ⒰cⓒ⒦ the bad words");System.out.println(result);result = SensitiveWordHelper.replace("fffuuck the bad words");System.out.println(result);}
}
运行结果:
acc****xx*bitch***bitchjwbc
-------------------------------
acc****xx元bitch购物车bitchjwbc
**** the bad words
ⒻⒻⒻfⓤuⓤ⒰cⓒ⒦ the bad words
fffuuck the bad words
可以实现基础过滤。比读取文件更方便。
(忽略掉这里的“元”和“购物车”。只是为了文章过审把一些很offensive的词换成了随便写的词嗯。)
如果要设置更多需要过滤的内容,可以参考以下步骤。
3. 构建配置类SensitiveWordConfig
(使用自定义过滤策略)
自己按照需求调一下就好。
package com.example.config;import com.github.houbb.sensitive.word.bs.SensitiveWordBs;
import com.github.houbb.sensitive.word.support.ignore.SensitiveWordCharIgnores;
import com.github.houbb.sensitive.word.support.resultcondition.WordResultConditions;
import com.github.houbb.sensitive.word.support.tag.WordTags;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 配置类,用于设置敏感词过滤器的自定义过滤策略* 更多配置见 https://github.com/houbb/sensitive-word*/
@Configuration
public class SensitiveWordConfig {/*** 初始化引导类* @return 初始化引导类* @since 1.0.0*/@Beanpublic SensitiveWordBs sensitiveWordBs() {SensitiveWordBs wordBs = SensitiveWordBs.newInstance().ignoreCase(true) // 忽略大小写,默认值为true.ignoreWidth(true) // 忽略半角圆角,默认值为true.ignoreNumStyle(true) // 忽略数字的写法,默认值为true.ignoreChineseStyle(true) // 忽略中文的书写格式,默认值为true.ignoreEnglishStyle(true) // 忽略英文的书写格式,默认值为true.ignoreRepeat(false) // 忽略重复词,默认值为false.enableNumCheck(false) // 是否启用数字检测,默认值为false.enableEmailCheck(false) // 是有启用邮箱检测,默认值为false.enableUrlCheck(false) // 是否启用链接检测,默认值为false.enableIpv4Check(false) // 是否启用IPv4检测,默认值为false.enableWordCheck(true) // 是否启用敏感单词检测,默认值为true.numCheckLen(8) // 数字检测,自定义指定长度,默认值为8.wordTag(WordTags.none()) // 词对应的标签,默认值为none.charIgnore(SensitiveWordCharIgnores.defaults()) // 忽略的字符,默认值为none.wordResultCondition(WordResultConditions.alwaysTrue()) // 针对匹配的敏感词额外加工,比如可以限制英文单词必须全匹配,默认恒为真.init();return wordBs;}
}
4. 测试与使用(使用自定义过滤策略)
在刚刚的配置类中已经启用了数字检测。
.enableNumCheck(true) // 是否启用数字检测,默认值为false
测一下。
package com.example.filter;import com.github.houbb.sensitive.word.bs.SensitiveWordBs;
import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
class SensitiveFilterTest {...@Autowiredprivate SensitiveWordBs sensitiveWordBs;...@Testvoid test() {String result = sensitiveWordBs.replace("accfuckxx元bitch购物车bitchjwbc");System.out.println(result);result = sensitiveWordBs.replace("Ⓕⓤc⒦ the bad words");System.out.println(result);result = sensitiveWordBs.replace("ⒻⒻⒻfⓤuⓤ⒰cⓒ⒦ the bad words");System.out.println(result);result = sensitiveWordBs.replace("fffuuck the bad words");System.out.println(result);result = sensitiveWordBs.replace("12345678dwnoxcw");System.out.println(result);result = sensitiveWordBs.replace("123456789dwnoxcw");System.out.println(result);result = sensitiveWordBs.replace("一二三四五六七八九dwnoxcw");System.out.println(result);result = sensitiveWordBs.replace("这个是我的微信:9⓿二肆⁹₈③⑸⒋➃㈤㊄");System.out.println(result);}
}
运行结果:
acc****xx元bitch购物车bitchjwbc
**** the bad words
*********** the bad words
******* the bad words
********dwnoxcw
*********dwnoxcw
*********dwnoxcw
这个是我的微信:************
就很好用了。
(忽略掉这里的“元”和“购物车”。只是为了文章过审把一些很offensive的词换成了随便写的词嗯。)
两种实现方式的对比
- 自行构建前缀树过滤器:
- 优势:高度定制,易于理解与维护,无外部依赖。
- 劣势:开发耗时,需优化性能,学习成本。
- 使用第三方开源项目:
- 优势:快速集成,功能成熟,社区支持。
- 劣势:依赖管理,安全风险,定制受限。
根据项目需求紧迫性、定制化需求及团队技术背景综合选择。简单需求或有定制化要求倾向自建;追求快速、功能全面则推荐使用现成开源方案。
最后。全文仅做学习交流使用,参考来源均已标明。
感谢提供开源的大佬们。
相关文章:
【Spring Boot】过滤敏感词的两种实现
文章目录 项目场景前置知识前缀树 实现方式解决方案一:读取敏感词文件生成前缀树构建敏感词过滤器1. 导入敏感词文件 src/main/resources/sensitive_words.txt2. 构建敏感词过滤器 SensitiveFilter3. 测试与使用 解决方案二:使用第三方插件 houbb/sensit…...
在 Zustand 中管理状态能使用类(Class)吗
在 Zustand 中,通常不推荐使用类(Class)来管理状态,因为 Zustand 的设计理念是基于函数式编程和 React Hooks 的。然而,仍然可以在 Zustand 中间接地使用类,但这并不是 Zustand 的典型用法。 如果确实想要…...
MoreTable 方法selectWithFun,count 使用实例
ORM Bee, example for MoreTable methods:selectWithFun,count ORM Bee时, MoreTable 方法selectWithFun,count 使用实例 package org.teasoft.exam.bee.osql;import org.teasoft.bee.osql.BeeException; import org.teasoft.bee.osql.FunctionType; import org.teasoft.be…...
【SpringBoot】在Spring中使用自定义条件类在Java声明Bean时实现条件注入
在Spring框架中,通过实现org.springframework.context.annotation.Condition接口并重写matches()方法,可以根据自定义条件来控制Bean的注入。这种机制非常灵活,可以帮助开发人员根据环境或配置来有选择地启用或禁用某些Bean。本文将详细介绍如…...
网卡聚合链路配置
创建名为mybond0的绑定,使用示例如下: # nmcli con add type bond con-name mybond0 ifname mybond0 mode active-backup添加从属接口,使用示例如下: # nmcli con add type bond-slave ifname enp3s0 master mybond0要添加其他从…...
PlantSimulation导入cad图作为背景
PlantSimulation导入cad图作为背景 首先要整理cad文件,正常的工艺规划总图中存在较多杂乱文件,这些信息是不需要的,如果直接导入,会非常卡。 1、打开cad软件,使用layon命令打开所有的隐藏图层,删除不需要…...
【大模型】个人对大模型选择的见解
选择大模型产品时,需要考虑多个因素,包括但不限于以下几点: 需求匹配度:首先,要明确你的需求是什么。不同的大模型产品可能在功能、性能、应用场景等方面有所侧重。例如,有的模型擅长自然语言处理ÿ…...
java的反射和python的鸭子类型
Java的反射(Reflection)和Python的鸭子类型(Duck Typing)感觉相似但又说不出具体的细节,本文借助kimi试图给出总结。 相似之处: 动态性:Java的反射允许程序在运行时查询、创建和修改类和对象的…...
爬虫工具yt-dlp
yt-dlp是youtube-dlp的一个fork,youtube-dlp曾经也较为活跃,但后来被众多网站屏蔽,于是大家转而在其基础上开发yt-dlp。yt-dlp的github项目地址为:GitHub - yt-dlp/yt-dlp: A feature-rich command-line audio/video downloaderA …...
【代码随想录训练营】【Day 50】【动态规划-9】| Leetcode 198, 213, 337
【代码随想录训练营】【Day 50】【动态规划-9】【需二刷】| Leetcode 198, 213, 337 需强化知识点 需二刷,打家劫舍系列 题目 198. 打家劫舍 class Solution:def rob(self, nums: List[int]) -> int:if len(nums) 1:return nums[0]dp [0] * (len(nums))dp…...
源码讲解kafka 如何使用零拷贝技术(zero-copy)
前言 kafka 作为一个高吞吐量的分布式消息系统,广泛应用与实时应用场景中。为了实现高效的数据传输,kafka使用了零拷贝技术(zero-copy)显著提高了性能。本文将详细讲解 Kafka 如何利用零拷贝技术优化数据传输。 什么是零拷贝 零拷贝技术目的是减少数据传输的效率。在传统…...
Ubuntu20.04配置qwen0.5B记录
环境简介 Ubuntu20.04、 NVIDIA-SMI 545.29.06、 Cuda 11.4、 python3.10、 pytorch1.11.0 开始搭建 python环境设置 创建虚拟环境 conda create --name qewn python3.10预安装modelscope和transformers pip install modelscope pip install transformers安装pytorch co…...
java自学阶段二:JavaWeb开发--day80(项目实战2之苍穹外卖)
《项目案例—黑马苍穹外卖》 目录: 学习目标项目介绍前端环境搭建(前期直接导入老师的项目,后期自己敲)后端环境搭建(导入初始项目,新建仓库使用git管理项目,新建数据库,修改登录功能ÿ…...
HPUX系统Oracle RAC如何添加ASM磁盘
前言 HPUX简介 HP-UX (Hewlett-Packard Unix) 是惠普公司开发的类 Unix 操作系统。自 1980 年代问世以来,HP-UX 在技术和功能上不断发展,适应了多种硬件平台和企业计算需求。以下是 HP-UX 的发展历史概述: 1980 年代:起源与早期…...
Jmeter 压力测测试的简单入门
下载安装 官方网站:Apache JMeter - Download Apache JMeter 下载完成解压即可。 配置 1. 找到 bin 目录下的 ApacheJMeter.jar 包,直接打开 如果向图片这样不能直接打开,就在此路径运行 CMD,然后输入下面的命令即可启动。 ja…...
N叉树的层序遍历-力扣
本题同样是二叉树的层序遍历的扩展,只不过二叉树每个节点的子节点只有左右节点,而N叉树的子节点是一个数组,层序遍历到一个节点时,需要将这个节点的子节点数组的每个节点都入队。 代码如下: /* // Definition for a N…...
解决阿里云的端口添加安全组仍然无法扫描到
发现用线上的网站扫不到这个端口,这个端口关了,但是没有更详细信息了 我用nmap扫了一下我的这个端口,发现主机是活跃的,但是有防火墙,我们列出云服务器上面的这个防火墙list,发现确实没有5566端口 参考&a…...
【因果推断python】26_双重稳健估计1
目录 不要把所有的鸡蛋放在一个篮子里 双重稳健估计 关键思想 不要把所有的鸡蛋放在一个篮子里 我们已经学会了如何使用线性回归和倾向得分加权来估计 。但是我们应该在什么时候使用哪一个呢?在不明确的情况下,请同时使用两者!双重稳健估计…...
C语言 图形化界面方式连接MySQL【C/C++】【图形化界面组件分享】
博客主页:花果山~程序猿-CSDN博客 文章分栏:MySQL之旅_花果山~程序猿的博客-CSDN博客 关注我一起学习,一起进步,一起探索编程的无限可能吧!让我们一起努力,一起成长! 目录 一.配置开发环境 二…...
Unity DOTS技术(十五) 物理系统
要解决性能的瓶颈问题,在DOTS中我们将不再使用Unity自带的物理组件. 下面来分享一下在DOTS中当如何使用物理插件. 一.导入插件 在使用DOTS系创建的实体我们会发现,游戏物体无法受物理系统影响进行运动.于是我们需要添加物理系统插件. 1.打开Package Manager > 搜索插件Uni…...
Java线程安全
线程安全 线程安全:线程安全:synchronized同步代码块:同步方法:成员同步方法:静态同步方法: Lock:应用: 单例模式:懒汉式:饿汉式:枚举饿汉式:双重检验锁: 线程…...
Solidity选择使用 require 语句还是条件语句结合手动触发 revert 操作?回滚交易和抛出异常如何选择?
文章目录 Solidity选择使用 require 语句还是条件语句结合手动触发 revert 操作?场景举例:回滚交易和抛出异常如何选择? Solidity选择使用 require 语句还是条件语句结合手动触发 revert 操作? IERC721 nft IERC721(nftAddress)…...
SpringCloud 网关配置websocket
一、nginx https://域名.com location /websocket/ { proxy_pass http://172.1.1.173:8181/; #内网网关IP proxy_http_version 1.1; proxy_read_timeout 360s; proxy_redirect off; proxy_set_header Upgrade $http_upgrade; …...
基于JavaScript 实现近邻算法以及优化方案
前言 近邻算法(K-Nearest Neighbors,简称 KNN)是一种简单的、广泛使用的分类和回归算法。它的基本思想是:给定一个待分类的样本,找到这个样本在特征空间中距离最近的 k 个样本,这 k 个样本的多数类别作为待…...
移动端适配和响应式页面中的常用单位
在移动端适配和响应式页面中,一般采用以下几种单位: 百分比(%):百分比单位是相对于父元素的大小计算的。它可以用于设置宽度、高度、字体大小等属性,使得元素能够随着父元素的大小自动调整。百分比单位在响…...
麒麟v10系统arm64架构openssh9.7p1的rpm包
制作openssh 说明 理论上制作的多个rpm在arm64架构(aarch64)都适用 系统信息:4.19.90-17.ky10.aarch64 GNU/Linux 升级前备份好文件/etc/ssh、/etc/pam.d等以及开启telnet 升级后确认正常后关闭telnet 在之前制作过openssh-9.5p1基础上继续…...
刚刚❗️德勤2025校招暑期实习测评笔试SHL测评题库已发(答案)
📣德勤 2024暑期实习测评已发,正在申请的小伙伴看过来哦👀 ㊙️本次暑期实习优先考虑2025年本科及以上学历的毕业生,此次只有“审计及鉴定”“税务与商务咨询”两个部门开放了岗位~ ⚠️测评注意事项: ὄ…...
python对视频进行帧处理以及裁减部分区域
视频截取帧 废话不多说直接上代码: from cv2 import VideoCapture from cv2 import imwrite# 定义保存图片函数 # image:要保存的图片名字 # addr;图片地址与相片名字的前部分 # num: 相片,名字的后缀。int 类型 def save_image(image, add…...
Python栈的编程题目
你好,我是悦创。 下面是三道关于栈的编程题目,适合不同难度级别的练习: 1. 有效的括号(简单) 题目描述: 给定一个只包括 (,),{,},[ 和 ] 的字符串…...
ROS云课三分钟外传之CoppeliaSim_Edu_V4_1_0_Ubuntu16_04
三分钟热度试一试吧,走过路过不要错过。 参考之前: 从云课五分钟到一分钟之v-rep_pro_edu_v3_6_2-CSDN博客 git clone https://gitcode.net/ZhangRelay/v-rep_pro_edu_v3_6_2_ubuntu16_04.gittar -xf v-rep_pro_edu_v3_6_2_ubuntu16_04/V-REP_PRO_EDU…...
西安网络建站/网页优化怎么做
本文实例讲述了php实现将HTML页面转换成word并且保存的方法。分享给大家供大家参考,具体如下:这里用使用到一个PHP的工具叫:PHPWord。生成Word的原理是,将堆规定好了的xml压缩成一个zip包,并且把后缀名改成doc或者docx…...
怎样在网站做宣传/国家税务总局网
1 两种模式的原理和区别 Receiver模式 1. Receiver模式下的运行架构 1)InputDStream: 从流数据源接收的输入数据。 2)Receiver:负责接收数据流,并将数据写到本地。 3)Streaming Context:代表SparkStreaming,负责Streaming层面…...
网站建设与网页设计从入门到精通 pdf/软文发稿公司
昨天在软件上完成了登录,今天完善一下界面 转载于:https://www.cnblogs.com/lijing925/p/8494951.html...
做电影网站需多大的空间/优化设计答案五年级上册
MATLAB概率分布函数mean Average or mean value of arraystd Standard deviationcorrcoef Correlation coefficientsmedian Median value of arraymax Largest elements in arraymin Smallest elements in array统计工具箱函数表Ⅰ-1 概率密度函数函数名对应分布的概率密度函数…...
推广网站的方法/百度认证营销推广师
盒子不能为空的插板问题 有8个一模一样的小球,把它们放到4个不同的盒子里,每个盒子都不能为空,有几种不同的放法? 解题思路 因为要放入4个不同的盒子里,可以在小球之间插入3块隔板将它们成四份,如下图所…...
自学做甜品师的网站/搜索百度
Dictionary 存放所有数据表,视图,同义词名称和解释Dict_columns 数据字典里字段名称的和解释Dba_users 用户 Dba_tablespaces 表空间Dba_data_files 数据库的文件 Dba_free_space 空闲表空间Dba_rollback_segs 回滚段User_objects 数据对象 User_constra…...