1. 校园易物系统的现实需求与技术选型
校园二手交易一直是个高频刚需场景。每到毕业季,大量教材、电器、生活用品被低价抛售;而新生入学时,又急需采购这些物品。传统的信息发布方式(如微信群、公告栏)存在信息杂乱、沟通低效、缺乏信任机制等问题。我去年参与开发的校园多方易物系统,正是为了解决这些痛点。
技术栈选择上,后端采用Spring Boot 2.7 + MyBatis-Plus的组合。Spring Boot的自动配置特性让项目初始化时间缩短了60%,内置Tomcat容器省去了传统War包部署的繁琐。MyBatis-Plus的Lambda表达式写法让数据库操作代码量减少40%,其强大的代码生成器更是直接生成了80%的基础CRUD代码。
前端选用Vue 3 + Element Plus。Vue的响应式特性特别适合交易类页面的实时状态更新,比如商品库存变化、订单状态流转等场景。Element Plus的表格和表单组件经过二次封装后,开发效率提升明显。
数据库选用MySQL 8.0,主要考虑到:
- 校园场景下数据量通常在10万条以内
- 事务操作频繁(如商品库存扣减)
- 需要全文检索支持(通过MySQL的ngram分词器实现)
踩坑提示:初期尝试用MongoDB存储商品信息,但在处理事务性操作(如库存扣减)时遇到并发问题,最终回退到MySQL方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统核心模块设计与实现
2.1 用户权限分级设计
系统采用RBAC(基于角色的访问控制)模型,设计了四层角色结构:
| 角色 | 权限说明 | 接口示例 |
|---|---|---|
| 游客 | 浏览商品、搜索 | /api/goods/list |
| 普通用户 | 发布商品、交易 | /api/order/create |
| 管理员 | 内容审核、用户管理 | /api/admin/audit |
| 超级管理员 | 系统配置、权限分配 | /api/root/config-update |
权限校验通过Spring Security + JWT实现。关键代码片段:
java复制@PreAuthorize("hasRole('USER')")
@PostMapping("/order/create")
public Result createOrder(@Valid @RequestBody OrderDTO dto) {
// 订单创建逻辑
}
2.2 商品交易流程实现
完整的交易状态机包含6个核心状态:
- 待审核(新发布)
- 已上架(审核通过)
- 交易中(有用户下单)
- 已完成(双方确认)
- 已取消(主动撤销)
- 违规下架(管理员操作)
使用Spring State Machine实现状态流转:
java复制@WithStateMachine
public class OrderStateListener {
@OnTransition(source = "CREATED", target = "PAID")
public void payTransition() {
// 扣减库存等操作
}
}
2.3 即时通讯方案选型
最初考虑WebSocket全双工方案,但实测发现:
- 校园网环境下长连接不稳定
- 移动端频繁切换网络导致重连
最终采用降级方案:HTTP轮询 + 本地缓存。前端每15秒请求一次消息接口,配合Redis的Sorted Set存储未读消息,关键实现:
java复制public List<Message> getNewMessages(Long userId, Long lastMsgId) {
String key = "msg:" + userId;
return redisTemplate.opsForZSet()
.rangeByScore(key, lastMsgId, Double.MAX_VALUE);
}
3. 性能优化实战记录
3.1 缓存策略设计
采用三级缓存架构:
- 本地Caffeine缓存(商品详情)
- Redis集群缓存(热门列表)
- MySQL持久层(全量数据)
缓存更新策略对比测试:
| 策略 | QPS | 数据一致性 | 实现复杂度 |
|---|---|---|---|
| 主动更新 | 3200 | 强 | 高 |
| 过期失效 | 4500 | 弱 | 低 |
| 结合版本号 | 3800 | 最终一致 | 中 |
最终选择版本号方案,核心代码:
java复制@CachePut(value = "goods", key = "#good.id", condition = "#good.version > cacheVersion")
public Good updateGood(Good good) {
// 更新数据库
}
3.2 图片存储优化
初期使用本地存储遇到问题:
- 学生上传的图片平均大小1.8MB
- 日访问量峰值时带宽吃紧
改进方案:
- 前端使用Compressor.js压缩图片(300KB以内)
- 七牛云OSS存储静态资源
- 通过WebP格式转换节省30%流量
配置示例:
properties复制# application-oss.properties
qiniu.access-key=your_ak
qiniu.secret-key=your_sk
qiniu.bucket=your_bucket
qiniu.domain=https://img.yourdomain.com
4. 典型问题排查实录
4.1 事务失效场景
遇到最隐蔽的问题是@Transactional注解失效,最终定位到三个原因:
- 同类方法内调用(未走代理)
java复制public void createOrder() {
this.updateStock(); // 事务失效
}
@Transactional
public void updateStock() {...}
- 异常类型不匹配
java复制@Transactional(rollbackFor = BusinessException.class)
void method() throws Exception {
// 抛出其他异常不会回滚
}
- 数据库引擎不是InnoDB
解决方案:
- 通过AopContext.currentProxy()获取代理对象
- 统一使用@Transactional(rollbackFor = Exception.class)
- 建表时显式指定ENGINE=InnoDB
4.2 并发超卖问题
使用乐观锁解决库存扣减问题:
sql复制UPDATE goods
SET stock = stock - 1, version = version + 1
WHERE id = ? AND version = ? AND stock > 0
配合Redis分布式锁防止重复提交:
java复制String lockKey = "lock:order:" + userId;
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
if (!locked) {
throw new BusinessException("操作太频繁");
}
5. 部署与监控方案
5.1 多环境配置
通过Profile实现环境隔离:
code复制application-dev.properties # 开发环境
application-test.properties # 测试环境
application-prod.properties # 生产环境
启动时指定环境:
bash复制java -jar campus-trade.jar --spring.profiles.active=prod
5.2 Prometheus监控
关键监控指标配置:
yaml复制# application.yml
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
tags:
application: ${spring.application.name}
监控看板重点关注:
- 接口成功率(<99%告警)
- JVM内存使用(>80%告警)
- 慢SQL数量(>5次/分钟告警)
6. 项目扩展方向
- 信用积分体系设计:
java复制public class CreditService {
@Transactional
public void addCredit(Long userId, int points) {
// 积分变更记录
creditRecordMapper.insert(...);
// 更新总积分(需考虑并发)
userMapper.updateCredit(userId, points);
}
}
- 物流跟踪集成:
- 对接快递鸟API实现运单查询
- 使用Redis GEO存储自提点位置信息
- 推荐算法优化:
sql复制-- 基于协同过滤的SQL实现
SELECT * FROM goods
WHERE category IN (
SELECT category FROM orders
WHERE user_id = ?
GROUP BY category
ORDER BY COUNT(*) DESC
LIMIT 3
)
ORDER BY create_time DESC
这个项目让我深刻体会到,校园场景的技术方案需要特别考虑:
- 网络环境的不稳定性
- 用户行为的季节性波动
- 硬件资源的有限性
下次如果再开发类似系统,我会优先考虑引入GraalVM原生镜像编译,进一步降低服务器资源消耗
