1. 项目概述:校园闲置经济的数字化解决方案
校园里每年毕业季堆积如山的二手教材、搬家时带不走的自行车、闲置的健身器材——这些场景催生了我们对校园闲置物品交易系统的思考。传统贴吧、QQ群的信息发布方式存在交易流程不透明、信任机制缺失、物品管理混乱等问题。我们基于Spring Boot框架开发的这套系统,正是为了解决这些痛点。
系统核心定位是为在校师生提供安全便捷的闲置物品交易平台,支持租售两种模式。技术栈选择上,后端采用Spring Boot 2.7 + MyBatis-Plus组合保证开发效率,MySQL 8.0作为主数据库存储交易数据,Redis 6.2用于处理高并发场景下的缓存和会话管理。前端使用Vue 3组合式API开发响应式界面,通过RESTful API与后端交互。
关键设计原则:采用领域驱动设计(DDD)划分商品、订单、用户等核心域,每个域有独立的仓储和服务层。这种架构在后期新增租赁模块时,只需扩展原有商品域而无需重构核心逻辑。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计与技术选型
2.1 分层架构实现
系统采用经典四层架构:
- 表现层:处理HTTP请求和响应格式化,包含:
- 自定义全局异常处理器(@ControllerAdvice)
- 统一API响应包装器(ResponseBodyAdvice)
- 基于JWT的认证过滤器
- 应用层:协调领域对象完成业务逻辑,典型如:
java复制@Transactional public OrderDTO createOrder(OrderRequest request) { Item item = itemRepository.lockItem(request.getItemId()); // 悲观锁 User buyer = userRepository.findById(request.getUserId()); Order order = OrderFactory.create(item, buyer); orderRepository.save(order); return OrderMapper.toDTO(order); } - 领域层:包含商品、订单等聚合根,维护业务规则
- 基础设施层:提供数据库访问(MyBatis-Plus)、缓存(RedisTemplate)等技术支持
2.2 数据库设计要点
MySQL表设计遵循几个原则:
- 交易核心表添加行级锁(SELECT ... FOR UPDATE)
- 商品表采用JSON字段存储动态属性(如电子产品的配置参数)
- 使用触发器自动更新商品状态(当关联订单状态变更时)
典型商品表结构:
sql复制CREATE TABLE `item` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`user_id` BIGINT NOT NULL COMMENT '所属用户',
`title` VARCHAR(100) NOT NULL,
`type` ENUM('sale','rent') NOT NULL,
`price` DECIMAL(10,2) UNSIGNED NOT NULL,
`specs` JSON DEFAULT NULL COMMENT '商品规格',
`status` TINYINT NOT NULL DEFAULT 0,
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user` (`user_id`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
2.3 缓存策略设计
Redis主要承担三类数据缓存:
- 热点商品信息:采用主动更新策略,商品修改时同步更新缓存
- 会话数据:JWT黑名单、用户权限信息,设置TTL自动过期
- 分布式锁:使用Redisson实现商品秒杀场景的互斥访问
缓存键设计示例:
code复制item:detail:{itemId} -> 商品详情缓存
user:perms:{userId} -> 用户权限缓存
lock:order:{itemId} -> 下单分布式锁
3. 核心业务模块实现
3.1 商品发布流程
商品发布涉及的关键技术点:
- 多图上传采用阿里云OSS分片上传,前端生成MD5校验值避免重复传输
- 敏感词过滤使用DFA算法,内存中构建关键词树实现毫秒级检测
- 价格合理性校验:对比同类商品价格均值,偏差过大需人工审核
核心代码逻辑:
java复制public Item publishItem(ItemPublishDTO dto) {
// 敏感词检测
if (sensitiveWordFilter.contains(dto.getTitle())
|| sensitiveWordFilter.contains(dto.getDescription())) {
throw new BusinessException(ErrorCode.CONTENT_SENSITIVE);
}
// 价格校验
BigDecimal avgPrice = itemRepository.getAvgPriceByCategory(dto.getCategory());
if (dto.getPrice().compareTo(avgPrice.multiply(BigDecimal.valueOf(1.5))) > 0) {
dto.setStatus(ItemStatus.PENDING_REVIEW);
}
Item item = ItemMapper.fromDTO(dto);
itemRepository.insert(item);
// 异步处理图片
imageService.asyncUploadImages(item.getId(), dto.getImageUrls());
return item;
}
3.2 交易流程设计
交易状态机设计(简化版):
code复制[待付款] -- 支付超时 --> [已取消]
[待付款] -- 用户支付 --> [待发货]
[待发货] -- 卖家发货 --> [待收货]
[待收货] -- 确认收货 --> [已完成]
[待收货] -- 发起退款 --> [退款中]
分布式事务处理:
- 使用本地消息表保证支付成功后的订单状态更新
- 定时任务补偿处理异常状态(如支付成功但订单未更新)
3.3 租赁模块特殊处理
租赁业务特有的技术实现:
- 档期冲突检测:使用MySQL的日期范围查询
sql复制SELECT COUNT(*) FROM rent_order WHERE item_id = ? AND ((start_time BETWEEN ? AND ?) OR (end_time BETWEEN ? AND ?)) AND status NOT IN ('CANCELLED', 'REJECTED') - 押金管理:单独账户存管,使用资金托管接口
- 自动扣款:基于Quartz实现定时任务扫描待支付账单
4. 性能优化实践
4.1 高并发场景应对
秒杀场景下的技术方案:
- 库存预热:活动前将库存加载到Redis
- 令牌桶限流:Guava RateLimiter控制接口访问
- 请求队列:RabbitMQ削峰填谷
- 库存扣减:Redis原子操作+Lua脚本
lua复制local stock = tonumber(redis.call('GET', KEYS[1])) if stock <= 0 then return 0 end redis.call('DECR', KEYS[1]) return 1
4.2 查询优化策略
-
商品列表页:
- 使用Elasticsearch实现多条件检索
- 默认排序采用综合评分(热度+新鲜度)
- 分页优化:使用游标分页替代传统LIMIT
sql复制SELECT * FROM item WHERE id < ? AND status = 'ON_SALE' ORDER BY id DESC LIMIT 20
-
复杂统计查询:
- 定时任务预计算热门品类
- 使用MySQL窗口函数处理排行榜
- 商品详情页采用字段冗余减少联表查询
5. 安全防护措施
5.1 常见攻击防护
- XSS防护:
- 前端使用DOMPurify净化HTML输入
- 后端Jackson配置HTML转义
- CSRF防护:
- 重要操作要求二次验证(短信/邮箱)
- 敏感接口校验Referer头
- SQL注入:
- 强制使用MyBatis参数绑定
- 定期SQL审计
5.2 业务安全设计
- 防刷单机制:
- 同一设备/IP限购数量
- 交易频率监控
- 敏感操作日志:
- 记录完整操作轨迹
- 关键数据变更保存历史版本
- 隐私保护:
- 联系方式脱敏显示
- 聊天内容端到端加密
6. 部署与监控方案
6.1 容器化部署
Docker Compose编排方案:
yaml复制version: '3'
services:
app:
image: campus-trade:1.0
ports:
- "8080:8080"
depends_on:
- redis
- mysql
redis:
image: redis:6.2-alpine
volumes:
- redis_data:/data
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
volumes:
redis_data:
mysql_data:
6.2 监控体系
- 应用监控:
- Spring Boot Actuator暴露健康指标
- Prometheus采集JVM指标
- 业务监控:
- 关键交易链路日志标记TraceID
- 异常交易行为实时告警
- 性能监控:
- SkyWalking追踪慢SQL
- Grafana展示接口响应时间百分位
7. 典型问题排查实录
7.1 商品图片加载慢
现象:移动端访问时图片加载时间超过3秒
排查过程:
- 检查OSS带宽未达上限
- 发现未开启WebP自动转换
- 部分图片未使用CDN加速
解决方案:
- 配置图片服务自动根据设备返回WebP格式
- 对热门商品图片预生成缩略图
- 启用HTTP/2协议提升并发加载能力
7.2 订单状态不一致
现象:支付成功但订单仍显示"待付款"
根因分析:
- 本地消息表写入成功但MQ消息丢失
- 补偿任务执行间隔过长(原设置5分钟)
优化措施:
- 引入双重检查机制:支付回调时主动查询支付渠道
- 缩短补偿任务间隔至1分钟
- 增加状态不一致告警
经验总结:所有重要状态变更都应设计对账机制,我们后来增加了每日凌晨的全量订单状态校验任务,彻底解决了这类问题。
8. 扩展方向与演进思考
当前系统已支持基础租售功能,后续可考虑:
- 信用体系:接入校园一卡通数据建立用户信用分
- 智能推荐:基于用户专业和浏览历史推荐相关商品
- 物流集成:与校园快递中心API对接实现上门取件
- 区块链存证:将重要交易哈希值上链,增强可信度
技术架构的演进路线:
- 当前:单体应用+基础微服务组件
- 中期:按业务域拆分微服务(商品服务、交易服务等)
- 远期:引入Service Mesh治理服务间通信
在开发过程中最深刻的体会是:校园场景下的系统设计必须平衡技术先进性与实际运维成本。比如我们最初计划使用Elasticsearch实现全文搜索,但考虑到服务器资源有限,最终采用MySQL全文索引+关键词预热的方案,在保证基本可用的前提下大幅降低了运维复杂度。
