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

Springboot集成ElasticSearch实现minio文件内容全文检索

一、docker安装Elasticsearch

(1)springboot和Elasticsearch的版本对应关系如下,请看版本对应:

 注意安装对应版本,否则可能会出现一些未知的错误。

(2)拉取镜像

docker pull elasticsearch:7.17.6

(3)运行容器

docker run  -it  -d  --name elasticsearch -e "discovery.type=single-node"  -e "ES_JAVA_OPTS=-Xms512m -Xmx1024m"   -p 9200:9200 -p 9300:9300  elasticsearch:7.17.6

 访问http://localhost:9200/,出现如下内容表示安装成功。

(4)安装中文分词器

进入容器:

docker exec -it elasticsearch bash

然后进入bin目录执行下载安装ik分词器命令:

elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.6/elasticsearch-analysis-ik-7.17.6.zip

退出bash并重启容器:

docker restart elasticsearch

二、安装kibana

Kibana 是为 Elasticsearch设计的开源分析和可视化平台。你可以使用 Kibana 来搜索,查看存储在 Elasticsearch 索引中的数据并与之交互。你可以很容易实现高级的数据分析和可视化,以图表的形式展现出来。

(1)拉取镜像

docker pull kibana:7.17.6

(2)运行容器 

docker run --name kibana -p 5601:5601 --link elasticsearch:es  -e "elasticsearch.hosts=http://es:9200"  -d kibana:7.17.6

--link elasticsearch:es表示容器互联,即容器kibana连接到elasticsearch。

(3)使用kibana dev_tools发送http请求操作Elasticsearch

 三、后端代码

(1)引入maven依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>

(2)application.yml配置

spring:elasticsearch:uris: http://localhost:9200

(3)实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;import java.util.Date;/*** @author yangfeng*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "file")
public class File {@Idprivate String id;/*** 文件名称*/@Field(type = FieldType.Text, analyzer = "ik_max_word")private String fileName;/*** 文件分类*/@Field(type = FieldType.Keyword)private String fileCategory;/*** 文件内容*/@Field(type = FieldType.Text, analyzer = "ik_max_word")private String fileContent;/*** 文件存储路径*/@Field(type = FieldType.Keyword, index = false)private String filePath;/*** 文件大小*/@Field(type = FieldType.Keyword, index = false)private Long fileSize;/*** 文件类型*/@Field(type = FieldType.Keyword, index = false)private String fileType;/*** 创建人*/@Field(type = FieldType.Keyword, index = false)private String createBy;/*** 创建日期*/@Field(type = FieldType.Keyword, index = false)private Date createTime;/*** 更新人*/@Field(type = FieldType.Keyword, index = false)private String updateBy;/*** 更新日期*/@Field(type = FieldType.Keyword, index = false)private Date updateTime;}

(4)repository接口,继承ElasticsearchRepository

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Highlight;
import org.springframework.data.elasticsearch.annotations.HighlightField;
import org.springframework.data.elasticsearch.annotations.HighlightParameters;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;import java.util.List;/*** @author yangfeng* @date: 2024年11月9日 15:29*/
@Repository
public interface FileRepository extends ElasticsearchRepository<File, String> {/*** 关键字查询** @return*/@Highlight(fields = {@HighlightField(name = "fileName"), @HighlightField(name = "fileContent")},parameters = @HighlightParameters(preTags = {"<span style='color:red'>"}, postTags = {"</span>"}, numberOfFragments = 0))List<SearchHit<File>> findByFileNameOrFileContent(String fileName, String fileContent, Pageable pageable);
}

(5)service接口

import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;import java.util.List;/*** description: ES文件服务** @author yangfeng* @version V1.0* @date 2023-02-21*/
public interface IFileService {/*** 保存文件*/void saveFile(String filePath, String fileCategory) throws Exception;/*** 关键字查询** @return*/List<SearchHit<File>> search(FileDTO dto);/*** 关键字查询** @return*/SearchHits<File> searchPage(FileDTO dto);
}

(6)service实现类

import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.MinioUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Objects;/*** description: ES文件服务** @author yangfeng* @version V1.0* @date 2023-02-21*/
@Slf4j
@Service
public class FileServiceImpl implements IFileService {@Autowiredprivate FileRepository fileRepository;@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;/*** 保存文件*/@Overridepublic void saveFile(String filePath, String fileCategory) throws Exception {if (Objects.isNull(filePath)) {throw new JeecgBootException("文件不存在");}LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();String fileName = CommonUtils.getFileNameByUrl(filePath);String fileType = StringUtils.isNotBlank(fileName) ? fileName.substring(fileName.lastIndexOf(".") + 1) : null;InputStream inputStream = MinioUtil.getMinioFile(filePath);// 读取文件内容,上传到es,方便后续的检索String fileContent = FileUtils.readFileContent(inputStream, fileType);File file = new File();file.setId(IdUtil.getSnowflake(1, 1).nextIdStr());file.setFileContent(fileContent);file.setFileName(fileName);file.setFilePath(filePath);file.setFileType(fileType);file.setFileCategory(fileCategory);file.setCreateBy(user.getUsername());file.setCreateTime(new Date());fileRepository.save(file);}/*** 关键字查询** @return*/@Overridepublic List<SearchHit<File>> search(FileDTO dto) {Pageable pageable = PageRequest.of(dto.getPageNo() - 1, dto.getPageSize(), Sort.Direction.DESC, "createTime");return fileRepository.findByFileNameOrFileContent(dto.getKeyword(), dto.getKeyword(), pageable);}@Overridepublic SearchHits<File> searchPage(FileDTO dto) {NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();queryBuilder.withQuery(QueryBuilders.multiMatchQuery(dto.getKeyword(), "fileName", "fileContent"));// 设置高亮HighlightBuilder highlightBuilder = new HighlightBuilder();String[] fieldNames = {"fileName", "fileContent"};for (String fieldName : fieldNames) {highlightBuilder.field(fieldName);}highlightBuilder.preTags("<span style='color:red'>");highlightBuilder.postTags("</span>");highlightBuilder.order();queryBuilder.withHighlightBuilder(highlightBuilder);// 也可以添加分页和排序queryBuilder.withSorts(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)).withPageable(PageRequest.of(dto.getPageNo() - 1, dto.getPageSize()));NativeSearchQuery nativeSearchQuery = queryBuilder.build();return elasticsearchRestTemplate.search(nativeSearchQuery, File.class);}}

(7)controller

import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 文件es操作** @author yangfeng* @since 2024-11-09*/
@Slf4j
@RestController
@RequestMapping("/elasticsearch/file")
public class FileController {@Autowiredprivate IFileService fileService;/*** 保存文件** @return*/@PostMapping(value = "/saveFile")public Result<?> saveFile(@RequestBody File file) throws Exception {fileService.saveFile(file.getFilePath(), file.getFileCategory());return Result.OK();}/*** 关键字查询-repository** @throws Exception*/@PostMapping(value = "/search")public Result<?> search(@RequestBody FileDTO dto) {return Result.OK(fileService.search(dto));}/*** 关键字查询-原生方法** @throws Exception*/@PostMapping(value = "/searchPage")public Result<?> searchPage(@RequestBody FileDTO dto) {return Result.OK(fileService.searchPage(dto));}}

(8)工具类

import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;@Slf4j
public class FileUtils {private static final List<String> FILE_TYPE;static {FILE_TYPE = Arrays.asList("pdf", "doc", "docx", "text");}public static String readFileContent(InputStream inputStream, String fileType) throws Exception{if (!FILE_TYPE.contains(fileType)) {return null;}// 使用PdfBox读取pdf文件内容if ("pdf".equalsIgnoreCase(fileType)) {return readPdfContent(inputStream);} else if ("doc".equalsIgnoreCase(fileType) || "docx".equalsIgnoreCase(fileType)) {return readDocOrDocxContent(inputStream);} else if ("text".equalsIgnoreCase(fileType)) {return readTextContent(inputStream);}return null;}private static String readPdfContent(InputStream inputStream) throws Exception {// 加载PDF文档PDDocument pdDocument = PDDocument.load(inputStream);// 创建PDFTextStripper对象, 提取文本PDFTextStripper textStripper = new PDFTextStripper();// 提取文本String content = textStripper.getText(pdDocument);// 关闭PDF文档pdDocument.close();return content;}private static String readDocOrDocxContent(InputStream inputStream) {try {// 加载DOC文档XWPFDocument document = new XWPFDocument(inputStream);// 2. 提取文本内容XWPFWordExtractor extractor = new XWPFWordExtractor(document);return extractor.getText();} catch (IOException e) {e.printStackTrace();return null;}}private static String readTextContent(InputStream inputStream) {StringBuilder content = new StringBuilder();try (InputStreamReader isr = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {int ch;while ((ch = isr.read()) != -1) {content.append((char) ch);}} catch (IOException e) {e.printStackTrace();return null;}return content.toString();}}

(9)dto

import lombok.Data;@Data
public class FileDTO {private String keyword;private Integer pageNo;private Integer pageSize;}

四、前端代码

(1)查询组件封装

<template><a-input-searchv-model:value="pageInfo.keyword"placeholder="全文检索"@search="handleSearch"style="width: 220px;margin-left:30px"/><a-modal v-model:visible="showSearch" title="全文检索" width="900px" :footer="null"destroy-on-close><SearchContent :items="searchItems" :loading="loading"/><div style="padding: 10px;display: flex;justify-content: flex-end"><Pagination v-if="pageInfo.total" :pageSize="pageInfo.pageSize" :pageNo="pageInfo.pageNo":total="pageInfo.total" @pageChange="changePage" :show-total="total => `共 ${total} 条`"/></div></a-modal>
</template><script lang="ts" setup>
import {ref} from 'vue'
import {Pagination} from "ant-design-vue";
import SearchContent from "@/components/ElasticSearch/SearchContent.vue"
import {searchPage} from "@/api/sys/elasticsearch"const loading = ref<boolean>(false)
const showSearch = ref<any>(false)
const searchItems = ref<any>();const pageInfo = ref<{pageNo: number;pageSize: number;keyword: string;total: number;
}>({// 当前页码pageNo: 1,// 当前每页显示多少条数据pageSize: 10,keyword: '',total: 0,
});async function handleSearch() {if (!pageInfo.value.keyword) {return;}pageInfo.value.pageNo = 1showSearch.value = trueawait getSearchItems();
}function changePage(pageNo) {pageInfo.value.pageNo = pageNogetSearchItems();
}async function getSearchItems() {loading.value = truetry {const res: any = await searchPage(pageInfo.value);searchItems.value = res?.searchHits;debuggerpageInfo.value.total = res?.totalHits} finally {loading.value = false}
}
</script><style scoped></style>

(2)接口elasticsearch.ts

import {defHttp} from '/@/utils/http/axios';enum Api {saveFile = '/elasticsearch/file/saveFile',searchPage = '/elasticsearch/file/searchPage',
}/*** 保存文件到es* @param params*/
export const saveFile = (params) => defHttp.post({url: Api.saveFile,params
});/*** 关键字查询-原生方法* @param params*/
export const searchPage = (params) => defHttp.post({url: Api.searchPage,params
},);

(3)搜索内容组件SearchContent.vue

<template><a-spin :spinning="loading"><div class="searchContent"><div v-for="(item,index) in items" :key="index" v-if="!!items.length > 0"><a-card class="contentCard"><template #title><a @click="detailSearch(item.content)"><div class="flex" style="align-items: center"><div><img src="../../assets/images/pdf.png" v-if="item?.content?.fileType=='pdf'" style="width: 20px"/><img src="../../assets/images/word.png" v-if="item?.content?.fileType=='word'" style="width: 20px"/><img src="../../assets/images/excel.png" v-if="item?.content?.fileType=='excel'" style="width: 20px"/></div><div style="margin-left:10px"><article class="article" v-html="item.highlightFields.fileName"v-if="item?.highlightFields?.fileName"></article><span v-else>{{ item?.content?.fileName }}</span></div></div></a></template><div class="item"><article class="article" v-html="item.highlightFields.fileContent"v-if="item?.highlightFields?.fileContent"></article><span v-else>{{item?.content?.fileContent?.length > 150 ? item.content.fileContent.substring(0, 150) + '......' : item.content.fileContent}}</span></div></a-card></div><EmptyData v-else/></div></a-spin>
</template>
<script lang="ts" setup>
import {useGlobSetting} from "@/hooks/setting";
import EmptyData from "/@/components/ElasticSearch/EmptyData.vue";
import {ref} from "vue";const glob = useGlobSetting();const props = defineProps({loading: {type: Boolean,default: false},items: {type: Array,default: []},
})function detailSearch(searchItem) {const url = ref(`${glob.domainUrl}/sys/common/pdf/preview/`);window.open(url.value + searchItem.filePath + '#scrollbars=0&toolbar=0&statusbar=0', '_blank');
}</script>
<style lang="less" scoped>
.searchContent {min-height: 500px;overflow-y: auto;
}.contentCard {margin: 10px 20px;
}a {color: black;
}a:hover {color: #3370ff;
}:deep(.ant-card-body) {padding: 13px;
}
</style>

五、效果展示

相关文章:

Springboot集成ElasticSearch实现minio文件内容全文检索

一、docker安装Elasticsearch &#xff08;1&#xff09;springboot和Elasticsearch的版本对应关系如下&#xff0c;请看版本对应&#xff1a; 注意安装对应版本&#xff0c;否则可能会出现一些未知的错误。 &#xff08;2&#xff09;拉取镜像 docker pull elasticsearch:7…...

ISAAC SIM踩坑记录--ROS2相机影像发布

其实这个例子官方和大佬NVIDIA Omniverse和Isaac Sim笔记5&#xff1a;Isaac Sim的ROS接口与相机影像、位姿真值发布/保存都已经有详细介绍了&#xff0c;但是都是基于ROS的&#xff0c;现在最新的已经是ROS2&#xff0c;这里把不同的地方简单记录一下。 搭建一个简单的场景&a…...

CSS Module:告别类名冲突,拥抱模块化样式(5)

CSS Module 是一种解决 CSS 类名冲突的全新思路。它通过构建工具&#xff08;如 webpack&#xff09;将 CSS 样式切分为更加精细的模块&#xff0c;并在编译时将类名转换为唯一的标识符&#xff0c;从而避免类名冲突。本文将详细介绍 CSS Module 的实现原理和使用方法。 1. 思…...

JavaSE常用API-日期(计算两个日期时间差-高考倒计时)

计算两个日期时间差&#xff08;高考倒计时&#xff09; JDK8之前日期、时间 Date SimpleDateFormat Calender JDK8开始日期、时间 LocalDate/LocalTime/LocalDateTime ZoneId/ZoneDateTIme Instant-时间毫秒值 DateTimeFormatter Duration/Period...

AutoDL上进行tensorboard可视化

1.下载SSH隧道工具 输入ssh指令、ssh密码、代理到本地端口、代理到远程端口 2.在实例中执行&#xff1a;export https_proxyhttp://127.0.0.1:1080 3.在实例中执行&#xff1a;tensorboard --port 6006 --logdir work_dirs 4.打开 http://localhost:6006/ 即可...

20.UE5UI预构造,开始菜单,事件分发器

2-22 开始菜单、事件分发器、UI预构造_哔哩哔哩_bilibili 目录 1.UI预构造 2.开始菜单和开始关卡 2.1开始菜单 2.2开始关卡 2.3将开始菜单展示到开始关卡 3.事件分发器 1.UI预构造 如果我们直接再画布上设计我们的按钮&#xff0c;我们需要为每一个按钮进行编辑&#x…...

【C语言指南】C语言内存管理 深度解析

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C语言指南》 期待您的关注 引言 C语言是一种强大而灵活的编程语言&#xff0c;为程序员提供了对内存的直接控制能力。这种对内存…...

前海华海金融创新中心的工地餐点探寻

​前海的工地餐大部分都是13元一份的哈。我在前海华海金融创新中心的工地餐点吃过一份猪杂饭&#xff0c;现做13元一份。我一般打包后回公司吃或直接桂湾公园找个环境优美的地方吃饭。 ​我点的这份猪杂汤粉主要是瘦肉、猪肝、肉饼片、豆芽和生菜&#xff0c;老板依旧贴心问需要…...

索引及练习

1.索引 &#x1f4d6;什么是索引&#xff1f; 1. 索引是对数据库一列或者多列的值进行排序的一种结构。 2. 索引的建立会大大提高 mysql 的检索速度。 3. 如果想高效的使用 mysql, 而且数据量大时&#xff0c;需要花费事件去设计索引&#xff0c;建立优秀的索引规 则&a…...

java版嘎嘎快充汽车单车充电系统源码系统jeecgboot

汽车使用云快充1.6 1.5协议&#xff0c;单车用的铁塔协议 前端uniapp、后端jeecgbootvue2...

vueRouter路由切换时实现页面子元素动画效果, 左右两侧滑入滑出效果

说明 vue路由切换时&#xff0c;当前页面左侧和右侧容器分别从两侧滑出&#xff0c;新页面左右分别从两侧滑入 效果展示 路由切换-滑入滑出效果 难点和踩坑 现路由和新路由始终存在一个页面根容器&#xff0c;通过<transition>组件&#xff0c;效果只能对页面根容器有效…...

MacOS编译hello_xr——记一次CMake搜索路径限制导致的ANDROID_NATIVE_APP_GLUE not found

首先,由于之前使用过Unity, 系统已经装好了android SDK和NDK, 所以在hello_xr文件夹下, 用local.properties文件来设置系统中二者的路径: sdk.dir/Applications/Unity/Hub/Editor/2022.3.48f1c1/PlaybackEngines/AndroidPlayer/SDK/ # ndk.dir/Applications/Unity/Hub/Editor/…...

基于NI Vision和MATLAB的图像颜色识别与透视变换

1. 任务概述 利用LabVIEW的NI Vision模块读取图片&#xff0c;对图像中具有特征颜色的部分进行识别&#xff0c;并对识别的颜色区域进行标记。接着&#xff0c;通过图像处理算法检测图像的四个顶点&#xff08;左上、左下、右上、右下&#xff09;&#xff0c;并识别每个顶点周…...

【Linux:IO多路复用(select、poll函数)

目录 什么是IO多路复用&#xff1f; select: 参数介绍&#xff1a; select函数返回值&#xff1a; fd_set类型&#xff1a; 内核如何更新集合中的标志位 处理并发问题 处理流程的步骤&#xff1a; poll: poll的函数原型&#xff1a; 参数介绍&#xff1a; select与p…...

计数排序(C语言)

一、步骤 1.首先&#xff0c;遍历数组统计出相同元素出现的次数 2.根据统计的结果将序列收回到原来的数组 方法&#xff1a;我们可以建立一个临时数组用来存储元素出现的次数&#xff0c;然后用该数组的下标表示该元素&#xff08;即假设i为临时数组的下标&#xff0c;a[i]为…...

LabVIEW弧焊参数测控系统

在现代制造业中&#xff0c;焊接技术作为关键的生产工艺之一&#xff0c;其质量直接影响到最终产品的性能与稳定性。焊接过程中&#xff0c;电流、电压等焊接参数的精确控制是保证焊接质量的核心。基于LabVIEW开发的弧焊参数测控系统&#xff0c;通过实时监控和控制焊接过程中关…...

Android笔记(三十七):封装一个RecyclerView Item曝光工具——用于埋点上报

背景 项目中首页列表页需要统计每个item的曝光情况&#xff0c;给产品运营提供数据报表分析用户行为&#xff0c;于是封装了一个通用的列表Item曝光工具&#xff0c;方便曝光埋点上报 源码分析 核心就是监听RecyclerView的滚动&#xff0c;在滚动状态为SCROLL_STATE_IDLE的时…...

【Linux】内核模版加载modprobe | lsmod

modprobe modprobe 是一个用于加载和卸载 Linux 内核模块的命令。它不仅能够加载单个模块&#xff0c;还能处理模块之间的依赖关系&#xff0c;确保所有依赖的模块都被正确加载。以下是一些关于 modprobe 命令的基本用法和常见选项的详细介绍。 基本语法 modprobe [option…...

Android从Drawable资源Id直接生成Bitmap,Kotlin

Android从Drawable资源Id直接生成Bitmap,Kotlin val t1 System.currentTimeMillis()val bmp getBmpFromDrawId(this, R.mipmap.ic_launcher_round)Log.d("fly", "1 ${bmp?.byteCount} h${bmp?.height} w${bmp?.width} cost time${System.currentTimeMillis…...

蓝桥杯——数组

1、移动数组元素 package day3;import java.util.Arrays;public class Demo1 {public static void main(String[] args) {int[] arr {1,2,3,4,5,6};int k 2;int[] arr_new f(arr,k);for (int i : arr_new) {System.out.print(i",");}//或System.out.println();St…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...