资讯动态

基于若依框架的无人机智慧巡检后端源码设计与实现

发布时间:2026/10/27 23:00:54 来源:尧图企业网站定制
简介这份源码是面向无人机智慧巡检场景的后端系统完整实现基于轻量级、易扩展的若依框架与Java语言构建适合具备一定Java与Spring开发基础、希望研究行业级后端架构的开发者参考。系统围绕实时视频流检测报警、报表数据查看与大屏可视化展示三大核心功能展开可应用于电力巡检、农业监测、城市规划等无人机作业领域。压缩包共405个文件约11.3MB以333个Java源文件为主体承载业务逻辑辅以29个XML与3个YAML配置文件、14个VM模板文件另有PNG、JPG、JPEG等界面与大屏视觉素材以及数据库脚本、proto协议文件与readme说明整体呈现前后端分离、模块化与可配置的设计思路。目前已有363人学习下载。通过研读其目录结构与代码组织读者可掌握若依框架下巡检后端的搭建方式、实时数据处理与可视化展示的实现路径并获得一套可直接借鉴的行业后端解决方案。1. 若依框架做无人机智慧巡检后端这套源码到底解决什么问题拿到「基于若依框架的无人机智慧巡检后端设计源码」这个题目时我第一反应不是去翻代码而是先想清楚一件事无人机巡检这条链路里后端到底卡在哪。真实场景是这样的——一架四轴无人机按航线飞完一段输电线路或光伏区机载相机拍回几百张带 GPS 坐标的图落地后这些图要入库、要按航段归档、要跑缺陷识别、要生成巡检报告、要能在地图上回放飞行轨迹。如果每个环节都靠人工拷卡、Excel 登记、微信传图一个班组一天处理不完一个架次。这套后端要干的就是把「飞行任务下发 → 媒体回传归档 → AI 识别 → 缺陷工单 → 报告导出」串成一条可查询、可追溯的数据流水线。若依RuoYi在这里的价值不是它多先进而是它把 RBAC 权限、菜单、部门、字典、操作日志、代码生成器这些「每个管理系统都要写一遍」的东西提前给好了。巡检系统天然是多角色协作飞手、审核员、检修班组、管理员权限颗粒度要求高用若依能省掉至少两周的权限模块开发。这套源码适合两类人一是手里有巡检业务、想快速搭出可用后端的团队二是想拿一个真实业务练若依二次开发的 Java 后端。下面我按「先立住架构、再动手复现、最后讲坑」的顺序拆开讲。2. 巡检后端的分层架构与若依二次开发边界2.1 为什么选若依而不是从零搭 Spring Boot从零搭一个 Spring Boot 后端权限、日志、代码生成这些基础设施至少要写三到五周而且很容易在 RBAC 的数据模型上反复返工。若依已经把用户、角色、菜单、部门、岗位、字典、参数配置、操作日志、登录日志这套做完了还带一个能根据数据库表反向生成 Controller/Service/Mapper/Vue 页面的代码生成器。对巡检这种「业务表多、CRUD 密集」的系统代码生成器能省掉大量重复劳动。但要注意边界若依是「后台管理框架」不是「业务中台」。它擅长的是管理端 CRUD 和权限不擅长高并发媒体处理、实时消息、大文件流式上传。所以我的做法是——把若依当管理后台的底座把巡检核心业务任务调度、媒体处理、AI 推理调用拆成独立模块通过接口和若依主应用解耦。这样既吃到若依的权限红利又不会被它的单体结构拖住。2.2 分层结构与模块划分我一般把巡检后端分成四层对应到若依的多模块结构里层职责对应若依模块典型类接入层鉴权、参数校验、限流ruoyi-adminController业务层任务、航线、媒体、缺陷、工单ruoyi-inspectionService领域层巡检领域模型、状态机ruoyi-inspection-domainEntity/Enum基础设施层存储、消息、AI 调用ruoyi-common 自建Mapper/Client关键设计点是巡检任务的状态机。一个任务从「待下发」到「已完成」要经过待下发 → 已下发 → 飞行中 → 待归档 → 识别中 → 待审核 → 已完成中间还可能进「异常」「已取消」。这个状态机不要写在 Controller 里要单独抽一个InspectionTaskStateMachine用枚举 转移表控制否则后面加一个「复飞」状态就会到处改 if-else。2.3 数据库表设计的最小集合巡检业务的核心表我一般先建这几张其余用代码生成器补-- 巡检任务表 CREATE TABLE inspection_task ( task_id BIGINT NOT NULL AUTO_INCREMENT COMMENT 任务ID, task_code VARCHAR(64) NOT NULL COMMENT 任务编号, route_id BIGINT NOT NULL COMMENT 航线ID, drone_sn VARCHAR(64) DEFAULT NULL COMMENT 无人机序列号, pilot_id BIGINT DEFAULT NULL COMMENT 飞手用户ID, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待下发 1已下发 2飞行中 3待归档 4识别中 5待审核 6已完成 9异常, plan_start DATETIME DEFAULT NULL COMMENT 计划开始时间, actual_start DATETIME DEFAULT NULL COMMENT 实际开始时间, actual_end DATETIME DEFAULT NULL COMMENT 实际结束时间, del_flag CHAR(1) DEFAULT 0 COMMENT 删除标志, create_by VARCHAR(64) DEFAULT COMMENT 创建者, create_time DATETIME DEFAULT NULL COMMENT 创建时间, PRIMARY KEY (task_id), UNIQUE KEY uk_task_code (task_code), KEY idx_status (status) ) ENGINEInnoDB COMMENT巡检任务表; -- 巡检媒体表 CREATE TABLE inspection_media ( media_id BIGINT NOT NULL AUTO_INCREMENT COMMENT 媒体ID, task_id BIGINT NOT NULL COMMENT 任务ID, media_type TINYINT NOT NULL COMMENT 1图片 2视频, file_path VARCHAR(512) NOT NULL COMMENT 存储路径, longitude DECIMAL(10,7) DEFAULT NULL COMMENT 经度, latitude DECIMAL(10,7) DEFAULT NULL COMMENT 纬度, altitude DECIMAL(8,2) DEFAULT NULL COMMENT 海拔, shoot_time DATETIME DEFAULT NULL COMMENT 拍摄时间, ai_status TINYINT NOT NULL DEFAULT 0 COMMENT 0未识别 1识别中 2已识别 3识别失败, PRIMARY KEY (media_id), KEY idx_task (task_id) ) ENGINEInnoDB COMMENT巡检媒体表;inspection_task的status用 TINYINT 而不是字符串是为了索引效率和状态机判断inspection_media把经纬度单独存字段而不是塞进 JSON是因为后面要按地理范围查「某段线路的所有缺陷图」JSON 字段没法走空间索引。ai_status独立于任务状态是因为一个任务下几百张图识别是逐张推进的任务级状态和媒体级状态必须分开。3. 从若依代码生成器到巡检业务接口的落地步骤3.1 用代码生成器生成基础 CRUD若依的代码生成器在「系统工具 → 代码生成」里导入上面建好的表配置好字段类型和查询方式就能生成一套 Controller/Service/Mapper/XML 和前端页面。生成前有几个配置必须改对实体类名InspectionTask不要用默认的InspectionTask加表前缀。字段的「查询方式」task_code选LIKEstatus选EQplan_start选BETWEEN。「显示类型」status选下拉框字典类型填inspection_task_status这样前端自动渲染成状态标签。生成后先别急着改跑一遍确认增删改查通再动业务逻辑。这一步的产物是「能跑的骨架」不是「能用的系统」。3.2 任务下发接口的实现任务下发不是简单改个状态它要校验航线是否存在、无人机是否可用、飞手是否有资质然后推一条消息给调度服务。核心代码如下PreAuthorize(ss.hasPermi(inspection:task:dispatch)) Log(title 巡检任务, businessType BusinessType.UPDATE) PostMapping(/dispatch/{taskId}) public AjaxResult dispatch(PathVariable Long taskId) { InspectionTask task inspectionTaskService.selectById(taskId); // 1. 状态校验只有待下发状态能下发 if (!TaskStatusEnum.PENDING_DISPATCH.getCode().equals(task.getStatus())) { return AjaxResult.error(当前任务状态不允许下发); } // 2. 航线与无人机可用性校验 Route route routeService.selectById(task.getRouteId()); if (route null || !0.equals(route.getStatus())) { return AjaxResult.error(航线不存在或已停用); } Drone drone droneService.selectBySn(task.getDroneSn()); if (drone null || drone.getStatus() ! 1) { return AjaxResult.error(无人机不可用); } // 3. 状态机推进 推送调度消息 taskStateMachine.fire(task, TaskEvent.DISPATCH); inspectionTaskService.updateById(task); mqProducer.send(inspection.dispatch, buildDispatchMsg(task, route)); return AjaxResult.success(下发成功); }PreAuthorize用的是若依内置的权限校验表达式ss.hasPermi会去查当前用户的权限集合这是若依权限体系的标准用法不要自己另写一套。taskStateMachine.fire是前面说的状态机把「校验通过后该转到哪个状态」这件事收敛到一处。mqProducer.send是异步推送下发接口本身不等待无人机响应避免接口超时。3.3 媒体回传与归档媒体回传有两种模式无人机落地后批量上传或飞行中通过图传链路实时回传。批量上传用若依的文件上传组件改造即可关键是上传后要解析 EXIF 拿到经纬度和拍摄时间写入inspection_media。实时回传则要走独立的 WebSocket 或 MQTT 通道不要塞进若依的 HTTP 接口。public void handleMediaUpload(MultipartFile file, Long taskId) { String path fileService.upload(file); MediaMeta meta exifParser.parse(file); // 解析EXIF InspectionMedia media new InspectionMedia(); media.setTaskId(taskId); media.setFilePath(path); media.setLongitude(meta.getLongitude()); media.setLatitude(meta.getLatitude()); media.setShootTime(meta.getShootTime()); media.setAiStatus(0); inspectionMediaService.insert(media); // 触发异步识别 aiTaskExecutor.submit(() - aiClient.recognize(media.getMediaId(), path)); }exifParser要处理一个现实问题部分无人机导出的图 EXIF 里 GPS 是度分秒格式有的是十进制解析时要统一转成十进制存储否则地图上打点会偏。aiTaskExecutor用独立线程池不要用若依默认的ThreadPoolTaskExecutor因为识别任务耗时长会拖垮其他异步任务。4. 巡检后端避坑5 个我踩过的真实问题4.1 现象任务列表查询越来越慢翻到第 10 页要 3 秒原因inspection_task表数据量到几十万后若依默认的分页查询在status和create_time上没有合适索引全表扫描。解决给status、create_time、task_code建组合索引并且把「已删除」的数据用del_flag过滤掉后单独归档到历史表主表只留近半年的活跃任务。4.2 现象媒体上传到 200MB 以上就失败原因若依默认的spring.servlet.multipart.max-file-size是 10MB且 Nginx 的client_max_body_size默认 1MB。解决两处都要改Spring 侧调到 500MBNginx 侧调到 512MB同时把上传接口改成流式写入而不是先读进内存否则大文件会把 JVM 堆打满。4.3 现象AI 识别结果和图片对不上张冠李戴原因异步识别任务用了共享的mediaId变量多线程下被覆盖。解决识别任务提交时把mediaId和filePath作为不可变参数传入不要在 lambda 里引用外部可变变量。这个坑很隐蔽因为单张测试永远正常批量跑才暴露。4.4 现象飞手只能看到自己的任务但审核员看不到任何任务原因若依的数据权限默认按部门隔离审核员和飞手不在同一部门时审核员查不到数据。解决在DataScope注解上给审核员角色配置「全部数据权限」或者自定义数据权限切面按「任务参与人」而不是「部门」过滤。巡检业务的数据权限维度是「人」不是「部门」这点和若依默认假设不同。4.5 现象任务状态偶尔卡在「识别中」不动原因AI 识别服务超时或抛异常后没有回写ai_status媒体永远停在「识别中」。解决识别任务加超时兜底超过 5 分钟未回调的定时任务扫描出来标记为「识别失败」并告警。任何异步链路都要有「失败回写」和「超时兜底」这是血泪经验。5. 让巡检后端真正可用的两个进阶技巧5.1 用状态机 事件表做全链路可追溯巡检系统最怕的是「这张图到底是谁在什么时候识别出缺陷的」说不清。我的做法是在状态机每次fire时往inspection_task_event表写一条事件记录任务ID、事件类型、操作人、时间、备注。这样任何一个任务的全生命周期都能查出来出问题时有「后悔药」。这张表只增不改数据量大了按月分表。public void fire(InspectionTask task, TaskEvent event) { TaskStatusEnum from TaskStatusEnum.of(task.getStatus()); TaskStatusEnum to transitionTable.get(from, event); if (to null) { throw new BizException(非法状态转移: from - event); } task.setStatus(to.getCode()); eventService.record(task.getTaskId(), event, SecurityUtils.getUsername()); }transitionTable用MapPairStatus,Event, Status初始化所有合法转移集中定义新增状态只改这一处。eventService.record里拿当前登录用户用若依的SecurityUtils不要自己从 ThreadLocal 取。5.2 巡检报告的异步导出与断点续传巡检报告通常要汇总一个任务下所有媒体、缺陷、工单生成 PDF 或 Excel。同步生成会超时我的做法是导出请求先落一条export_job记录返回 jobId前端轮询进度后端用独立线程池生成生成过程中每完成 10% 更新一次进度文件生成后存到对象存储返回下载链接。如果生成中途服务重启job 状态停在「生成中」启动时扫描超过 30 分钟的 job 标记为失败并允许重试。这套机制不复杂但没有它运维会被「报告导不出来」的电话打爆。最后说个习惯我做完任何一个若依二次开发项目都会先把代码生成器生成的原始代码和手写业务代码用不同包名隔开比如com.xxx.inspection.generated和com.xxx.inspection.biz。这样下次若依升级或重新生成代码时不会覆盖掉手写的业务逻辑。这个习惯帮我省过至少两次大返工。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑