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 (1)springboot和Elasticsearch的版本对应关系如下,请看版本对应: 注意安装对应版本,否则可能会出现一些未知的错误。 (2)拉取镜像 docker pull elasticsearch:7…...

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

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

JavaSE常用API-日期(计算两个日期时间差-高考倒计时)
计算两个日期时间差(高考倒计时) JDK8之前日期、时间 Date SimpleDateFormat Calender JDK8开始日期、时间 LocalDate/LocalTime/LocalDateTime ZoneId/ZoneDateTIme Instant-时间毫秒值 DateTimeFormatter Duration/Period...

AutoDL上进行tensorboard可视化
1.下载SSH隧道工具 输入ssh指令、ssh密码、代理到本地端口、代理到远程端口 2.在实例中执行:export https_proxyhttp://127.0.0.1:1080 3.在实例中执行: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预构造 如果我们直接再画布上设计我们的按钮,我们需要为每一个按钮进行编辑&#x…...

【C语言指南】C语言内存管理 深度解析
💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《C语言指南》 期待您的关注 引言 C语言是一种强大而灵活的编程语言,为程序员提供了对内存的直接控制能力。这种对内存…...

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

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

java版嘎嘎快充汽车单车充电系统源码系统jeecgboot
汽车使用云快充1.6 1.5协议,单车用的铁塔协议 前端uniapp、后端jeecgbootvue2...

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

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模块读取图片,对图像中具有特征颜色的部分进行识别,并对识别的颜色区域进行标记。接着,通过图像处理算法检测图像的四个顶点(左上、左下、右上、右下),并识别每个顶点周…...

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

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

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

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

【Linux】内核模版加载modprobe | lsmod
modprobe modprobe 是一个用于加载和卸载 Linux 内核模块的命令。它不仅能够加载单个模块,还能处理模块之间的依赖关系,确保所有依赖的模块都被正确加载。以下是一些关于 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中,如果你想禁用侧滑返回功能,你可以使用WillPopScope小部件,并在onWillPop回调中返回false来阻止用户通过侧滑返回到上一个页面。 class DisableSwipePop extends StatelessWidget {overrideWidget build(BuildContext context) {…...

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

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

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

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

docker 部署freeswitch(非编译方式)
一:安装部署 1.拉取镜像 参考: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(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。 公共事件分类 公共事件从系统角度可分为:系统公共事件和自定义公共事件。 系统公共事件&#…...

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

低成本出租屋5G CPE解决方案:ZX7981PG/ZX7981PM WIFI6千兆高速网络
刚搬进新租的房子,没有网络,开个热点?续航不太行。随身WIFI?大多是百兆级网络。找人拉宽带?太麻烦,退租的时候也不能带着走。5G CPE倒是个不错的选择,插入SIM卡就能直接连接5G网络,千…...

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