当前位置: 首页 > 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…...

在Flutter中,禁止侧滑的方法

在Flutter中&#xff0c;如果你想禁用侧滑返回功能&#xff0c;你可以使用WillPopScope小部件&#xff0c;并在onWillPop回调中返回false来阻止用户通过侧滑返回到上一个页面。 class DisableSwipePop extends StatelessWidget {overrideWidget build(BuildContext context) {…...

黑盒测试案例设计方法的使用(1)

黑盒测试用例的设计是确保软件质量的关键步骤之一。 一、等价类划分法 定义&#xff1a;把所有可能的输入数据&#xff0c;即程序的输入域划分成若干部分&#xff08;子集&#xff09;&#xff0c;然后从每一个子集中选取少数具有代表性的数据作为测试用例。 步骤&#xff1a…...

第二十一章 TCP 客户端 服务器通信 - 客户端OPEN命令

文章目录 第二十一章 TCP 客户端 服务器通信 - 客户端OPEN命令客户端OPEN命令 第二十一章 TCP 客户端 服务器通信 - 客户端OPEN命令 客户端OPEN命令 客户端OPEN命令与服务器端OPEN命令只有一个方面的不同&#xff1a;第一个设备参数必须指定要连接的主机。要指定主机&#xf…...

pycharm报错:no module named cv2.cv2

1、问题概述&#xff1f; 在项目中报错no module named cv2.cv2&#xff0c;就会导致import cv2 as cv无法使用。 需要安装opencv-python,一个开源的计算机视觉库。 2、解决办法&#xff1f; 【第一步&#xff1a;如果当前环境中已经安装&#xff0c;先卸载】 有时候会出现…...

Android音视频直播低延迟探究之:WLAN低延迟模式

Android WLAN低延迟模式 Android WLAN低延迟模式是 Android 10 引入的一种功能&#xff0c;允许对延迟敏感的应用将 Wi-Fi 配置为低延迟模式&#xff0c;以减少网络延迟&#xff0c;启动条件如下&#xff1a; Wi-Fi 已启用且设备可以访问互联网。应用已创建并获得 Wi-Fi 锁&a…...

docker 部署freeswitch(非编译方式)

一&#xff1a;安装部署 1.拉取镜像 参考&#xff1a;https://hub.docker.com/r/safarov/freeswitch docker pull safarov/freeswitch 2.启动镜像 docker run --nethost --name freeswitch \-e SOUND_RATES8000:16000 \-e SOUND_TYPESmusic:en-us-callie \-v /home/xx/f…...

OpenHarmony的公共事件

OpenHarmony的公共事件 公共事件简介 CES&#xff08;Common Event Service&#xff0c;公共事件服务&#xff09;为应用程序提供订阅、发布、退订公共事件的能力。 公共事件分类 公共事件从系统角度可分为&#xff1a;系统公共事件和自定义公共事件。 系统公共事件&#…...

深度学习transformer

Transformer可是深度学习领域的一个大热门呢&#xff01;它是一个基于自注意力的序列到序列模型&#xff0c;最初由Vaswani等人在2017年提出&#xff0c;主要用于解决自然语言处理&#xff08;NLP&#xff09;领域的任务&#xff0c;比如机器翻译、文本生成这些。它厉害的地方在…...

低成本出租屋5G CPE解决方案:ZX7981PG/ZX7981PM WIFI6千兆高速网络

刚搬进新租的房子&#xff0c;没有网络&#xff0c;开个热点&#xff1f;续航不太行。随身WIFI&#xff1f;大多是百兆级网络。找人拉宽带&#xff1f;太麻烦&#xff0c;退租的时候也不能带着走。5G CPE倒是个不错的选择&#xff0c;插入SIM卡就能直接连接5G网络&#xff0c;千…...

【黑马点评debug日记】redis登录跳转不成功

登录后一直跳转登录界面&#xff1b; debug: 网络日志报401&#xff0c; 说明前端获取的token为空&#xff1b; 查看应用程序&#xff0c; 发现没有token存储信息 前端网页增加 sessionStorage.setItem("token", data); 记得刷新网页 成功存储token...