1. 项目概述
果蔬种植销售服务平台是一个面向现代农业的数字化解决方案,旨在打通从种植到销售的全流程管理。作为一名长期从事农业信息化开发的工程师,我在实际项目中发现传统果蔬产业普遍存在三个痛点:种植过程缺乏数据支撑、产销信息不对称、物流配送效率低下。这个基于SpringBoot+Vue的全栈系统正是为解决这些问题而生。
系统采用微服务架构设计,后端基于SpringBoot 2.7实现,前端使用Vue 3组合式API开发,数据库选用MySQL 8.0。特别值得一提的是,我们在项目中创新性地整合了物联网数据采集模块,通过Modbus协议与大棚传感器对接,实现了环境参数的分钟级采集。下面这张架构图能清晰展示系统组成:
code复制[图示:系统架构分为四层]
1. 设备层:温湿度传感器、光照传感器、土壤检测仪
2. 数据层:MySQL主从集群 + Redis缓存
3. 服务层:SpringCloud微服务(种植服务/订单服务/用户服务)
4. 展现层:Vue3前端 + 微信小程序
2. 技术栈深度解析
2.1 后端技术选型
选择SpringBoot作为基础框架主要基于三个考量:首先是其完善的生态体系,我们使用的SpringCloud Alibaba组件(Nacos+Sentinl)能完美支持后续的微服务扩展;其次是自动配置特性大幅减少了XML配置,比如数据库连接池默认使用HikariCP,只需简单配置即可获得生产级性能;最后是内嵌Tomcat容器让部署变得极其简单。
在数据持久层,我们采用MyBatis-Plus 3.5.3而非JPA,主要考虑到:
- 需要编写复杂SQL处理农业数据统计分析
- 动态表名支持(按年份分表存储种植记录)
- 强大的条件构造器简化查询代码
示例代码展示如何实现智能分页查询:
java复制public PageResult<CropVO> queryCropPage(QueryCondition cond) {
Page<Crop> page = new Page<>(cond.getPage(), cond.getSize());
LambdaQueryWrapper<Crop> wrapper = Wrappers.lambdaQuery();
wrapper.eq(StringUtils.isNotBlank(cond.getCropType()), Crop::getType, cond.getCropType())
.between(cond.getStartDate() != null, Crop::getPlantDate,
cond.getStartDate(), cond.getEndDate());
return new PageResult<>(cropMapper.selectPage(page, wrapper));
}
2.2 前端工程化实践
前端采用Vue3+TypeScript技术栈,值得分享的工程实践包括:
- 状态管理优化:使用Pinia替代Vuex,配合useStorage实现状态持久化
- 请求拦截:axios拦截器中实现JWT自动刷新机制
- 性能优化:
- 路由懒加载拆分代码包
- 使用v-lazy实现图片懒加载
- 大数据表格采用虚拟滚动
环境监控页面的核心代码示例:
typescript复制const sensorData = ref<SensorData[]>([]);
const fetchData = async () => {
const { data } = await api.getRealtimeData(greenhouseId.value);
sensorData.value = data.map(item => ({
...item,
status: getStatus(item.value, item.type)
}));
};
// 每30秒轮询数据
useIntervalFn(fetchData, 30000);
3. 核心功能实现
3.1 智能种植模块
该模块的技术难点在于物联网设备集成,我们采用的解决方案是:
- 设备层:使用Modbus RTU协议与传感器通信
- 数据采集:Spring Integration实现协议转换
- 数据处理:Flink实时计算环境指数
- 预警机制:基于规则引擎触发短信通知
关键数据库表设计:
sql复制CREATE TABLE `environment_data` (
`id` bigint NOT NULL AUTO_INCREMENT,
`greenhouse_id` varchar(20) NOT NULL COMMENT '大棚编号',
`temperature` decimal(5,2) NOT NULL COMMENT '温度℃',
`humidity` decimal(5,2) NOT NULL COMMENT '湿度%',
`co2` int NOT NULL COMMENT '二氧化碳ppm',
`lux` int NOT NULL COMMENT '光照强度Lux',
`record_time` datetime NOT NULL COMMENT '记录时间',
PRIMARY KEY (`id`),
KEY `idx_greenhouse` (`greenhouse_id`,`record_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 订单处理流程
订单系统实现了以下业务特性:
- 分布式事务处理:使用Seata保证订单创建→库存扣减→物流创建的一致性
- 状态机设计:采用Spring StateMachine管理订单状态流转
- 幂等控制:通过Redis token机制防止重复提交
状态机配置示例:
java复制@Configuration
@EnableStateMachine
public class OrderStateMachineConfig {
@Bean
public StateMachine<OrderStatus, OrderEvent> stateMachine() {
StateMachineBuilder.Builder<OrderStatus, OrderEvent> builder = StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial(OrderStatus.UNPAID)
.states(EnumSet.allOf(OrderStatus.class));
// 配置状态转移规则
builder.configureTransitions()
.withExternal()
.source(OrderStatus.UNPAID).target(OrderStatus.PAID)
.event(OrderEvent.PAY_SUCCESS);
return builder.build();
}
}
4. 质量保障体系
4.1 测试策略
我们采用分层测试策略确保质量:
- 单元测试:JUnit5 + Mockito 核心业务逻辑覆盖率>80%
- 集成测试:TestContainers进行真实数据库测试
- API测试:Postman自动化测试集合
- 前端测试:Vitest + Testing Library组件测试
特别分享一个性能测试案例:在模拟500并发用户下单的场景下,发现MySQL连接池配置不合理导致TPS骤降。通过调整连接池参数和增加从库,最终将响应时间控制在300ms内。
4.2 持续集成
GitLab CI流水线配置要点:
yaml复制stages:
- build
- test
- deploy
build-job:
stage: build
script:
- mvn clean package -DskipTests
artifacts:
paths:
- target/*.jar
test-job:
stage: test
script:
- mvn test
- cd frontend && npm run test:unit
deploy-job:
stage: deploy
only:
- master
script:
- scp target/app.jar user@server:/opt/app
- ssh user@server "systemctl restart app"
5. 部署与运维
5.1 容器化部署
采用Docker Compose编排服务:
dockerfile复制version: '3'
services:
app:
image: openjdk:17-jdk
ports:
- "8080:8080"
volumes:
- ./config:/config
command: ["java", "-jar", "/app.jar"]
depends_on:
- redis
- mysql
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
5.2 监控方案
Prometheus + Grafana监控体系配置:
- 应用指标:Spring Boot Actuator暴露metrics端点
- 日志收集:ELK栈统一处理日志
- 告警规则:当API错误率>1%时触发企业微信通知
6. 踩坑经验分享
-
MyBatis批量插入优化:
初始方案使用foreach拼接SQL,在万级数据时出现性能问题。最终采用ExecutorType.BATCH模式,性能提升20倍。 -
Vue响应式丢失问题:
在处理传感器数据流时,直接赋值导致视图不更新。解决方案是使用shallowRef配合triggerRef手动触发更新。 -
时间序列数据存储:
初期采用单表存储导致查询缓慢。通过按月分表+时序数据库双写方案解决。
这个项目让我深刻体会到农业信息化建设的特殊性:既要处理高并发的电商场景,又要应对复杂的物联网数据。建议后续开发者重点关注领域模型设计,我们采用的DDD方法在后期需求变更时展现出极大优势。