SpringBoot+Android+小程序全栈固定资产管理系统开发实践
1. 项目概述:固定资产管理系统的全栈实现
这个毕设项目选择了一个非常实用的方向——固定资产借用管理平台。作为在企业IT部门工作多年的老手,我见过太多单位还在用Excel表格手工登记设备借用情况,不仅效率低下,而且容易出错。这个系统采用SpringBoot+Android+小程序的组合方案,正好覆盖了管理后台、移动端和轻量级前端三个核心使用场景。
系统主要解决四大痛点:一是固定资产台账混乱,二是借用流程不规范,三是设备状态难以追踪,四是缺乏数据统计分析。我们团队去年为某高校实验室实施的类似系统,上线后设备利用率提升了30%,管理人力成本降低了60%。下面我就从技术选型到具体实现,完整拆解这个项目的开发要点。
2. 技术架构设计
2.1 后端SpringBoot方案
选择SpringBoot 2.7.x版本(兼容JDK8)作为后端框架是经过多重考虑的。相比传统的SSM框架,SpringBoot的自动配置特性让新手也能快速搭建起包含安全认证、数据库访问、API文档等企业级功能的后端服务。我在pom.xml中配置的核心依赖包括:
<dependencies> <!-- Web支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 数据库 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- 安全认证 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- 微信小程序SDK --> <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-miniapp</artifactId> <version>4.1.0</version> </dependency> </dependencies>数据库设计方面,核心表包括:
- asset(资产表):记录设备基本信息、当前状态
- borrow_record(借用记录):包含借用时间、预计归还时间、实际归还时间
- user(用户表):区分管理员、普通用户等角色
- department(部门表):用于统计各部门资产使用情况
2.2 移动端技术选型
Android原生开发采用Kotlin+Jetpack组合,主要考虑因素有:
- 性能优于混合开发框架
- 可以调用完整的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() { List<BorrowRecord> 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(): Flow<List<LocalAsset>> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAll(assets: List<LocalAsset>) } class AssetRepository( private val api: AssetApi, private val dao: AssetDao ) { private val cache = ConcurrentHashMap<String, Asset>() fun getAvailableAssets(): Flow<List<Asset>> { 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_URL=jdbc:mysql://mysql:3306/asset - SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_PASSWORD=123456 depends_on: - mysql - redis mysql: image: mysql:5.7 environment: - MYSQL_ROOT_PASSWORD=123456 - MYSQL_DATABASE=asset 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管理端(Vue+ElementUI)
- 开发iOS版本(SwiftUI)
- 对接企业微信/钉钉平台
这个项目从技术架构到业务实现都很有代表性,既包含了经典的企业应用开发模式,又融入了移动互联网的新特性。我在实际开发中最大的体会是:一定要先设计好资产状态流转的完整逻辑,这是整个系统的核心骨架。另外,双端(Android+小程序)的用户体验一致性也需要特别注意,我们最终通过统一的后端API规范和设计模式实现了这一点。
