1. 项目背景与核心价值
垃圾分类已成为现代城市管理的刚性需求。以上海为例,自2019年强制垃圾分类实施以来,全市日均分出可回收物较政策实施前增长4.6倍。但传统纸质宣传手册和线下督导模式存在信息更新滞后、覆盖范围有限等问题。这正是我们开发基于SpringBoot的垃圾分类网站的技术背景。
这个项目本质上是一个B/S架构的智能分类决策系统,其核心价值体现在三个维度:
- 对居民用户:提供实时分类查询、投放点导航、积分兑换等便民服务
- 对管理部门:实现政策宣传、数据统计、违规行为公示等管理功能
- 对运维人员:具备垃圾清运路线优化、满溢报警等智能调度能力
从技术选型角度看,采用SpringBoot框架具有显著优势。我们实测对比发现,与传统SSM框架相比:
- 启动时间缩短63%(2.8s vs 7.6s)
- 内存占用降低41%(128MB vs 217MB)
- 接口响应速度提升35%
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术栈选型
整套系统采用经典的三层架构,具体技术组件如下:
| 层级 | 技术选型 | 版本 | 选型理由 |
|---|---|---|---|
| 前端 | Thymeleaf + Bootstrap | 3.1.0 | 天然适配SpringBoot,SEO友好,减少前后端分离带来的跨域问题 |
| 后端框架 | SpringBoot | 3.1.5 | 自动配置、内嵌Tomcat、健康检查等开箱即用特性大幅提升开发效率 |
| 持久层 | MyBatis-Plus | 3.5.3.1 | 强大的CRUD封装,动态表名支持便于多小区数据隔离 |
| 数据库 | MySQL | 8.0.33 | 社区活跃,Window函数支持完善,适合统计分析场景 |
| 缓存 | Redis | 7.0.11 | 高频查询缓存(如分类规则)使QPS从120提升至2100 |
| 搜索 | Elasticsearch | 8.9.0 | 模糊搜索响应时间从320ms降至28ms |
| 消息队列 | RabbitMQ | 3.11.13 | 解耦清运任务调度与主业务流程 |
提示:实际开发中我们发现MyBatis-Plus的Lambda查询方式在多表关联时存在局限性,最终采用XML映射文件+注解的混合模式解决复杂查询需求。
2.2 数据库设计
核心表结构设计遵循垃圾分类业务特征:
sql复制CREATE TABLE `garbage_category` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT '可回收物/有害垃圾...',
`icon_url` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`sort_order` int DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
CREATE TABLE `garbage_item` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT '物品名称',
`category_id` int NOT NULL,
`keywords` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '搜索关键词',
`dispose_method` text COLLATE utf8mb4_bin COMMENT '处理方法',
PRIMARY KEY (`id`),
FULLTEXT KEY `ft_idx` (`name`,`keywords`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
关键设计要点:
- 采用utf8mb4字符集支持emoji表情搜索(如"💊属于什么垃圾")
- 为垃圾物品表建立全文索引,提升模糊匹配效率
- 分类图标单独存储URL,便于CDN加速
3. 核心功能实现
3.1 智能分类查询
分类算法采用HanLP分词+规则引擎双校验模式:
java复制public CategoryResult classify(String userInput) {
// 预处理
String processed = TextPreprocessor.clean(userInput);
// 精确匹配优先
GarbageItem item = itemMapper.selectOne(
new LambdaQueryWrapper<GarbageItem>()
.eq(GarbageItem::getName, processed));
if(item != null) {
return buildResult(item);
}
// 语义分析
List<Term> terms = HanLP.segment(processed);
String keyword = extractKeyword(terms);
// 模糊查询
List<GarbageItem> candidates = itemMapper.selectList(
new QueryWrapper<GarbageItem>()
.like("keywords", keyword));
// 相似度计算
return findMostSimilar(processed, candidates);
}
实测中遇到的典型问题及解决方案:
- 同义词处理:建立别名映射表(如"电池→蓄电池")
- 方言转换:配置自定义词典(如"么斯→什么"武汉方言)
- 错别字容错:采用拼音相似度辅助判断
3.2 积分激励系统
积分规则引擎采用状态模式实现:
java复制public interface PointsStrategy {
int calculatePoints(UserAction action);
}
@Component
@Qualifier("recyclePoints")
public class RecyclePoints implements PointsStrategy {
@Override
public int calculatePoints(UserAction action) {
// 根据重量、分类准确度等计算
return (int)(action.getWeight() *
accuracyFactor(action.getCategory()));
}
}
// 使用示例
@Autowired
private Map<String, PointsStrategy> strategyMap;
public void addPoints(UserAction action) {
PointsStrategy strategy = strategyMap.get(action.getType() + "Points");
int points = strategy.calculatePoints(action);
// 更新用户积分...
}
积分兑换采用TCC分布式事务保证数据一致性:
- Try阶段:预扣库存
- Confirm阶段:实际扣减
- Cancel阶段:恢复预扣
4. 部署与性能优化
4.1 Docker Compose部署方案
yaml复制version: '3.8'
services:
app:
image: garbage-classification:1.0
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- redis
- mysql
mysql:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=yourpassword
- MYSQL_DATABASE=garbage_db
redis:
image: redis:7.0
ports:
- "6379:6379"
4.2 性能调优实战
通过Arthas工具诊断发现的性能瓶颈及优化措施:
-
分类查询接口优化
- 问题:频繁访问MySQL导致平均RT达到420ms
- 方案:引入二级缓存(Caffeine+Redis)
- 效果:P99从780ms降至95ms
-
图片加载优化
- 问题:分类图标平均加载时间1.2s
- 方案:
- 使用WebP格式(体积减少65%)
- 配置Nginx静态资源缓存
- 效果:加载时间降至280ms
-
JVM参数调整
bash复制JAVA_OPTS="-Xms512m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=35"调整后GC时间从1.4s/次降至0.3s/次
5. 特色功能扩展
5.1 AR识别辅助
集成百度AR SDK实现垃圾图像识别:
java复制public ARResult recognize(MultipartFile image) {
// 调用百度AR接口
String base64 = Base64.getEncoder()
.encodeToString(image.getBytes());
ARRequest request = new ARRequest(base64);
// 结果映射到垃圾类别
ARResponse response = arClient.recognize(request);
return convertToCategory(response);
}
开发中遇到的坑:
- 安卓端图片旋转问题:通过EXIF信息校正方向
- 相似物品误判:增加置信度阈值(实测0.7最佳)
- 光照影响:建议用户拍摄时打开闪光灯
5.2 微信小程序对接
采用SpringBoot+WxJava实现:
java复制@GetMapping("/wx/auth")
public String auth(@RequestParam String code) {
// 获取openid
WxMpOAuth2AccessToken token = wxService
.getOAuth2Service().getAccessToken(code);
// 查询或创建用户
User user = userService.getOrCreate(token.getOpenId());
// 生成JWT
return jwtUtil.generateToken(user);
}
注意事项:
- 敏感接口需配置IP白名单
- 用户unionid获取需要额外资质审核
- 模板消息改为订阅消息后需要重新设计交互流程
这个项目从技术角度看最值得分享的经验是:在业务规则频繁变更的场景下(如垃圾分类标准调整),采用策略模式+规则引擎的设计,配合数据库的版本化配置表,可以使系统在不重启的情况下动态更新分类规则。我们通过这种设计将政策响应时间从原来的2周缩短至2小时。
