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

springboot整合MeiliSearch轻量级搜索引擎

一、Meilisearch与Easy Search点击进入官网了解,本文主要从小微型公司业务出发,选择meilisearch来作为项目的全文搜索引擎,还可以当成来mongodb来使用。

二、starter封装

1、项目结构展示

2、引入依赖包

    <dependencies><dependency><groupId>cn.iocoder.boot</groupId><artifactId>yudao-common</artifactId></dependency><!-- meilisearch 轻量级搜索       --><!-- https://mvnrepository.com/artifact/com.meilisearch.sdk/meilisearch-java --><dependency><groupId>com.meilisearch.sdk</groupId><artifactId>meilisearch-java</artifactId><version>0.11.2</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.40</version><scope>provided</scope></dependency><!-- Web 相关 --><dependency><groupId>cn.iocoder.boot</groupId><artifactId>yudao-spring-boot-starter-web</artifactId><scope>provided</scope> <!-- 设置为 provided,只有 OncePerRequestFilter 使用到 --></dependency></dependencies>

3、yml参数读取代码参考

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;/*** MeiliSearch 自动装配参数类* 2023年9月21日*/
@ConfigurationProperties("yudao.meilisearch")
@Data
@Validated
public class MeiliSearchProperties {/*** 主机地址*/private String hostUrl = "";/*** 接口访问标识*/private String apiKey = "123456";}

4、自动配置类代码参考

import com.meilisearch.sdk.Client;
import com.meilisearch.sdk.Config;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;import javax.annotation.Resource;/*** MeiliSearch 自动装配类* 2023年9月21日*/
@AutoConfiguration
@EnableConfigurationProperties({MeiliSearchProperties.class})
@EnableCaching
public class MeiliSearchAutoConfiguration {@ResourceMeiliSearchProperties properties;@Bean@ConditionalOnMissingBean(Client.class)Client client() {return new Client(config());}@Bean@ConditionalOnMissingBean(Config.class)Config config() {return new Config(properties.getHostUrl(), properties.getApiKey());}}

5、数据处理类参考

import com.meilisearch.sdk.json.GsonJsonHandler;import java.util.List;/*** MeiliSearch json解析类* 2023年9月21日*/
public class JsonHandler {private com.meilisearch.sdk.json.JsonHandler jsonHandler = new GsonJsonHandler();public <T> SearchResult<T> resultDecode(String o, Class<T> clazz) {Object result = null;try {result = jsonHandler.decode(o, SearchResult.class, clazz);} catch (Exception e) {e.printStackTrace();}return result == null ? null : (SearchResult<T>) result;}public <T> List<T> listDecode(Object o, Class<T> clazz) {Object list = null;try {list = jsonHandler.decode(o, List.class, clazz);} catch (Exception e) {e.printStackTrace();}return list == null ? null : (List<T>) list;}public String encode(Object o) {try {return jsonHandler.encode(o);} catch (Exception e) {e.printStackTrace();return null;}}public <T> T decode(Object o, Class<T> clazz) {T t = null;try {t = jsonHandler.decode(o, clazz);} catch (Exception e) {e.printStackTrace();}return t;}
}import java.util.List;
import java.util.Map;/*** MeiliSearch* 2023年9月21日*/
public class MatchedBean<T> {private T _formatted;private Map<String, List<Matching>> _matchesInfo;public T get_formatted() {return _formatted;}public void set_formatted(T _formatted) {this._formatted = _formatted;}public Map<String, List<Matching>> get_matchesInfo() {return _matchesInfo;}public void set_matchesInfo(Map<String, List<Matching>> _matchesInfo) {this._matchesInfo = _matchesInfo;}private class Matching {long start;long length;public long getStart() {return start;}public void setStart(long start) {this.start = start;}public long getLength() {return length;}public void setLength(long length) {this.length = length;}}
}import java.util.List;/*** MeiliSearch* 2023年9月21日*/
public class SearchResult<T> {private String query;private long offset;private long limit;private long processingTimeMs;private long nbHits;private boolean exhaustiveNbHits;private List<T> hits;public String getQuery() {return query;}public void setQuery(String query) {this.query = query;}public long getOffset() {return offset;}public void setOffset(long offset) {this.offset = offset;}public long getLimit() {return limit;}public void setLimit(long limit) {this.limit = limit;}public long getProcessingTimeMs() {return processingTimeMs;}public void setProcessingTimeMs(long processingTimeMs) {this.processingTimeMs = processingTimeMs;}public long getNbHits() {return nbHits;}public void setNbHits(long nbHits) {this.nbHits = nbHits;}public boolean isExhaustiveNbHits() {return exhaustiveNbHits;}public void setExhaustiveNbHits(boolean exhaustiveNbHits) {this.exhaustiveNbHits = exhaustiveNbHits;}public List<T> getHits() {return hits;}public void setHits(List<T> hits) {this.hits = hits;}@Overridepublic String toString() {return "SearchResult{" +"query='" + query + '\'' +", offset=" + offset +", limit=" + limit +", processingTimeMs=" + processingTimeMs +", nbHits=" + nbHits +", exhaustiveNbHits=" + exhaustiveNbHits +", hits=" + hits +'}';}
}

6、自定义注解代码参考

import java.lang.annotation.*;/*** MeiliSearch* 2023年9月21日*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MSFiled {/*** 是否开启过滤*/boolean openFilter() default false;/*** 是否不展示*/boolean noDisplayed() default false;/*** 是否开启排序*/boolean openSort() default false;/***  处理的字段名*/String key() ;
}import java.lang.annotation.*;/*** MeiliSearch* 2023年9月21日*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MSIndex {/*** 索引*/String uid() default "";/*** 主键*/String primaryKey() default "";/*** 分类最大数量*/int maxValuesPerFacet() default 100;/***  单次查询最大数量*/int maxTotalHits() default 1000;
}

7、基础操作接口封装

import cn.iocoder.yudao.framework.meilisearch.json.SearchResult;
import com.meilisearch.sdk.SearchRequest;
import com.meilisearch.sdk.model.Settings;
import com.meilisearch.sdk.model.Task;
import com.meilisearch.sdk.model.TaskInfo;import java.util.List;/*** MeiliSearch 基础接口* 2023年9月21日*/
interface DocumentOperations<T> {T get(String identifier);List<T> list();List<T> list(int limit);List<T> list(int offset, int limit);long add(T document);long update(T document);long add(List<T> documents);long update(List<T> documents);long delete(String identifier);long deleteBatch(String... documentsIdentifiers);long deleteAll();SearchResult<T> search(String q);SearchResult<T> search(String q, int offset, int limit);SearchResult<T> search(SearchRequest sr);Settings getSettings();TaskInfo updateSettings(Settings settings);TaskInfo resetSettings();Task getUpdate(int updateId);
}

8、基本操作实现

import cn.iocoder.yudao.framework.meilisearch.json.JsonHandler;
import cn.iocoder.yudao.framework.meilisearch.json.MSFiled;
import cn.iocoder.yudao.framework.meilisearch.json.MSIndex;
import cn.iocoder.yudao.framework.meilisearch.json.SearchResult;
import com.alibaba.fastjson2.JSON;
import com.meilisearch.sdk.*;
import com.meilisearch.sdk.model.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.*;/*** MeiliSearch 基本操作实现* 2023年9月21日*/
public class MeilisearchRepository<T> implements InitializingBean, DocumentOperations<T> {private Index index;private Class<T> tClass;private JsonHandler jsonHandler = new JsonHandler();@Resourceprivate Client client;@Overridepublic T get(String identifier) {T document;try {document = index.getDocument(identifier, tClass);} catch (Exception e) {throw new RuntimeException(e);}return document;}@Overridepublic List<T> list() {List<T> documents;try {documents = Optional.ofNullable(index.getDocuments(tClass)).map(indexDocument -> indexDocument.getResults()).map(result -> Arrays.asList(result)).orElse(new ArrayList<>());} catch (Exception e) {throw new RuntimeException(e);}return documents;}@Overridepublic List<T> list(int limit) {List<T> documents;try {DocumentsQuery query = new DocumentsQuery();query.setLimit(limit);documents = Optional.ofNullable(index.getDocuments(query, tClass)).map(indexDocument -> indexDocument.getResults()).map(result -> Arrays.asList(result)).orElse(new ArrayList<>());} catch (Exception e) {throw new RuntimeException(e);}return documents;}@Overridepublic List<T> list(int offset, int limit) {List<T> documents;try {DocumentsQuery query = new DocumentsQuery();query.setLimit(limit);query.setOffset(offset);documents = Optional.ofNullable(index.getDocuments(query, tClass)).map(indexDocument -> indexDocument.getResults()).map(result -> Arrays.asList(result)).orElse(new ArrayList<>());} catch (Exception e) {throw new RuntimeException(e);}return documents;}@Overridepublic long add(T document) {List<T> list = Collections.singletonList(document);return add(list);}@Overridepublic long update(T document) {List<T> list = Collections.singletonList(document);return update(list);}@Overridepublic long add(List documents) {int taskId;try {taskId = index.addDocuments(JSON.toJSONString(documents)).getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return taskId;}@Overridepublic long update(List documents) {int updates;try {updates = index.updateDocuments(JSON.toJSONString(documents)).getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return updates;}@Overridepublic long delete(String identifier) {int taskId;try {taskId = index.deleteDocument(identifier).getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return taskId;}@Overridepublic long deleteBatch(String... documentsIdentifiers) {int taskId;try {taskId = index.deleteDocuments(Arrays.asList(documentsIdentifiers)).getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return taskId;}@Overridepublic long deleteAll() {int taskId;try {taskId = index.deleteAllDocuments().getTaskUid();} catch (Exception e) {throw new RuntimeException(e);}return taskId;}@Overridepublic cn.iocoder.yudao.framework.meilisearch.json.SearchResult<T> search(String q) {String result;try {result = JSON.toJSONString(index.search(q));} catch (Exception e) {throw new RuntimeException(e);}return jsonHandler.resultDecode(result, tClass);}@Overridepublic cn.iocoder.yudao.framework.meilisearch.json.SearchResult<T> search(String q, int offset, int limit) {SearchRequest searchRequest = SearchRequest.builder().q(q).offset(offset).limit(limit).build();return search(searchRequest);}@Overridepublic SearchResult<T> search(SearchRequest sr) {String result;try {result = JSON.toJSONString(index.search(sr));} catch (Exception e) {throw new RuntimeException(e);}return jsonHandler.resultDecode(result, tClass);}@Overridepublic Settings getSettings() {try {return index.getSettings();} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic TaskInfo updateSettings(Settings settings) {try {return index.updateSettings(settings);} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic TaskInfo resetSettings() {try {return index.resetSettings();} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic Task getUpdate(int updateId) {try {return index.getTask(updateId);} catch (Exception e) {throw new RuntimeException(e);}}@Overridepublic void afterPropertiesSet() throws Exception {initIndex();}public Index getIndex() {return index;}/*** 初始化索引信息** @throws Exception*/private void initIndex() throws Exception {Class<? extends MeilisearchRepository> clazz = getClass();tClass = (Class<T>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];MSIndex annoIndex = tClass.getAnnotation(MSIndex.class);String uid = annoIndex.uid();String primaryKey = annoIndex.primaryKey();if (StringUtils.isEmpty(uid)) {uid = tClass.getSimpleName().toLowerCase();}if (StringUtils.isEmpty(primaryKey)) {primaryKey = "id";}int maxTotalHit=1000;int maxValuesPerFacet=100;if (Objects.nonNull(annoIndex.maxTotalHits())){maxTotalHit=annoIndex.maxTotalHits();}if (Objects.nonNull(annoIndex.maxValuesPerFacet())){maxValuesPerFacet=100;}List<String> filterKey = new ArrayList<>();List<String> sortKey = new ArrayList<>();List<String> noDisPlay = new ArrayList<>();//获取类所有属性for (Field field : tClass.getDeclaredFields()) {//判断是否存在这个注解if (field.isAnnotationPresent(MSFiled.class)) {MSFiled annotation = field.getAnnotation(MSFiled.class);if (annotation.openFilter()) {filterKey.add(annotation.key());}if (annotation.openSort()) {sortKey.add(annotation.key());}if (annotation.noDisplayed()) {noDisPlay.add(annotation.key());}}}Results<Index> indexes = client.getIndexes();Index[] results = indexes.getResults();Boolean isHaveIndex=false;for (Index result : results) {if (uid.equals(result.getUid())){isHaveIndex=true;break;}}if (isHaveIndex){client.updateIndex(uid,primaryKey);this.index = client.getIndex(uid);Settings settings = new Settings();settings.setDisplayedAttributes(noDisPlay.size()>0?noDisPlay.toArray(new String[noDisPlay.size()]):new String[]{"*"});settings.setFilterableAttributes(filterKey.toArray(new String[filterKey.size()]));settings.setSortableAttributes(sortKey.toArray(new String[sortKey.size()]));index.updateSettings(settings);}else {client.createIndex(uid, primaryKey);}}
}

9、指定自动配置类所在

10、项目有统一版本管理的设置下版本管理

二、项目引用

1、引入starter依赖(没有版本统一管理的要把version加上)

2、基本使用

2.1、建立索引(宽表)

import cn.iocoder.yudao.framework.meilisearch.json.MSFiled;
import cn.iocoder.yudao.framework.meilisearch.json.MSIndex;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@MSIndex(uid = "com_baidu_main", primaryKey = "id")
public class MainDO {private Long id;private String seedsName;@MSFiled(openFilter = true, key = "isDelete")private Integer isDelete;@MSFiled(openFilter = true, key = "status")private Integer status;@MSFiled(openFilter = true, key = "classFiledId")private Integer classFiledId;private String classFiledName;@MSFiled(openFilter = true, key = "tags")private List<TageInfo> tags;
}

2.2、集成starter里边的mapper对milisearch进行基本操作

import cn.iocoder.yudao.framework.meilisearch.core.MeilisearchRepository;
import org.springframework.stereotype.Repository;@Repository
public class MeiliSearchMapper extends MeilisearchRepository<MainDO> {
}

2.3、基本使用

@Resource
private MeiliSearchMapper meiliSearchMapper;//根据标签分页查询
SearchRequest searchRequest4 = SearchRequest.builder().limit(pageParam.getPageSize().intValue()).sort(new String[]{"createTime:desc"}).offset(pageParam.getPageNo().intValue() == 0 ? pageParam.getPageNo().intValue() : (pageParam.getPageNo().intValue() - 1) * pageParam.getPageSize().intValue()).filter(new String[]{"tags.id=" + "10010" + " AND status=1 AND isDelete=0"}).build();
SearchResult<MainDO> search4 = meiliSearchMapper.search(searchRequest4);//保存Or编辑
List<SeedsDO> articleCardDTOS = new ArrayList<>();
Boolean aBoolean = meiliSearchMapper.add(articleCardDTOS) > 0 ? Boolean.TRUE : Boolean.FALSE;
//按id删除
meiliSearchMapper.delete(String.valueOf(10085));//根据类目分页查询
SearchRequest searchRequest3 = SearchRequest.builder().limit(pageParam.getPageSize().intValue()).offset(pageParam.getPageNo().intValue() == 0 ? pageParam.getPageNo().intValue() : (pageParam.getPageNo().intValue() - 1) * pageParam.getPageSize().intValue()).build();
StringBuffer sb1 = new StringBuffer();
sb.append("status =1 AND isDelete=0").append(" AND ").append("categoryId =").append(10086L);
searchRequest.setFilter(new String[]{sb.toString()});
searchRequest.setSort(new String[]{"createTime:desc"});
SearchResult<SeedsDO> search3 = meiliSearchMapper.search(searchRequest3);

相关文章:

springboot整合MeiliSearch轻量级搜索引擎

一、Meilisearch与Easy Search点击进入官网了解&#xff0c;本文主要从小微型公司业务出发&#xff0c;选择meilisearch来作为项目的全文搜索引擎&#xff0c;还可以当成来mongodb来使用。 二、starter封装 1、项目结构展示 2、引入依赖包 <dependencies><dependenc…...

禁用鼠标的侧边按键

新买了个鼠标&#xff0c;整体都不错&#xff0c;就是鼠标左侧有两个按键&#xff0c;大拇指经常无意触碰到&#xff0c;造成误操作。 就想着关闭侧边按键功能。以下这批文章帮了大忙&#xff01; 鼠标侧键屏蔽&#xff0c;再也不用担心按到侧键了。_禁用鼠标侧键_挣扎的蓝藻…...

【C语言】数组和指针刷题练习

指针和数组我们已经学习的差不多了&#xff0c;今天就为大家分享一些指针和数组的常见练习题&#xff0c;还包含许多经典面试题哦&#xff01; 一、求数组长度和大小 普通一维数组 int main() {//一维数组int a[] { 1,2,3,4 };printf("%d\n", sizeof(a));//整个数组…...

2023年中国研究生数学建模竞赛D题解题思路

为了更好的帮助大家第一天选题&#xff0c;这里首先为大家带来D题解题思路&#xff0c;分析对应赛题之后做题阶段可能会遇到的各种难点。 稍后会带来D题的详细解析思路&#xff0c;以及相关的其他版本解题思路 成品论文等资料。 赛题难度评估&#xff1a;A、B>C>E、F&g…...

在编译源码的环境下,搭建起Discuz!社区论坛和WordPress博客的LNMP架构

目录 一.编译安装nginx 二.编译安装MySQL 三.编译安装PHP 四.安装论坛 五.安装wordpress博客 六.yum安装LNMP架构&#xff08;简要过程参考&#xff09; 一.编译安装nginx 1&#xff09;关闭防火墙&#xff0c;将安装nginx所需软件包传到/opt目录下 systemctl stop fire…...

腾讯面试题:无网络环境,如何部署Docker镜像?

亲爱的小伙伴们&#xff0c;大家好&#xff01;我是小米&#xff0c;很高兴再次和大家见面。今天&#xff0c;我要和大家聊聊一个特别有趣的话题——腾讯面试题&#xff1a;无网络环境&#xff0c;如何部署Docker镜像&#xff1f;这可是一个技术含量颇高的问题哦&#xff01;废…...

医学影像信息(PACS)系统软件源码

PACS系统是PictureArchivingandCommunicationSystems的缩写&#xff0c;与临床信息系统&#xff08;ClinicalInformationSystem,CIS&#xff09;、放射学信息系统(RadiologyInformationSystem,RIS)、医院信息系统(HospitalInformationSystem,HIS)、实验室信息系统&#xff08;L…...

【01】FISCOBCOS的系统环境安装

我们选择ubuntu系统 01 https://www.ubuntu.org.cn/global 02 03下载最新版 04等待下载 00提前准备好VM&#xff0c;点击创建新的虚拟机 01选择自定义安装 02一直下一步到 03 04 05其他的默认即可 06 07 08 09 10 11一直默认到下面 12 13等待安装 安装后重启即可…...

flutter 权限和图片权限之前的冲突

权限插件 permission_handler: ^9.2.0想调起相册和视频&#xff0c;这个插件只有Permission.storage.request().&#xff0c;获取存储权限。 问题是android 13的一些手机&#xff0c;系统设置没有存储权限&#xff0c;用了上面这个权限&#xff0c;三次拒绝后就永久拒绝了&…...

OpenCV(四十八):读取视频和保存视频

OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个功能强大的开源计算机视觉库&#xff0c;它提供了丰富的功能&#xff0c;包括读取和保存视频。下面分别演示如何使用OpenCV来读取视频和保存视频。 1. 读取视频&#xff1a; 在OpenCV中我们要获取一…...

如何在react/next.js app中的同级组件间传递数据

这篇文章也可以在我的博客中查看 问题 为什么会有这么奇怪的需求&#xff1f;在事情真正发生前真的难说&#xff0c;但真遇到一个需要这么做的情况。 最近想做一个网页时钟&#xff0c;它的结构如下&#xff1a; 时钟&#xff08;计算时间&#xff0c;组织各个要素&#xff…...

软件需求文档、设计文档、开发文档、运维文档大全

在软件开发过程中&#xff0c;文档扮演着至关重要的角色。它不仅记录了项目的需求、设计和开发过程&#xff0c;还为项目的维护和管理提供了便利。本文将详细介绍软件开发文档的重要性和作用&#xff0c;以及需求分析、软件设计、开发过程、运维管理和项目管理等方面的文档要求…...

排序算法-----归并排序

目录 前言&#xff1a; 归并排序 1. 定义 2.算法过程讲解 2.1大致思路 2.2图解示例 拆分合成步骤 ​编辑 相关动态图 3.代码实现&#xff08;C语言&#xff09; 4.算法分析 4.1时间复杂度 4.2空间复杂度 4.3稳定性 前言&#xff1a; 今天我们就开始学习新的排序算法…...

docker 配置 gpu版pytorch环境--部署缺陷检测--Anomalib

目录 一、docker 配置 gpu版pyhorch环境1、显卡驱动、cuda版本、pytorch cuda版本三者对应2、拉取镜像 二、部署Anomalib1、下载Anomalib2、创建容器并且运行3、安装Anomalib进入项目路径安装依赖测试&#xff1a; 一、docker 配置 gpu版pyhorch环境 1、显卡驱动、cuda版本、p…...

为什么定时发朋友圈会更有效呢?

这是因为在同一时段 发送的好友朋友圈 无法有效分散用户的注意力 导致曝光度难以提升 而通过推广定时发朋友圈 可根据自己的粉丝活跃度 设置发圈时间 让每一条朋友圈都能高效 传递到更多的好友手中 这样&#xff0c;曝光度自然而然地就大大提升了&#xff01; 1.多个号…...

【跟小嘉学 PHP 程序设计】一、PHP 开发环境搭建

系列文章目录 【跟小嘉学 PHP 程序设计】一、PHP 开发环境搭建 文章目录 系列文章目录@[TOC](文章目录)前言一、PHP介绍二、Centos 安装 PHP2.1、安装并启动 Nginx2.2、安装并启动 mariadb2.3、安装 rh-php2.4、添加 Nginx 配置2.5、Nginx 服务三、使用 Docker 为 PHP 部署开发…...

【zookeeper】zk选举、使用与三种节点简介,以及基于redis分布式锁的缺点的讨论

这里我准备了4台虚拟机&#xff0c;从node1到node4&#xff0c;其myid也从1到4. 一&#xff0c;zk server的启动和选举 zk需要至少启动3台Server&#xff0c;按照配置的myid&#xff0c;选举出参与选举的myid最大的server为Leader。&#xff08;与redis的master、slave不同&a…...

Unity截图生成图片 图片生成器 一键生成图片

使用Unity编辑器扩展技术实现快速截图功能 效果&#xff1a; 里面没有什么太难的技术&#xff0c;直接上源码吧 注意&#xff01;代码需要放在Editor文件下才能正常运行 using System; using UnityEditor; using UnityEngine;[ExecuteInEditMode] public class Screenshot …...

Matlab图像处理-区域特征

凹凸性 设P是图像子集S中的点&#xff0c;若通过的每条直线只与S相交一次&#xff0c;则称S为发自P的星形&#xff0c;也就是站在P点能看到S的所有点。 满足下列条件之一&#xff0c;称此为凸状的&#xff1a; 1.从S中每点看&#xff0c;S都是星形的&#xff1b; 2.对S中任…...

golang 自动生成文件头

安装koroFileHeader控件 打开首选项&#xff0c;进入设置&#xff0c;配置文件头信息"fileheader.customMade": {"Author": "lmy","Date": "Do not edit", // 文件创建时间(不变)// 文件最后编辑者"LastEditors"…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...