多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

SpringBoot+Android+小程序全栈固定资产管理系统开发实践

SpringBoot+Android+小程序全栈固定资产管理系统开发实践 1. 项目概述固定资产管理系统的全栈实现这个毕设项目选择了一个非常实用的方向——固定资产借用管理平台。作为在企业IT部门工作多年的老手我见过太多单位还在用Excel表格手工登记设备借用情况不仅效率低下而且容易出错。这个系统采用SpringBootAndroid小程序的组合方案正好覆盖了管理后台、移动端和轻量级前端三个核心使用场景。系统主要解决四大痛点一是固定资产台账混乱二是借用流程不规范三是设备状态难以追踪四是缺乏数据统计分析。我们团队去年为某高校实验室实施的类似系统上线后设备利用率提升了30%管理人力成本降低了60%。下面我就从技术选型到具体实现完整拆解这个项目的开发要点。2. 技术架构设计2.1 后端SpringBoot方案选择SpringBoot 2.7.x版本兼容JDK8作为后端框架是经过多重考虑的。相比传统的SSM框架SpringBoot的自动配置特性让新手也能快速搭建起包含安全认证、数据库访问、API文档等企业级功能的后端服务。我在pom.xml中配置的核心依赖包括dependencies !-- Web支持 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 数据库 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- 安全认证 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency !-- 微信小程序SDK -- dependency groupIdcom.github.binarywang/groupId artifactIdweixin-java-miniapp/artifactId version4.1.0/version /dependency /dependencies数据库设计方面核心表包括asset资产表记录设备基本信息、当前状态borrow_record借用记录包含借用时间、预计归还时间、实际归还时间user用户表区分管理员、普通用户等角色department部门表用于统计各部门资产使用情况2.2 移动端技术选型Android原生开发采用KotlinJetpack组合主要考虑因素有性能优于混合开发框架可以调用完整的Android硬件API如NFC识别与后台SpringBoot服务对接更稳定关键组件包括Retrofit2处理网络请求Room本地数据缓存ZXing二维码扫描WorkManager定时同步任务微信小程序端使用原生开发自定义组件方案主要实现扫码借用功能借用记录查询设备报修功能消息通知订阅3. 核心功能实现细节3.1 资产全生命周期管理资产状态机设计是系统的核心逻辑我采用状态模式State Pattern实现public interface AssetState { void handleBorrow(Asset asset, User user); void handleReturn(Asset asset); void handleRepair(Asset asset); } // 具体状态实现 public class AvailableState implements AssetState { Override public void handleBorrow(Asset asset, User user) { // 创建借用记录 BorrowRecord record new BorrowRecord(asset, user); recordRepository.save(record); // 更新资产状态 asset.setState(AssetStatus.BORROWED); asset.setCurrentUser(user); assetRepository.save(asset); // 发送微信通知 wxMiniAppService.sendBorrowNotice(user, asset); } // 其他方法实现... }状态转换包括可用 → 借出借出 → 归还中归还中 → 可用/维修中维修中 → 可用/报废3.2 双端扫码借用流程Android端扫码实现要点使用CameraX API获取相机预览通过ZXing解析二维码内容二维码格式asset://{assetId}?ts{timestamp}调用后端API验证资产状态class ScanActivity : AppCompatActivity() { private lateinit var cameraExecutor: ExecutorService override fun onCreate(savedInstanceState: Bundle?) { // 初始化相机 val cameraProviderFuture ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ val cameraProvider cameraProviderFuture.get() bindPreview(cameraProvider) }, ContextCompat.getMainExecutor(this)) // 分析二维码结果 barcodeAnalyzer BarcodeAnalyzer { barcode - if (barcode.startsWith(asset://)) { val assetId barcode.substring(8).split(?)[0] viewModel.checkAssetStatus(assetId) } } } private fun bindPreview(cameraProvider: ProcessCameraProvider) { // 相机绑定逻辑... } }小程序端实现差异点使用wx.scanCode API调用微信原生扫码需要处理小程序webview与原生环境的通信借用确认页面需要获取用户微信绑定的手机号3.3 定时任务与消息通知后台定时任务设计借用超时检查每天23点扫描borrow_record表设备保养提醒每月1号检查需要保养的设备数据统计报表每周一生成周报使用Spring Scheduler实现EnableScheduling SpringBootApplication public class AssetApplication { public static void main(String[] args) { SpringApplication.run(AssetApplication.class, args); } } Service RequiredArgsConstructor public class ScheduleService { private final BorrowRecordRepository recordRepository; private final WxMiniAppService wxService; Scheduled(cron 0 0 23 * * ?) public void checkOverdueRecords() { ListBorrowRecord overdueRecords recordRepository .findByActualReturnTimeIsNullAndExpectedReturnTimeBefore(LocalDateTime.now()); overdueRecords.forEach(record - { wxService.sendTemplateMsg( record.getUser().getOpenId(), 借用超时提醒, record.getAsset().getName(), 请尽快归还设备 ); // 同时发送邮件通知部门管理员 emailService.sendOverdueNotice(record); }); } }4. 开发中的典型问题与解决方案4.1 并发借用冲突处理当多个用户同时扫码借用同一设备时会出现资源竞争问题。我们采用乐观锁方案在asset表增加version字段更新时检查version是否变化Transactional public BorrowResult borrowAsset(Long assetId, Long userId) { Asset asset assetRepository.findById(assetId) .orElseThrow(() - new ResourceNotFoundException(设备不存在)); // 乐观锁检查 int updated assetRepository.updateAssetStatus( assetId, AssetStatus.AVAILABLE, AssetStatus.BORROWED, asset.getVersion() ); if (updated 0) { throw new ConcurrentModificationException(设备状态已变更); } // 创建借用记录... }4.2 微信小程序用户体系对接小程序用户与系统用户的绑定是个难点我们采用以下流程小程序端获取微信openid通过手机号验证匹配系统用户建立绑定关系存入user表public User bindWechatUser(String code, String encryptedData, String iv) { // 获取微信session WxMaJscode2SessionResult session wxMaService.getUserService() .getSessionInfo(code); // 解密用户信息 WxMaUserInfo userInfo wxMaService.getUserService() .getUserInfo(session.getSessionKey(), encryptedData, iv); // 通过手机号查找系统用户 User systemUser userRepository.findByPhone(userInfo.getPhoneNumber()) .orElseThrow(() - new BusinessException(系统用户不存在)); // 更新绑定信息 systemUser.setOpenid(session.getOpenid()); systemUser.setWechatInfo(userInfo); return userRepository.save(systemUser); }4.3 Android端数据同步策略移动端采用分层缓存策略内存缓存使用ConcurrentHashMap存储常用数据本地数据库Room持久化关键数据智能同步根据网络状态决定同步频率Dao interface AssetDao { Query(SELECT * FROM assets WHERE status AVAILABLE) fun getAvailableAssets(): FlowListLocalAsset Insert(onConflict OnConflictStrategy.REPLACE) suspend fun insertAll(assets: ListLocalAsset) } class AssetRepository( private val api: AssetApi, private val dao: AssetDao ) { private val cache ConcurrentHashMapString, Asset() fun getAvailableAssets(): FlowListAsset { return flow { // 先发射本地数据 dao.getAvailableAssets().collect { localAssets - emit(localAssets.map { it.toDomainModel() }) } // 网络请求更新 val remoteAssets api.getAvailableAssets() dao.insertAll(remoteAssets.map { it.toLocalModel() }) remoteAssets.forEach { cache[it.id] it } }.flowOn(Dispatchers.IO) } }5. 项目部署与运维要点5.1 服务端部署方案推荐使用Docker Compose部署version: 3 services: app: image: openjdk:8-jdk-alpine volumes: - ./target/asset-management.jar:/app.jar ports: - 8080:8080 environment: - SPRING_DATASOURCE_URLjdbc:mysql://mysql:3306/asset - SPRING_DATASOURCE_USERNAMEroot - SPRING_DATASOURCE_PASSWORD123456 depends_on: - mysql - redis mysql: image: mysql:5.7 environment: - MYSQL_ROOT_PASSWORD123456 - MYSQL_DATABASEasset volumes: - mysql_data:/var/lib/mysql redis: image: redis:alpine ports: - 6379:6379 volumes: mysql_data:关键配置项数据库连接池大小根据服务器配置调整JVM内存参数建议-Xmx设置为可用内存的70%日志轮转策略避免日志占满磁盘5.2 小程序发布注意事项域名备案确保后端API域名已完成ICP备案合法域名配置在小程序后台配置request合法域名权限设置获取用户手机号需要单独申请权限内容安全所有用户生成内容需通过微信内容安全API校验5.3 性能优化实践数据库索引优化borrow_record表的asset_id、user_id字段加索引联合索引(asset_id, status)API响应缓存使用Spring Cache Redis缓存常用查询缓存策略GET请求缓存5分钟POST/PUT/DELETE操作清除相关缓存前端懒加载小程序端分页加载资产列表Android端使用Paging3库实现分页6. 项目扩展方向6.1 物联网集成通过蓝牙/NFC实现资产自动识别无需扫码实时位置追踪使用状态监测如设备温度、电量等6.2 智能预测基于历史数据预测设备故障概率优化采购计划智能分配高需求设备6.3 多平台扩展增加Web管理端VueElementUI开发iOS版本SwiftUI对接企业微信/钉钉平台这个项目从技术架构到业务实现都很有代表性既包含了经典的企业应用开发模式又融入了移动互联网的新特性。我在实际开发中最大的体会是一定要先设计好资产状态流转的完整逻辑这是整个系统的核心骨架。另外双端Android小程序的用户体验一致性也需要特别注意我们最终通过统一的后端API规范和设计模式实现了这一点。
返回列表