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

使用Spring AI和MCP协议构建图片搜索服务

目录

使用Spring AI和MCP协议构建图片搜索服务

引言

技术栈概览

项目架构设计

架构图

服务端开发

1. 创建Spring Boot项目

2. 实现图片搜索工具

3. 配置传输模式

Stdio模式(本地调用)

SSE模式(远程调用)

4. 注册工具提供者

5. 单元测试

6. 打包服务

客户端开发

1. 引入MCP客户端依赖

2. 配置MCP服务连接

Stdio模式(本地调用)

SSE模式(远程调用)

3. 绑定MCP工具至ChatClient

4. 测试客户端

实现效果展示

Stdio模式测试结果

SSE模式测试结果

对话示例

高级功能扩展

1. 图片过滤功能

2. 图片合成与处理

部署最佳实践

本地部署

远程部署

Serverless部署

性能优化建议

安全性考虑

总结


使用Spring AI和MCP协议构建图片搜索服务

引言

随着大型语言模型(LLM)在各行业的应用不断深入,如何让AI能够获取和处理多模态信息成为了重要课题。图片搜索作为常见的多模态场景,是一个理想的实践案例。本文将详细介绍如何结合Spring AI框架与MCP协议,构建一个功能完整的图片搜索服务,使LLM能够根据用户需求搜索并展示相关图片。

技术栈概览

本项目主要使用以下技术:

  • Spring Boot:提供基础框架支持
  • Spring AI:集成AI能力与MCP协议
  • Pexels API:提供图片搜索功能
  • MCP协议:标准化工具调用接口
  • Hutool:提供HTTP请求等工具支持

项目架构设计

我们将构建的系统分为两部分:

  1. MCP服务端:提供图片搜索功能,对外暴露标准MCP接口
  1. MCP客户端:集成在业务应用中,调用MCP服务并处理结果

架构图

+----------------+      MCP协议      +----------------+      HTTP      +----------------+
|                |  <------------->  |                |  <--------->  |                |
|  应用程序       |                   |  图片搜索       |               |  Pexels API    |
|  (MCP客户端)    |                   |  MCP服务       |               |                |
+----------------+                   +----------------+               +----------------+

服务端开发

1. 创建Spring Boot项目

首先,创建一个Spring Boot项目,并添加必要的依赖:

<!-- Spring AI MCP 服务端 -->
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId><version>1.0.0-M6</version></dependency><!-- HTTP工具库 -->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-http</artifactId><version>5.8.26</version></dependency>

2. 实现图片搜索工具

创建一个核心服务类ImageSearchTool,封装Pexels API的调用:

@Service
public class ImageSearchTool {// 从官网申请获得的Pexels API密钥// 实际应用中应从环境变量或配置中心读取,避免硬编码private static final String API_KEY = "api key";// Pexels 搜索接口URLprivate static final String API_URL = "https://api.pexels.com/v1/search";/*** 提供给MCP协议的图片搜索工具* 使用@Tool注解标记为工具,并提供描述信息* * @param query 搜索关键词* @return 图片URL列表,以逗号分隔*/@Tool(description = "search image from web")public String searchImage(@ToolParam(description = "Search query keyword") String query) {try {return String.join(",", searchMediumImages(query));} catch (Exception e) {return "Error search image: " + e.getMessage();}}/*** 搜索中等尺寸的图片列表** @param query 搜索关键词* @return 图片URL列表*/public List<String> searchMediumImages(String query) {// 设置请求头(包含API密钥)Map<String, String> headers = new HashMap<>();headers.put("Authorization", API_KEY);// 设置请求参数Map<String, Object> params = new HashMap<>();params.put("query", query);// 发送 GET 请求String response = HttpUtil.createGet(API_URL).addHeaders(headers).form(params).execute().body();// 解析响应JSON,提取图片URLreturn JSONUtil.parseObj(response).getJSONArray("photos").stream().map(photoObj -> (JSONObject) photoObj).map(photoObj -> photoObj.getJSONObject("src")).map(photo -> photo.getStr("medium")).filter(StrUtil::isNotBlank).collect(Collectors.toList());}/*** 搜索完整尺寸和更多元数据的图片* 可用于高级场景*/public Map<String, Object> searchImagesWithDetails(String query, int perPage) {Map<String, String> headers = new HashMap<>();headers.put("Authorization", API_KEY);Map<String, Object> params = new HashMap<>();params.put("query", query);params.put("per_page", perPage);String response = HttpUtil.createGet(API_URL).addHeaders(headers).form(params).execute().body();JSONObject result = JSONUtil.parseObj(response);Map<String, Object> resultMap = new HashMap<>();resultMap.put("total_results", result.getInt("total_results"));resultMap.put("page", result.getInt("page"));resultMap.put("per_page", result.getInt("per_page"));List<Map<String, Object>> photos = new ArrayList<>();result.getJSONArray("photos").forEach(photo -> {JSONObject photoObj = (JSONObject) photo;Map<String, Object> photoMap = new HashMap<>();photoMap.put("id", photoObj.getInt("id"));photoMap.put("width", photoObj.getInt("width"));photoMap.put("height", photoObj.getInt("height"));photoMap.put("url", photoObj.getStr("url"));photoMap.put("photographer", photoObj.getStr("photographer"));photoMap.put("medium_url", photoObj.getJSONObject("src").getStr("medium"));photoMap.put("original_url", photoObj.getJSONObject("src").getStr("original"));photos.add(photoMap);});resultMap.put("photos", photos);return resultMap;}
}

3. 配置传输模式

MCP支持两种传输模式:Stdio和SSE。我们需要根据应用场景选择合适的模式:

Stdio模式(本地调用)

适用于本地开发环境或单机部署场景,通过标准输入输出进行通信。

# application.yml
spring:ai:mcp:server:name: image-search-mcp-serverversion: 0.0.1stdio: truemain:web-application-type: none
SSE模式(远程调用)

适用于分布式环境或多客户端共享的生产场景,通过HTTP Server-Sent Events进行通信。

# application.yml
spring:ai:mcp:server:name: image-search-mcp-serverversion: 0.0.1stdio: false
server:port: 8127

两种模式各有优势,可以根据部署环境和使用场景灵活选择:

传输模式

优点

缺点

适用场景

Stdio

简单部署、低延迟

需维护多个服务实例

开发测试、单用户应用

SSE

易共享、可扩展

依赖网络稳定性

生产环境、多用户共享

4. 注册工具提供者

在Spring Boot主类中注册工具提供者:

@SpringBootApplication
public class ImageSearchMcpServerApplication {public static void main(String[] args) {SpringApplication.run(ImageSearchMcpServerApplication.class, args);}@Beanpublic ToolCallbackProvider imageSearchTools(ImageSearchTool imageSearchTool) {return MethodToolCallbackProvider.builder().toolObjects(imageSearchTool).build();}
}

5. 单元测试

创建单元测试验证功能:

@SpringBootTest
public class ImageSearchToolTest {@Resourceprivate ImageSearchTool imageSearchTool;@Testvoid searchImage() {String result = imageSearchTool.searchImage("computer");String[] urlArray = result.split(",");for (int i = 0; i < urlArray.length; i++) {String markdownUrl = "![](" + urlArray[i] + ")";System.out.println(markdownUrl);}}
}

6. 打包服务

使用Maven命令打包MCP服务:

mvn clean package

打包后的JAR文件位于target/image-search-mcp-server-0.0.1-SNAPSHOT.jar

客户端开发

现在我们已经完成了MCP服务端的开发,接下来需要实现客户端,将图片搜索能力集成到AI应用中。

1. 引入MCP客户端依赖

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId><version>1.0.0-M6</version></dependency>

2. 配置MCP服务连接

根据部署方式,选择不同的配置:

Stdio模式(本地调用)

创建resources/mcp-servers.json文件:

{"mcpServers": {"image-search-mcp-server": {"command": "java","args": ["-Dspring.ai.mcp.server.stdio=true","-Dspring.main.web-application-type=none","-Dlogging.pattern.console=","-jar","path/to/image-search-mcp-server-0.0.1-SNAPSHOT.jar"],"env": {}}}
}

application.yml中配置:

spring:ai:mcp:client:stdio:servers-configuration: classpath:mcp-servers.json
SSE模式(远程调用)
spring:ai:mcp:client:sse:connections:server1:url: http://localhost:8127

3. 绑定MCP工具至ChatClient

在AI应用中集成MCP工具:

@Service
@Slf4j
public class AiAssistantService {@Resourceprivate ChatClient chatClient;@Resourceprivate ToolCallbackProvider toolCallbackProvider;public String doChatWithMcp(String message, String chatId) {ChatResponse response = chatClient.prompt().user(message).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))// 开启日志,便于观察效果.advisors(new MyLoggerAdvisor()).tools(toolCallbackProvider).call().chatResponse();String content = response.getResult().getOutput().getText();log.info("content: {}", content);return content;}
}

4. 测试客户端

编写单元测试验证客户端功能:

@SpringBootTest
class AiAssistantServiceTest {@Autowiredprivate AiAssistantService aiAssistantService;@Testvoid doChatWithMcp() {String chatId = UUID.randomUUID().toString();// 测试图片搜索 MCPString message = "帮我搜索一些关于自然风景的图片";String answer = aiAssistantService.doChatWithMcp(message, chatId);System.out.println(answer);assertNotNull(answer);}
}

实现效果展示

成功实现后,系统可以支持以下场景:

  1. 基本图片搜索:用户请求搜索特定主题的图片
  2. 多图搜索:一次返回多张相关图片
  3. 主题识别:理解用户描述的主题并进行相关搜索

Stdio模式测试结果

使用本地Stdio模式运行MCP服务并集成到Spring AI应用中:

SSE模式测试结果

将MCP服务部署为远程HTTP服务并通过SSE方式调用:

对话示例

用户: 帮我搜索一些哄另一半开心的图片AI: 我已经为您搜索了一些可以哄另一半开心的图片,请看:![一对情侣在海滩上](https://images.pexels.com/photos/1574...]
![手捧心形礼物](https://images.pexels.com/photos/3598...]
![浪漫烛光晚餐](https://images.pexels.com/photos/2762...]希望这些图片能帮助您哄另一半开心!

这个示例展示了AI如何理解用户的情感需求,调用图片搜索MCP服务找到合适的图片,并以标准markdown格式返回结果,使图片能够直接在聊天界面上显示。

高级功能扩展

1. 图片过滤功能

扩展服务以支持更多搜索参数:

@Tool(description = "search image with filters")
public String searchImagesWithFilters(@ToolParam(description = "Search query keyword") String query,@ToolParam(description = "Image orientation (landscape/portrait/square)") String orientation,@ToolParam(description = "Image size (large/medium/small)") String size,@ToolParam(description = "Maximum number of images") Integer maxImages
) {// 实现过滤逻辑
}

2. 图片合成与处理

结合其他服务进行图片处理:

@Tool(description = "process and enhance image")
public String enhanceImage(@ToolParam(description = "Image URL to process") String imageUrl,@ToolParam(description = "Enhancement type (brighten/crop/resize)") String enhancementType
) {// 实现图片处理逻辑
}

部署最佳实践

本地部署

适用于开发测试环境:

  • 打包MCP服务JAR文件
  • 配置客户端使用Stdio模式
  • 在客户端启动时自动启动MCP服务

远程部署

适用于生产环境:

  • 将MCP服务部署为独立服务
  • 配置客户端使用SSE模式连接
  • 实现服务健康检查和自动重试

Serverless部署

适用于弹性需求场景:

  • 部署到云函数平台(如阿里云FC)
  • 配置按需自动扩缩容
  • 节约资源成本

性能优化建议

  1. 连接池管理:对HTTP请求使用连接池
  2. 缓存机制:对热门搜索词结果进行缓存
  3. 超时控制:设置合理的API调用超时
  4. 指标监控:加入性能监控指标收集

安全性考虑

  1. API密钥保护:避免硬编码,使用环境变量
  2. 请求验证:验证搜索参数,防止注入攻击
  3. 结果过滤:确保返回内容符合预期
  4. 访问限制:添加调用频率限制

总结

通过Spring AI和MCP协议,我们成功构建了一个功能完整的图片搜索服务,使AI应用能够轻松获取和展示图片资源。这种模式不仅提高了AI的实用性,还为开发者提供了一种标准化、可复用的工具集成方式。

参考资料:

  • Spring AI 官方文档
  • Pexels API 文档
  • MCP 协议规范

作者:lenyan
GitHub:lenyanjgk (lenyanjgk) · GitHub
CSDN:lenyan~-CSDN博客

相关文章:

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

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;用于…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...