1. 项目背景与意义
随着消费者对食品安全和农产品品质的关注度不断提升,传统农产品流通环节中信息不透明、来源难追溯、责任难界定等问题日益突出。农产品从田间到餐桌往往要经历种植、加工、仓储、运输、销售等多个环节,任何一个环节出现问题,都可能导致质量安全隐患难以定位。
基于 Java 的智农农产品溯源系统,正是为了解决上述痛点而设计。系统以二维码或溯源码为载体,将农产品全生命周期信息进行数字化记录和关联,实现「源头可查、去向可追、责任可究」。其核心意义体现在以下几个方面:
- 保障食品安全:消费者扫码即可查看农产品的产地、施肥用药、检测报告等关键信息,增强消费信任。
- 提升管理效率:农业生产企业可通过系统统一管理批次、库存和流通记录,减少人工台账成本。
- 支撑监管决策:监管部门可基于溯源数据快速定位问题批次,提高应急处置能力。
- 塑造品牌价值:透明化的溯源信息有助于优质农产品建立差异化品牌形象,提升市场竞争力。
2. 系统技术栈
本系统采用经典的企业级 Java 技术体系,兼顾开发效率、稳定性和可维护性。整体技术栈如下:
| 层次 | 技术选型 | 说明 |
|---|---|---|
| 前端 | HTML、CSS、JavaScript、Vue.js / Layui | 负责页面渲染与交互,管理端与消费者查询端分离 |
| 后端框架 | Spring Boot、Spring MVC、MyBatis / MyBatis-Plus | 提供 RESTful 接口、业务逻辑处理与数据持久化 |
| 数据库 | MySQL 5.7+ | 存储用户、农产品、批次、溯源记录等核心业务数据 |
| 缓存 | Redis | 缓存热点查询数据,提升扫码溯源响应速度 |
| 权限认证 | Spring Security + JWT | 实现登录认证与基于角色的访问控制 |
| 文件存储 | 本地存储 / 阿里云 OSS | 保存农产品图片、检测报告等附件 |
| 二维码生成 | ZXing | 为每个农产品批次生成唯一溯源码与二维码 |
| 构建部署 | Maven、Docker、Nginx | 自动化构建、容器化部署与反向代理 |
3. 系统核心功能模块
系统按角色划分为管理员、生产企业、消费者三类用户,核心功能模块如下:
- 用户管理模块:支持用户注册、登录、角色分配与个人信息维护。
- 农产品管理模块:生产企业录入农产品基础信息,包括名称、品种、产地、图片等。
- 批次管理模块:对同一生产条件下的农产品进行批次划分,生成唯一溯源码。
- 溯源记录模块:记录种植、施肥、采摘、检测、仓储、运输等环节的操作信息。
- 溯源查询模块:消费者通过扫描二维码或输入溯源码,查看完整溯源链路。
- 数据统计模块:管理端按时间、品类、产地等维度统计溯源数据,辅助决策。
4. 数据库设计
数据库是溯源系统的核心支撑。以下为主要数据表的设计要点:
- user 表:存储用户账号、密码(BCrypt 加密)、角色类型、联系方式等。
- product 表:存储农产品基础信息,包括名称、品种、产地、规格、图片地址等。
- batch 表:存储批次信息,包括批次编号、关联产品、生产日期、溯源码等。
- trace_record 表:存储溯源环节记录,包括环节名称、操作人、操作时间、描述、图片等。
- detection_report 表:存储检测报告信息,包括检测机构、检测结果、报告文件等。
其中,batch 表与 trace_record 表通过批次编号建立一对多关联,构成溯源链路的骨干。
5. 核心代码实现
下面给出系统后端几个关键模块的核心代码示例。
5.1 实体类设计
以批次实体 Batch 为例,使用 MyBatis-Plus 注解简化开发:
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.time.LocalDateTime; @Data @TableName("batch") public class Batch { @TableId(type = IdType.AUTO) private Long id; /** 批次编号 */ private String batchNo; /** 关联农产品ID */ private Long productId; /** 生产日期 */ private LocalDateTime produceDate; /** 唯一溯源码 */ private String traceCode; /** 批次状态:0-生产中 1-已上市 2-已下架 */ private Integer status; private LocalDateTime createTime; }5.2 生成溯源码与二维码
批次创建时,系统生成唯一溯源码,并调用 ZXing 生成二维码图片:
import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class QrCodeUtil { /** 生成唯一溯源码 */ public static String generateTraceCode() { return "ZN" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 6); } /** 生成二维码图片到指定路径 */ public static void createQrCode(String content, String filePath) throws Exception { int width = 300; int height = 300; Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); BitMatrix bitMatrix = new MultiFormatWriter() .encode(content, BarcodeFormat.QR_CODE, width, height, hints); Path path = Paths.get(filePath); MatrixToImageWriter.writeToPath(bitMatrix, "png", path); } }5.3 溯源查询接口
消费者输入溯源码后,后端按批次查询完整溯源链路并返回:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/api/trace") public class TraceController { @Autowired private BatchService batchService; @Autowired private TraceRecordService traceRecordService; @Autowired private ProductService productService; /** 根据溯源码查询完整溯源信息 */ @GetMapping("/query") public Map<String, Object> queryByTraceCode(@RequestParam String traceCode) { Map<String, Object> result = new HashMap<>(); Batch batch = batchService.getByTraceCode(traceCode); if (batch == null) { result.put("code", 404); result.put("msg", "未查询到该溯源码对应的农产品"); return result; } // 查询农产品基础信息 Product product = productService.getById(batch.getProductId()); // 查询该批次下的全部溯源记录 List<TraceRecord> records = traceRecordService.listByBatchId(batch.getId()); result.put("code", 200); result.put("msg", "查询成功"); result.put("product", product); result.put("batch", batch); result.put("records", records); return result; } }5.4 溯源记录添加
生产企业在各环节完成后,向指定批次追加溯源记录:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.time.LocalDateTime; @RestController @RequestMapping("/api/record") public class TraceRecordController { @Autowired private TraceRecordService traceRecordService; /** 添加一条溯源记录 */ @PostMapping("/add") public Map<String, Object> addRecord(@RequestBody TraceRecord record) { Map<String, Object> result = new HashMap<>(); record.setCreateTime(LocalDateTime.now()); boolean saved = traceRecordService.save(record); if (saved) { result.put("code", 200); result.put("msg", "溯源记录添加成功"); } else { result.put("code", 500); result.put("msg", "溯源记录添加失败"); } return result; } }6. 系统部署与运行
系统采用前后端分离架构,后端打包为可执行 Jar 包,前端静态资源由 Nginx 托管。推荐部署方式如下:
- 环境要求:JDK 1.8+、MySQL 5.7+、Redis、Maven 3.6+。
- 数据库初始化:执行项目提供的 SQL 脚本创建数据库表结构。
- 后端启动:执行
mvn clean package打包,再运行java -jar zn-trace-system.jar。 - 前端部署:将前端构建产物上传至 Nginx 的 html 目录,并配置反向代理转发 API 请求。
7. 总结与展望
基于 Java 的智农农产品溯源系统,通过 Spring Boot + MyBatis-Plus + MySQL 的技术组合,实现了农产品从生产到销售的全链路信息追溯,有效提升了食品安全保障能力和企业管理效率。系统架构清晰、扩展性良好,后续可进一步引入区块链技术增强数据防篡改能力,或结合物联网设备实现环境数据的自动采集与上链,推动智慧农业向更深层次发展。