1. 项目概述
社区旧衣物回收与捐赠系统是一个基于SpringBoot+Vue技术栈开发的公益类Web应用,旨在为社区居民提供便捷的旧衣物回收与捐赠渠道。系统采用前后端分离架构,后端使用SpringBoot框架搭建RESTful API服务,前端采用Vue.js实现响应式用户界面,数据库选用MySQL进行数据存储。
这个系统解决了传统衣物回收方式存在的几个痛点:一是回收渠道不透明,居民难以了解衣物的最终去向;二是捐赠流程繁琐,需要亲自送到指定地点;三是缺乏信息化管理,难以统计回收数据。通过本系统,居民可以足不出户完成衣物捐赠,管理员也能实时掌握回收情况,实现资源的优化配置。
2. 系统架构设计
2.1 技术选型解析
后端技术栈:
- Spring Boot 2.7.x:作为基础框架,提供自动配置、依赖注入等特性
- MyBatis-Plus 3.5.x:简化数据库操作,内置通用CRUD方法
- Shiro 1.10.x:负责认证授权,保障系统安全
- Redis 6.x:用于缓存热点数据,提升系统响应速度
- Swagger 3.0:自动生成API文档,方便前后端协作
前端技术栈:
- Vue 3.x:采用Composition API编写组件
- Element Plus:UI组件库,快速构建美观界面
- Axios:处理HTTP请求,与后端API交互
- Vue Router:实现前端路由管理
- Pinia:状态管理库,替代Vuex
数据库:
- MySQL 8.0:关系型数据库,存储业务数据
- 采用InnoDB引擎,支持事务处理
- 配置读写分离,提升数据库性能
2.2 系统架构图
系统采用典型的三层架构:
code复制┌───────────────────────────────────────┐
│ 客户端层 │
│ ┌───────────┐ ┌─────────────┐ │
│ │ Web浏览器 │ │ 移动端(H5) │ │
│ └───────────┘ └─────────────┘ │
└───────────────────────────────────────┘
▲
│ HTTP/HTTPS
▼
┌───────────────────────────────────────┐
│ 应用服务层 │
│ ┌───────────┐ ┌─────────────┐ │
│ │ Spring Boot │ │ 业务逻辑层 │ │
│ └───────────┘ └─────────────┘ │
└───────────────────────────────────────┘
▲
│ JDBC/MyBatis
▼
┌───────────────────────────────────────┐
│ 数据存储层 │
│ ┌───────────┐ ┌─────────────┐ │
│ │ MySQL主库 │ ◄───► │ MySQL从库 │ │
│ └───────────┘ └─────────────┘ │
└───────────────────────────────────────┘
2.3 核心设计模式
MVC模式实现:
- Model层:使用MyBatis-Plus的BaseMapper和Entity类,简化数据访问
- View层:Vue组件负责渲染界面,通过Axios与后端交互
- Controller层:Spring的@RestController处理HTTP请求,返回JSON数据
领域驱动设计(DDD)应用:
- 将系统划分为捐赠者、回收员、管理员等界限上下文
- 使用聚合根管理衣物捐赠的生命周期
- 领域事件用于处理状态变更通知
3. 核心功能模块实现
3.1 用户认证模块
JWT认证流程:
- 用户登录成功后,后端生成包含用户ID和角色的JWT token
- 前端将token存储在localStorage中
- 每次请求通过Authorization头携带token
- 后端通过Shiro的JwtFilter验证token有效性
关键代码示例:
java复制// JWT工具类
public class JwtUtil {
private static final String SECRET = "your-secret-key";
private static final long EXPIRE = 86400L; // 24小时
public static String generateToken(Long userId, String role) {
return Jwts.builder()
.setSubject(userId.toString())
.claim("role", role)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE * 1000))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public static Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
}
}
权限控制实现:
- 基于Shiro的注解式权限控制
- 自定义Realm加载用户角色和权限
- 前端通过v-permission指令控制按钮级权限
3.2 衣物捐赠模块
捐赠流程:
- 用户填写捐赠表单(衣物类型、数量、取件地址等)
- 系统生成捐赠订单,状态为"待确认"
- 回收员接单后,状态变更为"已接单"
- 回收员完成取件,状态变更为"已完成"
数据库表设计:
sql复制CREATE TABLE `donation_order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '捐赠用户ID',
`recycler_id` bigint DEFAULT NULL COMMENT '回收员ID',
`clothes_type` varchar(50) NOT NULL COMMENT '衣物类型',
`quantity` int NOT NULL COMMENT '数量',
`address` varchar(255) NOT NULL COMMENT '取件地址',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0-待确认 1-已接单 2-已完成',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_recycler_id` (`recycler_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='捐赠订单表';
状态机设计:
使用枚举定义订单状态和流转规则:
java复制public enum OrderStatus {
PENDING(0, "待确认") {
@Override
public boolean canTransferTo(OrderStatus status) {
return status == ACCEPTED;
}
},
ACCEPTED(1, "已接单") {
@Override
public boolean canTransferTo(OrderStatus status) {
return status == COMPLETED;
}
},
COMPLETED(2, "已完成") {
@Override
public boolean canTransferTo(OrderStatus status) {
return false;
}
};
// 省略其他代码...
}
3.3 回收管理模块
回收员接单逻辑:
- 系统根据回收员位置和负载分配订单
- 采用Redis的Geo功能实现就近分配
- 使用ZSET记录回收员当前任务数,实现负载均衡
关键实现代码:
java复制public class OrderDispatchService {
private final RedisTemplate<String, String> redisTemplate;
@Async
public void dispatchOrder(Long orderId, Double lng, Double lat) {
// 1. 查找5公里范围内的空闲回收员
String geoKey = "recycler:geo";
String loadKey = "recycler:load";
GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo()
.radius(geoKey, new Circle(new Point(lng, lat),
new Distance(5, Metrics.KILOMETERS)));
// 2. 选择负载最小的回收员
String bestRecycler = results.getContent().stream()
.min(Comparator.comparing(
geo -> redisTemplate.opsForZSet().score(loadKey, geo.getContent().getName())))
.map(geo -> geo.getContent().getName())
.orElse(null);
// 3. 分配订单并更新负载
if (bestRecycler != null) {
redisTemplate.opsForZSet().incrementScore(loadKey, bestRecycler, 1);
orderService.assignRecycler(orderId, Long.parseLong(bestRecycler));
}
}
}
4. 系统优化与安全
4.1 性能优化措施
缓存策略:
- 使用Redis缓存热点数据:用户信息、衣物类型等
- 采用Spring Cache抽象,通过注解实现缓存
- 配置合理的过期时间,避免脏数据
SQL优化:
- 为所有查询条件添加合适索引
- 使用EXPLAIN分析慢查询
- 避免SELECT *,只查询必要字段
- 大数据量表采用分页查询
前端优化:
- 使用Vue的keep-alive缓存组件
- 路由懒加载减少首屏资源
- 图片使用WebP格式,体积更小
- 开启Gzip压缩传输
4.2 安全防护方案
输入验证:
- 后端对所有API参数进行校验
- 使用Hibernate Validator进行Bean验证
- 防范SQL注入:使用MyBatis参数绑定
安全配置:
- 启用HTTPS,配置HSTS
- 设置CSP头防止XSS攻击
- 使用CSRF Token防御跨站请求伪造
- 密码采用BCrypt加密存储
审计日志:
- 记录关键操作:登录、订单状态变更等
- 使用AOP统一记录操作日志
- 日志包含操作人、时间、IP等信息
- 日志文件按天归档,保留180天
5. 部署与运维
5.1 生产环境部署
服务器配置建议:
- 应用服务器:2核4G,CentOS 7.x
- 数据库服务器:4核8G,SSD存储
- Redis服务器:2核4G,关闭持久化
Docker部署方案:
dockerfile复制# Dockerfile示例
FROM openjdk:11-jre
COPY target/clothes-donation.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Nginx配置:
nginx复制server {
listen 80;
server_name donation.example.com;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://app-server:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
5.2 监控与告警
监控指标:
- 应用指标:JVM内存、GC次数、线程数
- 业务指标:订单创建量、完成率
- 系统指标:CPU、内存、磁盘使用率
Prometheus配置:
yaml复制scrape_configs:
- job_name: 'springboot'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['app-server:8080']
告警规则示例:
yaml复制groups:
- name: example
rules:
- alert: HighErrorRate
expr: rate(http_server_requests_errors_total[1m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.instance }}"
description: "Error rate is {{ $value }}"
6. 开发经验与技巧
6.1 前后端协作实践
API设计规范:
- RESTful风格,资源使用复数名词
- 统一响应格式:
json复制{
"code": 200,
"message": "success",
"data": {...}
}
- 使用Swagger维护API文档
- 版本控制:URL中携带/v1/前缀
联调技巧:
- 使用Mock.js模拟后端API
- 约定错误码规范
- 定期同步接口变更
- 使用Postman共享接口集合
6.2 常见问题解决
跨域问题:
- 后端配置CORS:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
- Nginx反向代理解决
- 开发环境可配置Webpack代理
事务管理:
- 声明式事务:
java复制@Transactional(rollbackFor = Exception.class)
public void completeOrder(Long orderId) {
// 业务逻辑
}
- 避免事务中调用远程服务
- 合理设置事务隔离级别
并发控制:
- 乐观锁实现:
java复制@Version
private Integer version;
- 分布式锁:
java复制public boolean tryLock(String key, long expire) {
return redisTemplate.opsForValue()
.setIfAbsent(key, "1", expire, TimeUnit.SECONDS);
}
7. 项目扩展方向
7.1 功能扩展建议
- 积分商城:捐赠衣物获得积分,兑换礼品
- 衣物溯源:区块链记录衣物流转过程
- 智能调度:算法优化回收路线
- 微信小程序:拓展移动端入口
- 数据分析:可视化展示回收效果
7.2 技术演进路线
- 微服务化:Spring Cloud拆分单体应用
- 容器化:Kubernetes管理容器集群
- Serverless:非核心功能使用云函数
- AI应用:图像识别自动分类衣物
- IoT集成:智能回收箱数据对接
在实际开发过程中,我们发现合理的模块划分和清晰的接口定义能显著提高开发效率。特别是在处理捐赠订单状态流转时,采用状态机模式比简单的if-else更易于维护和扩展。另外,对于公益类系统,数据可视化展示回收成果对提升用户参与度有很大帮助,这部分值得投入更多精力优化。