Elastic:IK分词器分词、停用词热更新如何配置-基于数据库

news2024/11/21 1:25:06

上一期,我们说明了基于API形式的热更新,但是API形式的热更新存在词库的管理不方便,要直接操作磁盘文件,检索页很麻烦;文件的读写没有专门的优化,性能不好;多一次接口调用和网络传输等缺点,因此这期我们来说明直连数据库的方式来实现热更新

1. 简介

官方github中并没有说明这种方式,所以本身是不支持直连数据库实现热更新的,要实现需要通过修改源码来做到。

相比较与API的形式,直连数据库的方式更加稳定,但是因为官方并没有明确支持这种方式所以也存在着不确定性,生产中采取哪种方式,还要根据实际业务的需求情况而定

2. 步骤

1、github下载源码:https://github.com/medcl/elasticsearch-analysis-ik/releases?page=2
在这里插入图片描述
2、在IDEA中导入刚刚下载的源码

3、源码导入需要一会时间,我们先把数据表创建出来,一共要创建两张表:分词表、停止词表
需要字段id,word
在这里插入图片描述
在这里插入图片描述
4、下载下来的源码中使用的elasticsearch版本是7.4的,我们需要将其改为对应版本,因为我用的es是7.13.0的,所以在pom中将其改为7.13.0
在这里插入图片描述
5、并且在pom中添加mysql驱动器依赖

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
</dependency>

6、创建数据库配置文件jdbc-reload.properties,放在IK项目的config文件夹下

jdbc.url=jdbc:mysql://192.168.101.109:3306/user_test?serverTimezone=UTC
jdbc.user=root
jdbc.password=123456
jdbc.reload.extend.sql=select word from extend_word
jdbc.reload.stop.sql=select word from stop_word
# 间隔时间 毫秒
jdbc.reload.interval=1000

7、IK分词器加载分词的源码在witea.analyzer.dic.Dictionary类中,打开这个类,添加如下方法

两个加载分词的方法可以模仿自带的加载分词方法来写,具体如下:
添加加载拓展词方法

/**
	 * 加载自定义数据库拓展词典到主词库表
	 * 55555 20211216
	 */
	public void loadExtendDictFromMysql(){
		Connection connection = null;
		Statement statement = null;
		ResultSet resultSet = null;
		try{
			Path file = PathUtils.get(getDictRoot(),"jdbc-reload.properties");
			props.load(new FileInputStream(file.toFile()));
			logger.info("loading jdbc-reload.properties");
			for (Object key : props.keySet()) {
				 logger.info(key + "=" + props.getProperty(String.valueOf(key)));
			}
			logger.info(" hot dict " + props.getProperty("jdbc.reload.extend.sql"));
			connection = DriverManager.getConnection(
					props.getProperty("jdbc.url"),
					props.getProperty("jdbc.user"),
					props.getProperty("jdbc.password"));
			statement = connection.createStatement();
			resultSet = statement.executeQuery(props.getProperty("jdbc.reload.extend.sql"));
			while (resultSet.next()){
				// 加载扩展词典数据到主内存词典中
				String theWord = resultSet.getString("word");
				logger.info(theWord);
				_MainDict.fillSegment(theWord.trim().toLowerCase().toCharArray());
			}
			// 加载时间
			Thread.sleep(Integer.valueOf(String.valueOf(props.get("jdbc.reload.interval"))));
		}catch (Exception e){
			logger.error("[Extend Dict Loading] "+ e);
		}finally {
			if(resultSet != null){
				try {
					statement.close();
				} catch (SQLException e) {
					logger.error("[Extend Dict Loading] " + e);
				}
			}
			if(connection != null){
				try {
					connection.close();
				} catch (SQLException e) {
					logger.error("[Extend Dict Loading] " + e);
				}
			}
		}
	}

添加加载停用词方法

/**
	 * 加载自定义数据库拓展停止词词典到主词库表
	 * 55555 20211216
	 */
	public void loadStopDictFromMysql(){
		// 建立主词典实例
		_StopWords = new DictSegment((char) 0);
		Connection connection = null;
		Statement statement = null;
		ResultSet resultSet = null;
		try{
			Path file = PathUtils.get(getDictRoot(),"jdbc-reload.properties");
			props.load(new FileInputStream(file.toFile()));
			logger.info("loading jdbc-reload.properties");
			for (Object key : props.keySet()) {
				logger.info(key + "=" + props.getProperty(String.valueOf(key)));
			}
			logger.info(" stop dict " + props.getProperty("jdbc.reload.stop.sql"));
			connection = DriverManager.getConnection(
					props.getProperty("jdbc.url"),
					props.getProperty("jdbc.user"),
					props.getProperty("jdbc.password"));
			statement = connection.createStatement();
			resultSet = statement.executeQuery(props.getProperty("jdbc.reload.stop.sql"));
			while (resultSet.next()){
				// 加载扩展词典数据到主内存词典中
				String theWord = resultSet.getString("word");
				logger.info(theWord);
				_StopWords.fillSegment(theWord.trim().toLowerCase().toCharArray());
			}
			// 加载时间
			Thread.sleep(Integer.valueOf(String.valueOf(props.get("jdbc.reload.interval"))));
		}catch (Exception e){
			logger.error("[Stop Dict Loading] "+ e);
		}finally {
			if(resultSet != null){
				try {
					statement.close();
				} catch (SQLException e) {
					logger.error("[Stop Dict Loading] " + e);
				}
			}
			if(connection != null){
				try {
					connection.close();
				} catch (SQLException e) {
					logger.error("[Stop Dict Loading] " + e);
				}
			}
		}
	}

8、在loadMainDict()中添加自定义的加载拓展词的方法

在这里插入图片描述

9、在loadStopWordDict方法中添加自定义的加载停止词的方法
在这里插入图片描述
这里如何判断将新写的方法添加到哪里呢?
第一种方式:
(1)新增的加载拓展词的方法,只要查看原有的加载拓展词的方法loadRemoteExtDict()在哪些地方被引用了,同步的添加一下我们自己写的拓展词方法
(2)新增的加载停止词的方法,同理查看停止词方法loadStopWordDict()在哪儿被引用了,同步添加一份即可
第二种方式:
直接将方法添加到原有的加载拓展词、停止词的方法中

10、因为需要加载数据库,因此需要加载数据库驱动器,在Dictionary中添加:

static {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			logger.error("error", e);
		}
	}

11、使用maven将项目打包:
注意:这里因为pom中使用的是elasticsearch4.0,因此打出来的包的版本也是7.4.0.将其改为7.13.0.因为我现在用的es是7.13版本的。
在这里插入图片描述
12、将打包好的ik分词器添加到es/plusgins目录下,将原来的ik分词器删除,将新的重新解压并重命名为ik

13、将mysql驱动器jar包添加到ik分词器目录下

scp mysql-connector-java-8.0.22.jar root@172.16.188.8:/var/local/elasticsearch/plugins/ik

14、重启es

./bin/elasticsearch

日志打印出加载的分词和停用词
在这里插入图片描述
15、测试

GET _analyze
{
  "analyzer": "ik_smart",
  "text": "伍55突然想养一只猫了"
}

结果显示分词正常,停用词也被过滤了
在这里插入图片描述

3.常见报错

3.1 java.lang.ExceptionInInitializerError: null …access denied (“java.lang.RuntimePermission” “setContextClassLoader”)

报错详情:

java.lang.ExceptionInInitializerError: null
	at java.lang.Class.forName0(Native Method) ~[?:1.8.0_271]
	at java.lang.Class.forName(Class.java:264) ~[?:1.8.0_271]
	at com.mysql.cj.jdbc.NonRegisteringDriver.<clinit>(NonRegisteringDriver.java:99) ~[?:?]
	at java.lang.Class.forName0(Native Method) ~[?:1.8.0_271]
	at java.lang.Class.forName(Class.java:264) ~[?:1.8.0_271]
	at org.wltea.analyzer.dic.Dictionary.<clinit>(Dictionary.java:103) ~[?:?]
	at org.wltea.analyzer.cfg.Configuration.<init>(Configuration.java:40) ~[?:?]
	at org.elasticsearch.index.analysis.IkTokenizerFactory.<init>(IkTokenizerFactory.java:15) ~[?:?]
	at org.elasticsearch.index.analysis.IkTokenizerFactory.getIkSmartTokenizerFactory(IkTokenizerFactory.java:23) ~[?:?]
	at org.elasticsearch.index.analysis.AnalysisRegistry.buildMapping(AnalysisRegistry.java:433) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.index.analysis.AnalysisRegistry.buildTokenizerFactories(AnalysisRegistry.java:275) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.index.analysis.AnalysisRegistry.build(AnalysisRegistry.java:203) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.index.IndexModule.newIndexService(IndexModule.java:431) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.indices.IndicesService.createIndexService(IndicesService.java:663) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.indices.IndicesService.createIndex(IndicesService.java:566) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.indices.IndicesService.createIndex(IndicesService.java:170) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.indices.cluster.IndicesClusterStateService.createIndices(IndicesClusterStateService.java:468) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.indices.cluster.IndicesClusterStateService.applyClusterState(IndicesClusterStateService.java:228) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.cluster.service.ClusterApplierService.callClusterStateAppliers(ClusterApplierService.java:499) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.cluster.service.ClusterApplierService.callClusterStateAppliers(ClusterApplierService.java:489) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.cluster.service.ClusterApplierService.applyChanges(ClusterApplierService.java:460) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.cluster.service.ClusterApplierService.runTask(ClusterApplierService.java:407) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.cluster.service.ClusterApplierService.access$000(ClusterApplierService.java:57) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.cluster.service.ClusterApplierService$UpdateTask.run(ClusterApplierService.java:151) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:673) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.runAndClean(PrioritizedEsThreadPoolExecutor.java:241) ~[elasticsearch-7.13.0.jar:7.13.0]
	at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:204) ~[elasticsearch-7.13.0.jar:7.13.0]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_271]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_271]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_271]
Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "setContextClassLoader")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) ~[?:1.8.0_271]
	at java.security.AccessController.checkPermission(AccessController.java:886) ~[?:1.8.0_271]
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) ~[?:1.8.0_271]
	at java.lang.Thread.setContextClassLoader(Thread.java:1474) ~[?:1.8.0_271]
	at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.lambda$static$0(AbandonedConnectionCleanupThread.java:72) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.<init>(ThreadPoolExecutor.java:619) ~[?:1.8.0_271]
	at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:932) ~[?:1.8.0_271]
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1367) ~[?:1.8.0_271]
	at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:668) ~[?:1.8.0_271]
	at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.<clinit>(AbandonedConnectionCleanupThread.java:75) ~[?:?]
	... 30 more
fatal error in thread [elasticsearch[node-4][clusterApplierService#updateTask][T#1]], exiting
java.lang.ExceptionInInitializerError
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at com.mysql.cj.jdbc.NonRegisteringDriver.<clinit>(NonRegisteringDriver.java:99)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at org.wltea.analyzer.dic.Dictionary.<clinit>(Dictionary.java:103)
	at org.wltea.analyzer.cfg.Configuration.<init>(Configuration.java:40)
	at org.elasticsearch.index.analysis.IkTokenizerFactory.<init>(IkTokenizerFactory.java:15)
	at org.elasticsearch.index.analysis.IkTokenizerFactory.getIkSmartTokenizerFactory(IkTokenizerFactory.java:23)
	at org.elasticsearch.index.analysis.AnalysisRegistry.buildMapping(AnalysisRegistry.java:433)
	at org.elasticsearch.index.analysis.AnalysisRegistry.buildTokenizerFactories(AnalysisRegistry.java:275)
	at org.elasticsearch.index.analysis.AnalysisRegistry.build(AnalysisRegistry.java:203)
	at org.elasticsearch.index.IndexModule.newIndexService(IndexModule.java:431)
	at org.elasticsearch.indices.IndicesService.createIndexService(IndicesService.java:663)
	at org.elasticsearch.indices.IndicesService.createIndex(IndicesService.java:566)
	at org.elasticsearch.indices.IndicesService.createIndex(IndicesService.java:170)
	at org.elasticsearch.indices.cluster.IndicesClusterStateService.createIndices(IndicesClusterStateService.java:468)
	at org.elasticsearch.indices.cluster.IndicesClusterStateService.applyClusterState(IndicesClusterStateService.java:228)
	at org.elasticsearch.cluster.service.ClusterApplierService.callClusterStateAppliers(ClusterApplierService.java:499)
	at org.elasticsearch.cluster.service.ClusterApplierService.callClusterStateAppliers(ClusterApplierService.java:489)
	at org.elasticsearch.cluster.service.ClusterApplierService.applyChanges(ClusterApplierService.java:460)
	at org.elasticsearch.cluster.service.ClusterApplierService.runTask(ClusterApplierService.java:407)
	at org.elasticsearch.cluster.service.ClusterApplierService.access$000(ClusterApplierService.java:57)
	at org.elasticsearch.cluster.service.ClusterApplierService$UpdateTask.run(ClusterApplierService.java:151)
	at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:673)
	at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.runAndClean(PrioritizedEsThreadPoolExecutor.java:241)
	at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:204)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "setContextClassLoader")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
	at java.security.AccessController.checkPermission(AccessController.java:886)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
	at java.lang.Thread.setContextClassLoader(Thread.java:1474)
	at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.lambda$static$0(AbandonedConnectionCleanupThread.java:72)
	at java.util.concurrent.ThreadPoolExecutor$Worker.<init>(ThreadPoolExecutor.java:619)
	at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:932)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1367)
	at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:668)
	at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.<clinit>(AbandonedConnectionCleanupThread.java:75)
	... 30 more


解决:
这是因为jdk权限不够

jdk14在/var/local/jdk-14.0.2/lib/security/default.policy中的grant{}里添加
jdk8是在/var/local/jdk1.8.0_271/jre/lib/security/java.policy中的grant{}里添加
因为ES7.12后官方推荐使用jdk11+,而ES兼容的jdk版本又只有jdk8,11,14,所以我这里以jdk14为例

 permission java.lang.RuntimePermission "setContextClassLoader";

在这里插入图片描述
再次重启ES,出现报错
[Extend Dict Loading] java.sql.SQLNonTransientConnectionException: Could not create connection to database server.

3.2 java.sql.SQLNonTransientConnectionException: Could not create connection to database server.

解决:

1、检查是否将mysql-connector-java-8.0.22.jar错误的放在plugins目录下了,应该放在plugins/ik路径下

2、检查ik源码pom中的驱动器版本和ik目录中的驱动器版本是否一致

3、在jdk/lib/security/default.policy中添加权限
jdk14在/var/local/jdk-14.0.2/lib/security/default.policy中的grant{}里添加
jdk8是在/var/local/jdk1.8.0_271/jre/lib/security/java.policy中的grant{}里添加

我这里使用的是es自带的jdk

 vim jdk/lib/security/default.policy

添加内容,目的是给该ip和端口开通socket网络链接权限

// 192.168.244.1:3306是拓展词数据库ip和端口
permission java.net.SocketPermission "192.168.244.1:3306","connect,resolve"; 

在这里插入图片描述

参考博客

【1】https://artisan.blog.csdn.net/article/details/99350933(文中代码主要参考该文)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1978753.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件测试需要具备的基础知识【功能测试】---前端知识(一)

​ ​ 您好&#xff0c;我是程序员小羊&#xff01; 前言 为了更好的学习软件测试的相关技能&#xff0c;需要具备一定的基础知识。需要学习的基础知识包括&#xff1a; 1、计算机基础 2、前端知识 3、后端知识 4、软件测试理论 后期分四篇文章进行编写&#xff0c;这是第二篇 …

MongoDB未授权访问漏洞

开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作&#xff08;增、删、改、查高危动作&#xff09;而且可以远程访问数据库。 漏洞原因 造成未授权访问的根本原因就在于启动 Mongodb 的时候未设置 --auth 也很少…

Node.js的下一代浏览器和移动自动化测试框架-WebdriverIO

在现代软件开发中&#xff0c;自动化测试已成为保障软件质量的关键环节。而在众多测试框架中&#xff0c;WebdriverIO凭借其强大的功能和简洁的语法&#xff0c;成为Node.js生态中备受瞩目的浏览器和移动自动化测试框架。那么&#xff0c;WebdriverIO究竟有哪些独特之处&#x…

Substance Painter材质制作原理

21 材质制作原理_哔哩哔哩_bilibili 颜色&#xff0c;纹理&#xff0c;高光 木头的制作 玻璃的制作 玻璃要给一定的金属度

指标一致化处理

什么是数据指标 数据指标有别于传统意义上的统计指标&#xff0c;它是通过对数据进行分析得到的一个汇总结果&#xff0c;是将业务单元精分和量化后的度量值&#xff0c;使得业务目标可描述、可度量、可拆解。 数据指标有哪些类型 极大型:期望取值越大越好&#xff1b; 极小…

战略项目与可以帮助战略的项目

在公司内&#xff0c;如果没有机会做战略项目&#xff0c;那么就尽可能让自己的项目产生一些可以被战略项目使用的成果&#xff0c;最好是可以被多个战略项目使用的成果。 或者&#xff0c;将自己的项目和战略项目融合。 比如&#xff0c;一家生产面包的企业&#xff0c;你是负…

用PyTorch 从零开始构建 BitNet 1.58bit

我们手动实现BitNet的编写&#xff0c;并进行的一系列小实验证实&#xff0c;看看1.58bit 模型是否与全精度的大型语言模型相媲美&#xff01; 什么是量化以及为什么需要它&#xff1f; 量化是用更少的比特数表示浮点数的过程。当两个数字使用不同的比特数进行量化时&#xf…

一篇教会你PXE高效批量网络装机及kickstart无人值守安装

目录 搭建PXE的前提 搭建PEX的过程 如何构建PXE服务器 搭建本地yum源 搭建apache 创建软链接将本地yum源到apache页面下 搭建dhcp服务 dhcp配置文件如下 使用system-config-kickstart生成ks.cfg文件 &#xff0c;.cfg配置文件如下 搭建TFTP服务 搭建完成后测试 搭建…

跟李沐学AI:NiN网络中的网络

NiN块 一个卷积层后跟着两个全连接层&#xff08;实际为核窗口大小为1x1的卷积层&#xff09;。卷积层步幅为1&#xff0c;无填充&#xff0c;输出形状与卷积层输出形状相同&#xff0c;起到全连接层的作用。 NiN架构 无全连接层&#xff0c;交替使用NiN块和步幅为2的最大池化…

【C++标准模版库】list的介绍及使用

list 一.list的介绍二.list的使用1.list 构造函数2.list 空间大小3.list 增删查改4.list 迭代器的使用1.正向迭代器2.反向迭代器 5.list 其他成员函数 三.vector与list关于sort性能的比较 一.list的介绍 C中的list标准模板库&#xff08;STL&#xff09;是C标准库中的一个重要组…

Linux文件管理和IO重定向知识总结

目录 一&#xff0c;文件管理 Linux的目录结构是一个树状结构&#xff1a; 文件的分类&#xff1a; 操作文件的常用命令&#xff1a; 文件元数据和节点和inode表结构&#xff1a; 特点&#xff1a; 创建文件&#xff1a; 查看文件inode号&#xff1a; cp和inode&#x…

揭秘Matplotlib等高线图:让数据‘高山流水‘间,笑点与深度并存!

1. 引言 在这个数据如山的时代&#xff0c;你是不是也曾在茫茫数海中迷失方向&#xff0c;渴望找到那片隐藏的“数据绿洲”&#xff1f;别怕&#xff0c;今天咱们就来聊聊Matplotlib这位绘图界的魔术师&#xff0c;特别是它那令人叹为观止的等高线图技能。想象一下&#xff0c…

领域模型(Domain Model)

前言 软件的核心是其为用户解决领域相关的问题的能力。所有其他特性&#xff0c;不管有多么重要&#xff0c;都要服务于这个基本目的。当领域很复杂时&#xff0c;这是一项艰巨的任务&#xff0c;要求高水平技术人员的共同努力。开发人员必须钻研领域以获取业务知识。他们必须…

拉刀基础知识——拉刀的种类

如前面所说&#xff1a;近期要围绕拉削和拉刀这个话题&#xff0c;分享一些相关的内容&#xff0c;从最基础的知识开始&#xff0c;为此还专门买了本旧书——《拉刀设计》入门学习。废话不多说&#xff0c;直接开始。 拉刀最早由冲头演变而来&#xff0c;用于加工方孔&#xf…

【Web】TFCCTF 2024 部分题解

目录 GREETINGS SURFING SAFE_CONTENT FLASK DESTROYER GREETINGS 打express的SSTI GitHub - TheWation/NodeJsSSTI: Express app with Pug templates demonstrating SSTI vulnerability and secure implementation for educational purposes. payload: /result?user…

历史标签如何时间迁移?

本文解析的论文是&#xff1a; Lin, C.; Du, P.; Samat, A.; Li, E.; Wang, X.; Xia, J. Automatic Updating of Land Cover Maps in Rapidly Urbanizing Regions by Relational Knowledge Transferring from GlobeLand30. Remote Sens. 2019, 11, 1397. https://doi.org/10.33…

一刷代码随想录(动态规划2)

62.不同路径 题意&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少…

我的面包多

我的面包多主页&#xff1a;https://mbd.pub/o/author-bGubnGpq 欢迎咨询。

JavaSE面试篇章——一文干破Java集合

文章目录 Java集合——一文干破集合一、集合的理解和好处1.1 数组1.2 集合 二、集合的框架体系三、Collection接口和常用方法3.1 Collection接口实现类的特点3.2 Collection接口遍历元素方式1-使用Iterator(迭代器)3.2.1 基本介绍3.2.2 迭代器的执行原理3.2.3 Iterator接口的方…

数据库典型例题2-ER图转换关系模型

1.question solution: 2.做题步骤 一些解释&#xff1a; <1弱实体把强属性的主键写进去&#xff0c;指向强属性。eg:E6_A13指向E5_A13 <21:1&#xff0c;1:n&#xff0c;m:n&#xff1a;将完全参与的一方&#xff08;双线&#xff09;指向另一方&#xff0c;并将对方的…