
简介这是一套面向农业信息化开发者与Java移动应用学习者的智慧养猪Android客户端完整工程聚焦生猪养殖全流程数字化管理需求涵盖环境监测、饲喂记录、疫病预警等核心功能模块。资源共179个文件包含38个Java源码文件实现业务逻辑与UI交互、59个XML布局与配置文件定义界面结构与权限声明、34个PNG图标资源适配多分辨率设备以及25个SO本地库支撑定位、传感器等底层能力整体压缩包仅20.14MB轻量易部署。已有316人下载学习适合具备Android开发基础的中级开发者快速理解智慧农业类App的架构设计与技术落地路径。项目采用标准Gradle构建含完整gradle-wrapper、build.gradle及BaiduLBS地图SDK集成目录结构规范可直接导入Android Studio编译运行是学习移动端农业物联网融合实践的典型参考案例。1. 智慧化养猪App不是给猪装APP而是让养殖决策从“凭经验”变成“看数据流”你见过凌晨三点还在刷手机看猪舍温湿度曲线的场长吗我见过——他手机里那个标着“智牧通”的App正把23号分娩栏的氨气浓度异常报警推送到他微信同时自动调高了该区域风机转速。这不是科幻片是去年在山东某万头母猪场落地的真实场景。所谓“智慧化养猪AppJava100%”核心根本不是用Java写个能点开的图标而是以Java为技术底座构建一套可闭环、可回溯、可干预的养殖数据操作系统前端App只是入口背后是Java服务实时处理IoT设备上报的温湿度、氨气、摄食量、视频AI识别的采食行为、发情状态等多源异构数据再反向驱动硬件执行如自动投料、通风调节最终形成“感知-分析-决策-执行”完整链路。它解决的不是“有没有App”而是“App背后有没有一个能听懂猪语言的Java系统”。适合中小型规模化猪场的技术负责人、有IoT集成经验的Java工程师以及正在从人工巡检转向数字化管理的养殖企业IT团队。别被“App”二字带偏——真正值钱的是那套跑在Linux服务器上、每秒处理上千条传感器消息、支撑300并发场区数据同步的Java后端。2. 用Spring Boot MyBatis搭建核心数据管道从传感器到数据库的最小可靠链路智慧化养猪的数据流起点从来不是App界面而是部署在猪舍顶部的LoRa温湿度传感器、食槽底部的压力传感模块、摄像头边缘AI盒子输出的JSON结构化结果。这些设备通过网关汇聚后以HTTP POST或MQTT协议将原始数据推送到Java后端。我们不追求一步到位的微服务架构先用Spring Boot 2.7.xJDK 11兼容搭出一条抗丢包、可溯源、易扩展的数据管道。关键不在炫技而在稳——猪场网络环境复杂断网是常态必须设计本地缓存兜底。2.1 设计轻量级设备接入网关统一接收、校验、路由所有设备数据统一走/api/v1/device/data接口采用RESTful风格但严格约束请求体。重点不是REST而是防错前置必须携带X-Device-ID设备唯一编码如TH-001A-2023、X-Timestamp毫秒时间戳服务端校验±5分钟偏差、X-SignatureHMAC-SHA256签名密钥由设备注册时分配请求体为标准JSON字段名强制小驼峰禁止嵌套过深深度≤3// DeviceDataController.java PostMapping(/api/v1/device/data) public ResponseEntityApiResponse receiveDeviceData( RequestHeader(X-Device-ID) String deviceId, RequestHeader(X-Timestamp) long timestamp, RequestHeader(X-Signature) String signature, RequestBody DeviceDataPayload payload) { // 1. 时间戳校验防止重放攻击 long now System.currentTimeMillis(); if (Math.abs(now - timestamp) 5 * 60 * 1000) { return ResponseEntity.badRequest() .body(ApiResponse.error(Timestamp expired)); } // 2. 签名校验使用Redis缓存设备密钥避免DB查询 String secretKey redisTemplate.opsForValue() .get(device:secret: deviceId); if (secretKey null || !verifySignature(payload, timestamp, secretKey, signature)) { return ResponseEntity.status(401) .body(ApiResponse.error(Invalid signature)); } // 3. 路由到对应处理器解耦关键 DeviceDataHandler handler deviceHandlerRegistry.getHandler(payload.getDeviceType()); if (handler null) { return ResponseEntity.badRequest() .body(ApiResponse.error(Unsupported device type: payload.getDeviceType())); } // 4. 异步处理避免阻塞HTTP线程 CompletableFuture.runAsync(() - handler.handle(deviceId, payload)); return ResponseEntity.ok(ApiResponse.success(Accepted)); }提示DeviceDataHandler是策略接口按设备类型TEMP_HUMIDITY,FEED_WEIGHT,VIDEO_AI_RESULT动态注入不同实现类。这样新增一种摄像头AI分析结果格式只需新增一个Handler实现无需改Controller——这是应对养殖现场设备品牌混杂海康、大华、自研LoRa盒子的血泪经验。2.2 MyBatis动态建表与分表应对海量传感器数据的存储策略一个万头猪场300个传感器×每10秒1条数据≈260万条/天。若全塞进单表MySQL查询会越来越慢。我们放弃ShardingSphere等重型方案用MyBatis原生能力做时间维度分表每月一张表表名如sensor_data_202405。关键在Mapper.xml中用bind动态拼接表名!-- SensorDataMapper.xml -- insert idinsertBatch parameterTypejava.util.List INSERT INTO sensor_data_${tableName} (device_id, data_type, value, timestamp, created_at) VALUES foreach collectionlist itemitem separator, (#{item.deviceId}, #{item.dataType}, #{item.value}, #{item.timestamp}, NOW()) /foreach /insertJava层根据当前日期计算表名public String getTableName() { LocalDate now LocalDate.now(); return sensor_data_ now.format(DateTimeFormatter.ofPattern(yyyyMM)); } // 创建新表的SQL首次运行或月初自动触发 private void createMonthlyTableIfNotExists(String tableName) { String sql CREATE TABLE IF NOT EXISTS tableName ( id BIGINT AUTO_INCREMENT PRIMARY KEY, device_id VARCHAR(64) NOT NULL, data_type VARCHAR(32) NOT NULL, value DECIMAL(10,3) NOT NULL, timestamp BIGINT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_device_time (device_id, timestamp) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; jdbcTemplate.execute(sql); }参数说明data_type字段存储TEMP,HUMIDITY,AMMONIA等枚举值而非建300个字段——这是为后续加设备留的活口。索引idx_device_time确保按设备查历史趋势时毫秒级响应实测1亿数据下SELECT * FROM sensor_data_202405 WHERE device_idTH-001A-2023 AND timestamp BETWEEN 1717027200000 AND 1717113600000耗时80ms。2.3 数据清洗中间件把“脏数据”变成“决策依据”传感器常报错值温度突然跳到99℃实际是探头短路、摄食量负数称重模块归零失败。我们不丢弃而是用规则引擎标记为“待复核”并触发告警。核心是DataCleaningServiceComponent public class DataCleaningService { // 规则配置存在数据库支持后台修改非硬编码 private final MapString, CleaningRule rules new ConcurrentHashMap(); public CleanedData clean(DeviceDataPayload payload) { String ruleKey payload.getDeviceType() _ payload.getDataType(); CleaningRule rule rules.get(ruleKey); if (rule ! null !rule.isValid(payload.getValue())) { // 标记为异常但保留原始值供追溯 return CleanedData.builder() .originalValue(payload.getValue()) .cleanedValue(rule.getDefaultValue()) // 如温度异常时设为null .status(DataStatus.ABNORMAL) .reason(rule.getReason()) // 温度超出合理范围[0,50] .build(); } return CleanedData.builder() .originalValue(payload.getValue()) .cleanedValue(payload.getValue()) .status(DataStatus.NORMAL) .build(); } }规则示例存于cleaning_rule表device_typedata_typemin_valuemax_valuedefault_valuereasonTEMP_HUMIDITYTEMP050null温度超出合理范围[0,50]FEED_WEIGHTWEIGHT05000摄食量不能为负为什么不用Flink/Kafka因为中小猪场没专职大数据运维。这套基于Spring Boot的轻量清洗在单台4C8G服务器上稳定处理3000TPS且规则可后台配置——场长自己就能关掉某条误报规则这才是真智慧。3. App端核心功能落地用Java后端驱动的“非典型”移动体验很多人以为智慧养猪App就是做个UI展示图表其实真正的价值在于让一线人员用最省力的方式完成最关键动作。我们的AppAndroid/iOS双端本身不写业务逻辑所有操作都调用Java后端API但后端做了大量适配比如针对猪场网络差、手机型号老旧、操作员戴手套等现实约束设计了极简交互路径。3.1 “一键巡栏”功能把30分钟人工检查压缩到15秒传统巡栏要拿本子记23号栏温度28℃、湿度65%、氨气12ppm、母猪精神尚可。现在App首页大按钮【开始巡栏】点击后自动获取手机GPS定位精度要求±5米因猪舍布局固定调用GET /api/v1/pen/status?gps117.23,36.67后端根据坐标匹配最近猪舍编号如PEN-23返回该栏位当前所有传感器实时值 过去2小时趋势图 AI视频识别结果摘要如“检测到3头母猪站立1头卧姿无异常行为”操作员只需滑动三个开关✅ 正常 / ⚠️ 需关注 / ❌ 紧急后端API返回精简JSON{ penId: PEN-23, temperature: {current: 27.8, trend: ↑, alert: false}, ammonia: {current: 11.2, trend: →, alert: true, desc: 接近阈值12ppm}, aiSummary: 3头站立采食1头卧姿休息未见咳嗽/呕吐, lastCheckTime: 2024-05-22T08:15:22 }关键设计ammonia.alerttrue不代表立刻告警而是前端显示黄色感叹号图标操作员滑动“需关注”时才记录事件。这避免了传感器偶发抖动导致的无效告警——猪场最怕假警报疲劳。3.2 发情预测推送用Java定时任务跑LSTM模型但只推结论很多方案把AI模型直接塞进App结果低端机卡死。我们反其道而行模型跑在Java后端TensorFlow Java API每天凌晨2点用过去7天数据预测未来3天发情概率结果存入estrus_prediction表。App启动时拉取GET /api/v1/estrus/today只返回一句话结论{ date: 2024-05-22, predictions: [ { pigId: SOW-00123, penId: PEN-15, probability: 0.87, action: 建议今日上午9点进行公猪试情, confidence: high } ] }为什么不用Python服务因为猪场IT人员更熟悉Java日志排查logback.xml配置滚动归档、线程池监控/actuator/threaddump、内存泄漏分析jmap -histo。模型推理耗时我们压到200ms/头靠的是预加载模型对象池复用SavedModelBundle实例。3.3 离线模式保障当网络中断时App仍能记录关键动作猪场WiFi覆盖不均产房地下室常无信号。App设计离线优先所有“巡栏”、“用药记录”、“异常上报”操作先存本地SQLite后台Service每5分钟尝试同步成功后删本地记录同步失败时通知栏显示“已缓存3条记录等待网络恢复”后端同步API需幂等PostMapping(/api/v1/offline/sync) public ResponseEntity syncOfflineRecords(RequestBody ListOfflineRecord records) { // 1. 按recordId去重客户端生成UUID SetString syncedIds offlineSyncService.sync(records); // 2. 返回哪些已成功哪些因冲突需人工确认 return ResponseEntity.ok(new SyncResult(syncedIds, findConflicts(records, syncedIds))); }血泪经验离线记录必须包含device_id手机IMEI和operator_id员工工号否则网络恢复后无法区分是谁在哪个设备上录的——曾有场长用自己手机帮工人录数据结果全部记到他名下绩效算乱了。4. 避坑指南智慧化养猪项目中最容易翻车的5个技术雷区智慧化养猪不是技术炫技而是解决真实生产问题。以下5个坑都是我在3个猪场落地时踩出来的每个都导致过产房温度失控或发情漏检务必警惕4.1 现象App显示“23号栏温度25℃”但现场水银温度计读数是29℃原因传感器校准漂移未处理。LoRa温湿度探头在高湿85%环境下出厂校准值半年后偏差可达±2℃而Java后端直接存原始值未引入校准系数。解决在device_info表增加temp_offset、humidity_offset字段后端入库前自动修正// 入库前修正 payload.setValue(payload.getValue() deviceInfo.getTempOffset()); // 同时记录校准时间超180天自动触发告警 if (System.currentTimeMillis() - deviceInfo.getLastCalibratedAt() 180L * 24 * 3600 * 1000) { alertService.send(设备需校准, deviceInfo.getDeviceId()); }4.2 现象凌晨3点大量“氨气超标”告警但场长到场发现一切正常原因氨气传感器被苍蝇尸体堵塞。低价传感器200在猪舍高粉尘环境寿命仅3个月但后端未做传感器健康度评估持续接收错误数据。解决增加传感器自检逻辑。对连续10次上报值波动0.1ppm的设备标记health_statusSTUCK停止参与告警计算并推送“请清洁23号栏氨气探头”工单到App。4.3 现象App“发情预测”连续3天说“SOW-00123明日发情”结果配种失败原因模型训练数据未排除哺乳期母猪。LSTM模型用历史发情数据训练但未过滤掉产仔后21天内的数据此时激素紊乱行为不可信导致预测失真。解决在数据清洗阶段增加业务规则过滤-- 训练数据提取SQL关键 SELECT * FROM estrus_record WHERE status CONFIRMED AND DATEDIFF(NOW(), farrowing_date) 21; -- 哺乳期不参与训练4.4 现象App更新后老款华为Mate9用户打开即闪退原因前端用了WebP图片但Android 7.0以下不支持。Java后端虽无问题但App资源加载失败引发连锁崩溃。解决后端API返回图片URL时根据User-Agent动态降级// ImageController.java GetMapping(/api/v1/image/{id}) public ResponseEntityResource getImage( RequestHeader(User-Agent) String userAgent, PathVariable String id) { String imageUrl imageService.getUrl(id); // 对Android 7.0返回JPEG备用图 if (isOldAndroid(userAgent)) { imageUrl imageUrl.replace(.webp, .jpg); } return ResponseEntity.ok().body(imageService.getResource(imageUrl)); }4.5 现象场长说“App没用还是得自己去看”拒绝使用原因App设计违背养殖直觉。比如把“喂料记录”放在二级菜单而一线工人需要的是“扫一下料车二维码就完成投料”。解决重构交互路径。后端提供极简API# 扫码后App直接调用无登录态靠设备绑定 curl -X POST https://api.pigsmart.com/api/v1/feed/scan \ -H X-Device-ID: FEEDER-001 \ -d {batchNo:20240522-A,weight:125.5}后端收到即记录并触发短信通知技术员“PEN-23今日已投料125.5kg”。——工具的价值是让使用者感觉不到工具的存在。5. 把“Java100%”落到实处用JVM参数与日志规范守住猪场7x24小时底线“Java100%”不是指代码行数占比而是指整个系统稳定性、可观测性、可维护性100%由Java生态承载。猪场系统不能像互联网应用那样随时重启一次宕机可能影响整批仔猪成活率。我坚持的三条铁律5.1 JVM参数宁可保守不要激进猪场服务器通常是4C8G的旧款Dell R720绝不用G1GC这种吃内存的垃圾收集器。生产环境固定参数# JAVA_OPTS in startup.sh -XX:UseParallelGC \ -Xms2g -Xmx2g \ -XX:MaxMetaspaceSize256m \ -XX:HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath/opt/pigsmart/logs/heap.hprof \ -XX:PrintGCDetails \ -Xloggc:/opt/pigsmart/logs/gc.log \ -XX:UseGCLogFileRotation \ -XX:NumberOfGCLogFiles5 \ -XX:GCLogFileSize10M为什么选ParallelGC因为吞吐量优先。猪场数据写入压力大每秒千级INSERTParallelGC在4G堆内存下GC停顿稳定在80ms内而CMS在老年代碎片化后可能STW 2秒以上——这会导致MQTT消息积压传感器数据延迟超10分钟发情预测就废了。5.2 日志规范让每条日志都能回答“谁、在哪儿、干了什么、结果如何”不用Log4j2的复杂配置坚持SLF4J Logback最简组合但日志内容必须带业务上下文// 在Controller层统一埋点 Around(annotation(org.springframework.web.bind.annotation.RequestMapping)) public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start System.currentTimeMillis(); Object result joinPoint.proceed(); long end System.currentTimeMillis(); // 关键提取业务ID设备ID/猪栏ID/员工ID String bizId extractBizId(joinPoint.getArgs()); String method joinPoint.getSignature().toShortString(); log.info(API_EXEC: {} | bizId{} | cost{}ms | result{}, method, bizId, end-start, result instanceof ApiResponse ? ((ApiResponse)result).getCode() : unknown); return result; }日志样例2024-05-22 08:15:22 INFO API_EXEC: DeviceDataController.receiveDeviceData() | bizIdTH-001A-2023 | cost12ms | result200 2024-05-22 08:15:23 ERROR DB_SAVE: Failed to insert sensor_data_202405 | bizIdTH-001A-2023 | errorDeadlock found玄学技巧在logback-spring.xml中用springProperty读取application.yml里的spring.profiles.active不同环境日志级别不同prod:INFO避免磁盘爆满staging:DEBUG联调用dev:TRACE开发用这样不用改代码运维一句--spring.profiles.activestaging就切到调试模式。5.3 可观测性不用Prometheus用Java原生JMX暴露关键指标猪场没K8s也没运维团队拒绝复杂监控栈。直接暴露JMX端口用Zabbix采集# application.yml spring: jmx: enabled: true server: localhost:9999 # 自定义MBean暴露业务指标 management: endpoints: web: exposure: include: health,info,metrics,jvm,threaddump然后写一个PigFarmMetricsMBeanComponent ManagedResource(objectName pigfarm:typeMetrics, description Pig farm business metrics) public class PigFarmMetricsMBean { private final AtomicInteger activeDevices new AtomicInteger(0); private final AtomicInteger abnormalAlarms new AtomicInteger(0); ManagedOperation(description Get current active device count) ManagedOperationParameter(name count, description Active device count) public int getActiveDeviceCount() { return activeDevices.get(); } ManagedOperation(description Reset alarm counter) public void resetAlarmCounter() { abnormalAlarms.set(0); } }Zabbix脚本直接调用JMX# check_pigfarm_jmx.sh java -jar cmdline-jmxclient.jar - 127.0.0.1:9999 pigfarm:typeMetrics getActiveDeviceCount后悔药设计所有关键业务操作如修改温控阈值、确认发情必须落库operation_log表并开启MySQL Binlog。某次误操作把全场降温阈值设成10℃我们靠mysqlbinlog回滚了那条UPDATE30分钟恢复——比任何备份都快。最后说句实在话做智慧化养猪技术永远是配角猪才是主角。我见过太多团队花半年做酷炫3D猪舍可视化结果场长说“我只要知道哪栏该打疫苗”。所以每次写Java代码前我都会去产房站10分钟闻着味道听着猪叫再回来敲键盘。那些在空调房里设计的“高可用架构”往往不如一个能扛住猪舍45℃高温的LoRa网关来得实在。希望帮到你。本文还有配套的精品资源点击获取