☰
基于Spring Boot的无人机农田巡查系统:设计与实现全解析
2026/10/14 7:32:20 网站建设 项目流程

大学毕业设计做完了,回头再看“基于Spring Boot的无人机农田巡查系统设计与实现”这个题目,感触还挺多的。整个过程从选题时的懵懂,到中期被各种技术选型折磨,再到最后把无人机飞控、后台服务和前端地图串起来,这里面的坑和解决方案值得好好整理一下,希望能给正在做类似题目的同学一些参考。

这篇内容主要讲清楚三件事:这个毕业设计核心要解决什么问题、系统整体怎么拆解设计、以及每一个关键模块落地的技术细节和踩坑经验。无论你是刚拿到题目还没思路,还是已经写完一半想优化一下,这篇文章的粒度都够你直接参考。

先说这个系统是干什么的。传统的人工农田巡查效率低,人力成本高,而且巡查结果往往凭经验判断,不够量化。基于Spring Boot的无人机农田巡查系统,核心思路是把无人机变成空中数据采集终端,把后台管理系统变成数据处理和展示中枢。无人机按预设航线在农田上方飞行,拍摄高清照片和多光谱数据,通过网络回传到后端服务,再由后端进行存储、分析、展示,最终生成巡查报告。整个过程覆盖了硬件对接、通信协议、数据管理、算法处理四个层面,非常典型的软硬结合类毕设选题。

这个题目的工作量足够支撑一篇不错的本科毕业设计,而且技术栈非常主流。Spring Boot作为当前Java后端最主流的框架,就业认可度也高。如果你的开题报告还没交,选这个题目方向是比较稳妥的选择。

1. 系统需求分析与功能拆解

做毕设最容易犯的毛病,就是一上来就写代码。我自己的经验是,先把需求用“用户故事”的方式写清楚,再推功能模块。这个系统里面,角色的划分其实很清晰,不同角色能做的事也不一样。

1.1 角色与权限设计

我的系统里面设计了三种角色:管理员、巡查员(飞手)、普通农户。

  • 管理员:负责系统全局配置,管理用户账户、审核巡查任务、查看所有地块和报告数据。
  • 巡查员:负责绑定无人机设备、规划航线、执行飞行任务、上传巡查数据。
  • 普通农户:只能查看自己名下的农田地块和巡查报告,不能操作系统配置。

权限这块我直接用Spring Security的基于角色的访问控制来做。用一个@PreAuthorize("hasRole('ADMIN')")注解标注管理端接口,农户端接口用hasRole('FARMER')控制。前端根据登录返回的角色字段动态渲染菜单,后端再做一层校验,双保险。很多同学觉得权限设计麻烦,后面接一些安全工具改起来更麻烦,所以这里别偷懒。

1.2 核心功能模块划分

功能模块我拆成六大块,这也是本系统的主体结构:

模块名称核心功能涉及主要技术
用户认证模块登录注册、JWT签发、权限校验Spring Security + JWT
地块信息管理农田地块的增删改查、地图可视化MyBatis-Plus + Vue + Leaflet
无人机设备管理设备登记、状态跟踪设备信息表 + 状态枚举
飞行任务管理创建任务、规划航线、指令下发任务状态机 + 航线算法
巡查数据模块照片上传、数据分析、报告生成文件存储 + 图像处理
系统设置字典管理、参数配置Redis缓存 + 基础CRUD

六大模块不是孤立的,它们之间有非常明确的业务流线。巡查员新建一个飞行任务,选择本季需要巡查的农田地块,系统自动根据地块边界生成推荐航线,无人机起飞后拍摄的照片按经纬度标记回传,后端完成拼接和处理,最终生成一份巡查报告推送给农户。

这个闭环就是我说的“一个系统”,而不是六堆CRUD代码。

2. 技术选型:为什么是Spring Boot,以及搭配什么

选题题目里已经明确要求Spring Boot,所以后端框架不用纠结。但其他配套技术真的需要认真选,我当时在几个关键点上来回折腾不少时间,这里逐一说明。

2.1 后端与数据库选型

我用的是Spring Boot 2.7.x版本,内置Tomcat,依赖管理非常省心。持久层框架选了MyBatis-Plus,不是因为它比JPA好多少,而是因为对于毕设这种快速迭代场景,MyBatis-Plus的代码生成器真的能省一晚上时间。数据库用MySQL 8.0,本地环境搭配Navicat可视化操作,建表、调试数据库的时候非常方便。

ORM映射这块我多提一句。无人机巡查数据表里有经纬度、高度、航向角这些字段,设计表结构的时候要注意精度问题。位置坐标我统一用DECIMAL(10,6)来存,这个精度已经是厘米级别的了,完全够用。有些同学用DOUBLE或者FLOAT,浮点误差后面在地图上做多边形显示的时候会很痛苦。

2.2 地图组件选型

地图是这个系统的门面。我试过几款主流的API,考虑到毕设场景不涉及商业授权和服务器端复杂渲染,最终前端选了Leaflet,配合OpenStreetMap瓦片图层。Leaflet的API非常简洁,在地图上画多边形地块、画航线轨迹、打标记点都是几行代码的事。

后端如果有需要做地理围栏和航线距离计算的,我用的Geotools库来判断地块边界是否闭合、航线是否越界。如果你不想引入这个较重的依赖,也可以用Haversine公式手写一个距离计算工具类,几十行代码的事,效果差不多。

2.3 无人机对接方式

这是很多同学拿到题目的第一个疑问:无人机的数据到底怎么接?

实际做下来,无非两种方式。第一种是使用厂商提供的移动端SDK,让遥控器或者手机App直连无人机,然后通过SDK把数据转发到自己的后端;第二种是无人机通过4G蜂窝网络模块直接连后台,走MQTT或HTTP协议上报状态和图片。对于毕设来说,多数情况没有真机条件,我推荐用模拟器加模拟数据流的方式。自己开发一个DroneSimulator模块,按照真实无人机的经纬度变化规律生成模拟坐标点,通过WebSocket每秒推送位置信息到前端地图,画面回传用模拟图片。这个方案演示效果好,技术上也完全讲得通。

2.4 前端技术栈

前端我选的是Vue 3加上Element Plus组件库,地图库用Leaflet。Vue的响应式绑定配合地图库的图层管理,做状态的实时更新非常顺手。构建工具用Vite,本地开发热更新快得飞起,比之前用Webpack的时候体验好太多了。

提示:如果你的前端基础比较薄弱,完全可以用Spring Boot的模板引擎Thymeleaf + Bootstrap做一个传统的服务端渲染页面,这样就不用单独维护一套前端工程了。但这个方案在实时地图交互上会吃力一些。自己衡量。

3. 系统架构设计:从单体到分层

毕业设计的系统架构不需要复杂,但结构必须清晰、答辩讲得通。我采用的是经典的单体分层架构,把模块拆分开来,这个模式最容易理解,也最好维护。

3.1 分层架构

整个后端工程分成四个核心层:

  • Controller层:负责接收HTTP请求,参数校验,调用Service层,返回统一响应结构。
  • Service层:业务逻辑核心,比如创建任务时校验地块归属、计算航线、生成任务编码等。
  • Mapper层:用MyBatis-Plus的BaseMapper接口实现单表CRUD,多表查询用@Select注解手写SQL。
  • DTO/VO层:请求和响应对象。不要直接把Entity实体暴露给前端,通过DTO做字段过滤,避免密码等敏感信息泄露。

统一响应结构我建议用一个Result<T>泛型类,包含code、message、data三个字段。所有接口都返回这个结构,前端处理起来只用判断code是否为200,非常清爽。现在网上很多项目模板里都有这个写法,直接抄过来改改就行,不必重复造轮子。

3.2 数据库表设计

数据库设计是最能体现基本功的地方,我建了七张核心表。这里列一下每张表的关键字段:

-- 用户表 CREATE TABLE `sys_user` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(50) UNIQUE NOT NULL, `password` VARCHAR(255) NOT NULL, `role` VARCHAR(20) NOT NULL, `real_name` VARCHAR(50), `phone` VARCHAR(20), `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 地块表 CREATE TABLE `field_info` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `field_name` VARCHAR(100) NOT NULL, `owner_id` BIGINT NOT NULL, `area` DECIMAL(10, 2), `crop_type` VARCHAR(50), `boundary` JSON NOT NULL, `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 无人机设备表 CREATE TABLE `drone_device` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `device_name` VARCHAR(100), `device_code` VARCHAR(50) UNIQUE, `status` TINYINT DEFAULT 0, `battery_level` INT DEFAULT 100, `latitude` DECIMAL(10, 6), `longitude` DECIMAL(10, 6), `update_time` DATETIME ); -- 飞行任务表 CREATE TABLE `fly_task` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `task_code` VARCHAR(50), `field_id` BIGINT NOT NULL, `drone_id` BIGINT, `operator_id` BIGINT, `route` JSON, `status` TINYINT DEFAULT 0, `start_time` DATETIME, `end_time` DATETIME, `report_id` BIGINT ); -- 巡查照片表 CREATE TABLE `inspection_photo` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `task_id` BIGINT NOT NULL, `photo_url` VARCHAR(255), `latitude` DECIMAL(10, 6), `longitude` DECIMAL(10, 6), `altitude` DECIMAL(10, 2), `shoot_time` DATETIME, `analysis_result` TEXT );

这里特别说一下boundary字段。我直接用MySQL的JSON类型存地块边界坐标数组,形式是一个多边形顶点数组,比如:

[[120.123456, 30.234567], [121.123456, 30.234567], [121.123456, 31.234567]]

后面的航线规划算法直接读取这个数组做计算,很方便。如果用四个单独的字段存边界,会导致系统非常僵硬,大自然界的田地哪里有不规则的。

3.3 核心设计亮点:任务状态机

飞行任务的整个生命周期有多个状态,我是用一个状态机来管理的:草稿(0)、待审核(1)、执行中(2)、已完成(3)、已取消(4)。状态之间的流转必须合法,比如“已完成”的任务不能直接改回“执行中”。

代码实现上,我写了一个状态流转校验器,核心思想是在更新任务状态时先判断当前状态和目标状态是否满足预设的流转规则:

public enum TaskStatus { DRAFT(0), PENDING(1), EXECUTING(2), COMPLETED(3), CANCELED(4); public boolean canTransitionTo(TaskStatus target) { switch (this) { case DRAFT: return target == PENDING || target == CANCELED; case PENDING: return target == EXECUTING || target == CANCELED; case EXECUTING: return target == COMPLETED || target == CANCELED; default: return false; } } }

这个设计在答辩的时候是一个加分项,因为它体现了你对业务流程的深入理解,而不只是简单的CRUD。

4. 核心功能实现与实操细节

讲完了架构和表结构,这部分是全文的干货中的干货,我把几个核心模块的实现细节和关键代码讲透。

4.1 用户认证与授权实现

登录认证我用的是JWT方案。用户提交用户名密码,后端校验通过后签发一个有效期2小时的Token。前端拿Token存储在localStorage里面,每次请求在请求头加上Authorization: Bearer xxx。后端用一个拦截器解析Token并注入当前用户信息到请求上下文。

关键代码如下:

@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AuthInterceptor()) .addPathPatterns("/api/**") .excludePathPatterns("/api/user/login", "/api/user/register"); } }

拦截器里要注意的一个点:白名单不要只放行登录接口,如果前端需要加载系统配置、获取地图瓦片地址这类公共接口,也要加进白名单,否则前端页面都会因为401而无法初始化。这个是我调了半天才发现的坑。

密码存储千万不要明文入库,用BCrypt加密:

String encoded = new BCryptPasswordEncoder().encode(rawPassword); boolean matches = new BCryptPasswordEncoder().matches(rawPassword, storedHash);

4.2 航线规划算法

航线规划是本系统最具技术含量的模块,也是答辩时最容易出彩的地方。无人机的巡查航线不能随便画,要保证覆盖整个农田,并且相邻航线之间没有遗漏区域。

我采用的算法思路是“往返式扫描”。具体步骤:

  1. 从地块边界中找出最南端和最北端的点,确定南北跨度。
  2. 设定航线间隔,比如8米一条航线(这个数值取决于无人机摄像头的覆盖宽度)。
  3. 从北到南生成一系列平行线,与地块多边形求交点。
  4. 将这些交点按奇数航线从左到右、偶数航线从右到左的顺序连接起来,形成连续的扫描路径。

代码实现的核心是一个求线段与多边形交点的工具方法,用Geotools库可以简化:

public List<Point> generateRoute(List<Point> fieldBoundary, double spacing) { List<Point> routePoints = new ArrayList<>(); Envelope envelope = new Envelope( getMinX(fieldBoundary), getMaxX(fieldBoundary), getMinY(fieldBoundary), getMaxY(fieldBoundary) ); // 生成平行线并与多边形相交 for (double y = envelope.getMinY(); y <= envelope.getMaxY(); y += spacing) { LineString scanLine = new GeometryFactory().createLineString( new Coordinate[] { new Coordinate(envelope.getMinX() - 10, y), new Coordinate(envelope.getMaxX() + 10, y) } ); // 用intersection方法求交集 Geometry intersection = polygon.intersection(scanLine); // 按顺序收集交点... } return routePoints; }

模拟数据生成的时候,我就是让模拟器按这条航线上的点顺序飞行,每秒推进一个点,前端地图上就能看到无人机沿着预设航线小步前进。

4.3 实时位置推送

无人机状态的实时展示,我用了WebSocket。后端有一个DroneLocationEndpoint,客户端连上之后,DroneSimulator产生的每条位置消息通过SimpMessagingTemplate推送到订阅了对应通道的前端页面。

后端关键配置:

@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws/drone") .setAllowedOriginPatterns("*"); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("/app"); } }

前端页面订阅的位置是/topic/location/{taskId},后端推送的具体内容如下:

{ "droneId": 3, "latitude": 30.123456, "longitude": 120.654321, "altitude": 50.2, "battery": 87, "speed": 5.2 }

地图上的无人机图标用Leaflet的Marker实现,收到推送后动态更新图标位置。这个交互效果展示了就能让答辩老师直观体会系统功能。

4.4 巡查数据上传与图像处理

无人机拍摄的照片比较大,直接存数据库是不可取的。我的方案是存本地文件系统,数据库只存文件路径。上传接口用Spring Boot的MultipartFile接收文件,然后转存到指定目录。

照片上传后触发一个异步的分析任务。这里我做一个基础的图像质量判断和初步的植被颜色分析,判断照片是否偏色或者过曝。这个逻辑不复杂,用Java自带的BufferedImage读取像素,对每个像素的R、G、B通道做统计:

BufferedImage image = ImageIO.read(file); int totalPixels = 0; int vegetationPixels = 0; for (int x = 0; x < image.getWidth(); x += 4) { for (int y = 0; y < image.getHeight(); y += 4) { Color color = new Color(image.getRGB(x, y)); double r = color.getRed(); double g = color.getGreen(); double b = color.getBlue(); // 简单判断:绿色通道显著高于红色和蓝色 -> 植被区域 if (g > r * 1.1 && g > b * 1.1) { vegetationPixels++; } totalPixels++; } } double vegetationRate = (double) vegetationPixels / totalPixels;

采样间隔取4像素是为了减少计算量,分析时间从秒级降到百毫秒级。这个简单的植被覆盖率指数可以作为巡查报告里的一项指标。

4.5 巡查报告生成

所有照片和分析结果汇总之后,后端生成一份巡查报告。报告内容包含:任务编号、执行的日期、巡查地块名称、无人机设备、飞行总时长、总里程、照片总数、植被覆盖异常区域分析等。

我用的方案是后端生成JSON格式的报告数据,前端通过模板引擎渲染成页面,同时引导用户一键导出为PDF版本。这样既不用在服务端配置复杂的PDF模板,又有很好的展示效果。

5. 前端地图交互与可视化开发

这个系统不能只有后端,前端的地图交互才是直观输出。整个前端工程我用Vite创建,引入了Leaflet插画,页面包括登录注册、地图看板、任务管理、地块管理、报告查看几个页面。

5.1 地块多边形绘制与管理

农户或者管理员在新增地块时,需要通过地图手动绘制地块的边界。我用Leaflet内置的L.polygon来绘制,在draw:created回调中获取绘制完成的坐标数组。

map.on(L.Draw.Event.CREATED, function (event) { var layer = event.layer; var coords = layer.getLatLngs()[0].map(function (latlng) { return [latlng.lng, latlng.lat]; }); fieldBoundary.value = JSON.stringify(coords); });

这里注意存取经纬度的顺序,我之前画好多边形传给后端,后端再读出来画到地图上时,多边形位置差了一万多公里,最后发现是经度和纬度顺序写反了。

前端获取地块列表后,可以用L.geoJSON批量渲染,这样一处绘制,多端同步显示。

5.2 实时航线展示

任务执行的时候,主地图上会有两个图层:一个是规划航线(红色虚线),另一个是实际飞行路径(绿色实线)。红色虚线在创建任务时就已经画好,绿色实线是随着WebSocket推送的位置消息实时延展的。

实现方式是在接收到新位置数据后,把坐标点加到飞行轨迹数组中,重新设置图层的latlngs:

flightPath.setLatLngs(trackPoints); map.setView([latitude, longitude], 16);

地图跟随无人机移动这个功能,在答辩现场播放的时候效果特别好。

5.3 热力图可视化扩展

想做一个亮点功能的话,我强烈建议加一个植被长势的热力图。把每个采样点的NDVI指数映射成从红色到绿色的渐变色,然后在图上渲染成半透明的热力图层。这个功能虽然只是用一个现成的热力插件做的,但它在视觉上的冲击力很强,让“巡查系统”不只是跑一遍动画,而是真正展示了数据分析的价值。

6. 模拟器与测试环境搭建

一个实际难点是:如果你没有真机,怎么演示飞行过程和管理系统。我的做法是构建了一个完整的模拟环境,跑通整个闭环。

6.1 无人机模拟器设计

模拟器是一个独立的Spring Boot组件,触发任务后启动一个@Scheduled定时任务,每隔1秒执行一次。它按照前面生成的航线的坐标点依次飞行,每次更新位置信息,并模拟当前海拔、电量等参数。

@Component public class DroneSimulator { private List<Point> route; private int currentIndex = 0; @Scheduled(fixedRate = 1000) public void simulateFlight() { if (route == null || currentIndex >= route.size()) { return; } Point currentPoint = route.get(currentIndex); // 推送位置到WebSocket notifyLocation(currentPoint); // 模拟电量递减 currentIndex++; } }

模拟器里我故意让无人机航线轨迹带一些微小的随机偏移,模拟实际飞行中受到风力影响产生的漂移,这样画面看起来更真实。

6.2 模拟巡查图片生成

照片上传这个环节我也做了模拟处理。系统启动时会预先生成一批带有不同颜色分布的图片文件,有绿色的健康区域图片,有偏黄色的异常区域图片,有正常的农田俯视图。飞行任务模拟到特定位置时,自动“拍摄”并上传对应的模拟图片,从而触发后续的图像分析。

这套模拟方案让我在没有真机的情况下,完整跑通了“创建任务-规划航线-模拟飞行-上传数据-生成报告”整个链路。答辩演示如果时间充裕,还可以现场创建任务并实时看到执行画面。

6.3 本地开发环境配置

开发环境的配置有几个容易踩坑的地方,我单独列一下:

  • MySQL版本:尽量用8.0以上,装好之后确认root账号密码能够连接,别像我一开始把密码设置得太复杂结果一直认证失败。
  • Node版本:Vite 5要求Node 18以上,如果本地还是老版本,会报奇怪的兼容性错误,直接升级Node版本。
  • 端口占用:Spring Boot默认8080端口,我电脑上装了很多开发工具经常占用8080,可以在application.yml里把端口改成8090或者别的,省去排查冲突的时间。
  • 文件上传大小:Spring Boot默认上传上限是1MB,巡查照片的分辨率往往几MB,需要在application.yml里调大:
spring: servlet: multipart: max-file-size: 50MB max-request-size: 100MB

这个不设置真实照片一传就报错,很基础但很多人会忘。

7. 常见问题与调试经验

这个部分我整理了开发过程中最常遇到的几个问题,每一个都是实际排查过的,写出来省得你们再踩一遍。

7.1 数据库连接和JSON字段处理问题

问题现象:启动项目时报Field 'boundary' doesn't have a default value,或者查询时拿到的JSON字段是乱码。

排查思路:先检查MySQL连接串的时区参数和字符编码设置。我的连接串是这样的:

spring: datasource: url: jdbc:mysql://localhost:3306/drone_farm?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

JSON字段的处理要注意:MyBatis-Plus默认不支持直接映射JSON字段到Java对象,需要在字段上加上@TableField(typeHandler = JacksonTypeHandler.class)注解,同时实体类要标记@TableName(autoResultMap = true)。这个问题我查了很久才找到原因,报错信息也不太明显。

7.2 前端跨域问题

前后端分离开发时,Vue前端运行在localhost:5173,Spring Boot后端运行在8090端口,必然会遇到跨域问题。

我在后端配置了一个全局CORS映射:

@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.addAllowedOriginPattern("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); config.setAllowCredentials(true); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }

要注意的是,如果加了Spring Security,CORS过滤器要注册在认证过滤器之前,否则请求会被拦截器拦截掉。我刚开始是先写了Security配置后加的CORS,结果跨域问题怎么配置都不生效,先后顺序很重要。

7.3 文件存储路径问题

图片上传后放在本地的upload目录,但如果直接用相对路径,不同环境下工作目录不同可能导致文件找不到。我在配置里用绝对路径来存储,同时提供静态资源映射方式访问:

file: upload-dir: D:/drone_farm_upload/
@Configuration public class FileConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/upload/**") .addResourceLocations("file:D:/drone_farm_upload/"); } }

用这种方法后,前端图片链接直接填/upload/xxx.jpg就能访问了。

7.4 浏览器缓存导致页面不更新

开发过程中调整了Vue组件代码,刷新浏览器却没变化。排除热更新失效的问题后,我怀疑是浏览器缓存策略。在vite.config.js里配置:

server: { port: 5173, host: true, hmr: { overlay: true } }

实际里最实用的做法还是忽略这个缓存问题,开发阶段直接开无痕窗口,发布阶段打包时给静态资源文件名加上哈希值,一劳永逸。

7.5 高德/Leaflet坐标偏移问题

国内使用地图的时候,经常遇到GPS坐标在Leaflet地图上显示的位置与实际位置有几十米甚至上百米的偏移。这是因为使用的坐标标准不同。我的模拟器数据是模拟的,倒不至于有真机偏航问题,但如果你接真机,需要注意把无人机上报的WGS84坐标转换为在地图供应商使用的坐标系,否则地图上无人机位置会明显漂移。

如果用的Leaflet搭配OpenStreetMap,通常也需要自己实现一个坐标转换工具类,写一个简单的转换函数。这个问题答辩时会被老师追问,提前准备一下回答思路,能体现你了解民用无人机导航定位的基础知识。

8. 部署发布与答辩准备要点

开发完成之后,部署和答辩准备也是同样重要的环节。这套项目我最终打包部署在本地的一台闲置机器上,用Docker Compose一键启动了MySQL、后端服务和前端静态资源服务器。

8.1 后端打包部署

Spring Boot项目打包成可执行JAR:

mvn clean package -DskipTests java -jar target/drone-farm-system.jar --spring.profiles.active=prod

生产环境的数据库连接、文件上传路径等配置我单独放在application-prod.yml,避免覆盖开发环境的私有配置。

提示:打包之前务必检查application.yml里是否留有本机绝对路径的调试信息,我之前因为配置里遗留了开发机的数据库账号密码,差点把调试信息一起打包进部署版本。这类信息带来的安全隐患值得重视,尤其是课程设计或者毕设提交到公开仓库的时候,记得在打包前清理敏感配置。

8.2 答辩演示脚本准备

答辩演示顺序非常重要,一个好的演示顺序能让评委5分钟以内建立起对系统的整体认知。我演示时遵循这套顺序:

  1. 登录页展示系统界面,说明三种角色权限差异。
  2. 进入地块管理,展示已绘制的农田边界多边形。
  3. 创建一条新的飞行任务,根据地块自动生成航线。
  4. 启动任务,无人机在实时地图上沿航线飞行,同时展示电量下降、位置更新、图片上传。
  5. 打开巡查报告,展示植被覆盖率分析结果和异常区域标注。
  6. 最后展示系统管理页面,展示用户和设备管控。

整个演示控制在8分钟以内,节奏紧凑。中间如果因为环境问题卡住,马上切换浏览器演示备份视频,千万别在现场反复调试。

8.3 论文文档要点

除代码外,毕业设计一般还要交付配套文档。我当时的文档主要包括:需求规格说明书、数据库设计文档、接口文档、测试报告、用户操作手册。一份质量较高的配套文档的核心可以这样组织:

  • 首页:系统背景、意义、国内外现状分析。
  • 技术选型说明:为什么选Spring Boot、为什么选Leaflet、为什么用MySQL。
  • 设计章节:架构图、功能模块图、数据库ER图。
  • 实现章节:每个核心模块的代码片段并解释逻辑。
  • 测试章节:功能测试表、接口测试结果、性能测试初步结果。

文档中的截图要能对应上系统真实运行时的界面,不要用网上的图片,否则答辩时老师现场打开系统对比就露馅了。

9. 我的经验与体会

这个项目做完,收获真的比我想象的大很多。它在技术层面涵盖了后端框架、权限管理、实时通信、地图可视化、文件处理、算法设计,几乎每一个Web开发常遇到的技术点都有涉足。

我个人特别想说的一点:这类软硬结合的系统,不要一开始追求把真机硬件跑通。先把整体架构搭起来,用模拟数据把整个数据流跑通,之后再替换真实的数据源。这个思路其实也是工程领域很常见的做法——先建立仿真环境,再逐步替换真实组件,每一步都有可验证的中间产物。我见过太多同学一开始就纠结无人机SDK调用,被厂商文档折磨两周,进度完全卡住。换条路,先让系统转起来,后面再补细节,心态和进度都会好很多。

最后再分享一个让内容更出彩的小技巧:如果你的系统里加一个“历史巡查轨迹回放”的功能,把之前某次任务的飞行轨迹和照片像放电影一样重现一遍,不仅工作量不大,而且这往往是答辩现场让评委印象最深的功能,因为它呈现的是一个“系统在真实记录数据”的完整闭环,而不是一堆页面堆砌。

如果你也在做类似的系统,希望这篇文章能帮你少踩几个坑。有问题欢迎在评论区交流,我知道的都会尽量分享。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询