1. 项目概述
"家政服务撮合与评价平台"是一个典型的O2O(Online To Offline)服务类应用,采用前后端分离架构实现。前端使用Vue.js构建响应式用户界面,后端基于SpringBoot框架提供RESTful API服务,数据库采用MySQL关系型数据库。平台核心功能包括服务人员信息展示、在线预约、订单管理、支付对接、评价反馈等模块。
这个项目最核心的价值在于解决了传统家政服务行业存在的三大痛点:信息不对称导致的匹配效率低下、服务质量缺乏量化标准、纠纷处理缺乏依据。通过数字化平台将服务提供方和需求方直接连接,配合评价体系形成闭环,能显著提升行业整体服务水平和用户体验。
2. 技术架构设计
2.1 整体架构设计
平台采用经典的三层架构:
- 表现层:Vue 3.x + Element Plus
- 业务逻辑层:SpringBoot 2.7 + MyBatis-Plus
- 数据持久层:MySQL 8.0 + Redis缓存
这种架构选择主要基于以下考虑:
- Vue的响应式特性和组件化开发非常适合构建动态交互频繁的C端应用
- SpringBoot的自动配置和起步依赖能快速构建微服务
- MyBatis-Plus在传统ORM基础上提供了更便捷的CRUD操作
- MySQL关系型数据库能很好处理订单、评价等结构化数据
- Redis用于缓存热门服务人员和常用数据,减轻数据库压力
2.2 关键技术选型解析
2.2.1 前端技术栈
- Vue 3.x:采用Composition API写法,代码组织更清晰
- Vue Router:实现前端路由和权限控制
- Vuex/Pinia:状态管理,共享用户登录态等全局数据
- Element Plus:提供丰富的UI组件,加速开发
- Axios:处理HTTP请求,封装了请求拦截和响应拦截
- ECharts:用于展示服务人员评分分布等数据可视化
2.2.2 后端技术栈
- SpringBoot 2.7:快速构建RESTful API
- Spring Security:认证和授权管理
- MyBatis-Plus:增强的ORM框架
- Lombok:简化POJO编写
- Hutool:Java工具包,提供各种便捷方法
- Swagger:API文档自动生成
- Redis:缓存热点数据和分布式锁实现
3. 核心功能实现
3.1 服务撮合算法实现
撮合算法是平台的核心竞争力,我们实现了基于多维度匹配的智能推荐:
java复制// 服务人员推荐算法示例
public List<Worker> recommendWorkers(ServiceRequest request) {
// 基础筛选:服务类型、地理位置
QueryWrapper<Worker> query = new QueryWrapper<>()
.eq("service_type", request.getServiceType())
.apply("ST_Distance(location, ST_GeomFromText({0})) < {1}",
request.getLocation().toText(), MAX_DISTANCE);
// 获取符合条件的候选人
List<Worker> candidates = workerMapper.selectList(query);
// 多维度评分
candidates.forEach(worker -> {
// 评分维度1:距离分(越近分越高)
double distanceScore = 1 - (worker.getDistance() / MAX_DISTANCE);
// 评分维度2:评价分(平均评分)
double ratingScore = worker.getAvgRating() / 5.0;
// 评分维度3:接单率
double acceptRateScore = worker.getAcceptRate();
// 加权计算总分
worker.setRecommendScore(
0.4 * distanceScore +
0.4 * ratingScore +
0.2 * acceptRateScore
);
});
// 按总分排序返回
return candidates.stream()
.sorted(Comparator.comparing(Worker::getRecommendScore).reversed())
.limit(MAX_RECOMMEND)
.collect(Collectors.toList());
}
3.2 评价系统设计
评价系统采用多维度打分+文字评价的模式:
sql复制CREATE TABLE `rating` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_id` bigint NOT NULL COMMENT '关联订单ID',
`worker_id` bigint NOT NULL COMMENT '服务人员ID',
`customer_id` bigint NOT NULL COMMENT '客户ID',
`punctuality_score` tinyint DEFAULT NULL COMMENT '守时分数1-5',
`quality_score` tinyint DEFAULT NULL COMMENT '服务质量1-5',
`attitude_score` tinyint DEFAULT NULL COMMENT '服务态度1-5',
`overall_score` decimal(2,1) GENERATED ALWAYS AS
((punctuality_score + quality_score + attitude_score) / 3) STORED COMMENT '综合评分',
`comment` varchar(500) DEFAULT NULL COMMENT '文字评价',
`picture_urls` varchar(1000) DEFAULT NULL COMMENT '评价图片URL,多个用逗号分隔',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_worker_id` (`worker_id`),
KEY `idx_order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.3 订单状态机实现
订单状态流转是业务核心逻辑,我们采用状态模式实现:
java复制public interface OrderState {
void confirm(Order order);
void cancel(Order order);
void complete(Order order);
void pay(Order order);
}
@Service
@RequiredArgsConstructor
public class OrderContext {
private OrderState state;
public void setState(OrderState state) {
this.state = state;
}
public void confirm() {
state.confirm(this);
}
// 其他操作方法...
}
@Service
@Scope("prototype")
public class PendingState implements OrderState {
@Override
public void confirm(Order order) {
// 更新订单状态为已确认
order.setStatus(OrderStatus.CONFIRMED);
orderRepository.update(order);
// 通知服务人员
notificationService.notifyWorker(order.getWorkerId(),
"您的订单已被确认,请按时提供服务");
// 状态流转
order.getContext().setState(applicationContext.getBean(ConfirmedState.class));
}
// 其他状态方法实现...
}
4. 关键问题与解决方案
4.1 高并发预约问题
家政服务经常出现热门服务人员被多人同时预约的情况,我们采用以下方案解决:
- 乐观锁控制:
java复制@Transactional
public boolean reserveService(Long workerId, Long customerId) {
// 1. 查询服务人员当前可预约状态
Worker worker = workerMapper.selectById(workerId);
if (worker.getAvailableSlots() <= 0) {
return false;
}
// 2. 尝试占用名额(CAS操作)
int updated = workerMapper.updateAvailableSlots(
workerId,
worker.getAvailableSlots(),
worker.getAvailableSlots() - 1,
worker.getVersion()
);
// 3. 更新成功才创建订单
if (updated > 0) {
createOrder(workerId, customerId);
return true;
}
return false;
}
- Redis分布式锁:
java复制public boolean reserveWithLock(Long workerId, Long customerId) {
String lockKey = "worker_reserve:" + workerId;
String requestId = UUID.randomUUID().toString();
try {
// 尝试获取锁
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, requestId, 30, TimeUnit.SECONDS);
if (!locked) {
return false;
}
// 执行业务逻辑
return reserveService(workerId, customerId);
} finally {
// 释放锁
String currentValue = redisTemplate.opsForValue().get(lockKey);
if (requestId.equals(currentValue)) {
redisTemplate.delete(lockKey);
}
}
}
4.2 评价系统的防刷机制
为防止恶意刷评价,我们实现了以下防护措施:
- 基于订单的评价:只有已完成且未评价过的订单才能评价
- 频率限制:同一用户短时间内只能评价有限次数
- 敏感词过滤:评价内容经过敏感词库过滤
- 图片验证:上传的评价图片需通过内容审核
- 行为分析:检测异常评价模式(如大量相似评价)
实现代码片段:
java复制@Transactional
public RatingResult submitRating(RatingRequest request) {
// 1. 验证订单状态
Order order = orderService.getById(request.getOrderId());
if (order.getStatus() != OrderStatus.COMPLETED) {
throw new BusinessException("订单未完成,不能评价");
}
if (order.getIsRated()) {
throw new BusinessException("该订单已评价过");
}
// 2. 检查评价频率
String rateLimitKey = "rate_limit:" + request.getCustomerId();
Long count = redisTemplate.opsForValue().increment(rateLimitKey, 1);
if (count != null && count == 1) {
redisTemplate.expire(rateLimitKey, 24, TimeUnit.HOURS);
}
if (count > MAX_RATE_PER_DAY) {
throw new BusinessException("评价过于频繁,请稍后再试");
}
// 3. 敏感词过滤
String filteredComment = sensitiveWordFilter.filter(request.getComment());
// 4. 保存评价
Rating rating = new Rating();
// 设置各项属性...
ratingMapper.insert(rating);
// 5. 更新订单评价状态
order.setIsRated(true);
orderMapper.updateById(order);
// 6. 更新服务人员综合评分
updateWorkerOverallRating(request.getWorkerId());
return new RatingResult(true, "评价成功");
}
5. 性能优化实践
5.1 数据库优化
-
索引优化:
- 为所有查询条件字段添加合适索引
- 使用复合索引减少回表
- 示例:服务人员列表查询索引
sql复制ALTER TABLE worker ADD INDEX idx_search (service_type, area_id, is_verified, avg_rating); -
查询优化:
- 避免SELECT *,只查询必要字段
- 复杂查询使用JOIN优化
- 大数据量表使用分页查询
-
读写分离:
- 写操作走主库
- 读操作走从库
- 使用Spring AbstractRoutingDataSource实现动态数据源切换
5.2 缓存策略
-
多级缓存架构:
- 本地缓存(Caffeine):缓存用户基本信息等变化不频繁的数据
- Redis缓存:缓存热门服务人员列表、评价统计等数据
- 数据库:持久化存储
-
缓存更新策略:
- 写操作时双删缓存(先删后更新再删)
- 设置合理的过期时间
- 热点数据永不过期,通过后台任务定期更新
-
缓存穿透防护:
- 布隆过滤器过滤非法ID查询
- 对空结果也进行缓存,设置较短过期时间
示例代码:
java复制@Cacheable(value = "workers", key = "#workerId", unless = "#result == null")
public Worker getWorkerById(Long workerId) {
// 先检查布隆过滤器
if (!bloomFilter.mightContain(workerId)) {
return null;
}
Worker worker = workerMapper.selectById(workerId);
if (worker == null) {
// 将空结果也缓存,防止缓存穿透
return null;
}
return worker;
}
@CacheEvict(value = "workers", key = "#worker.id")
public void updateWorker(Worker worker) {
workerMapper.updateById(worker);
// 异步更新其他相关缓存
asyncTask.updateRelatedCache(worker.getId());
}
6. 安全防护措施
6.1 常见Web安全防护
-
XSS防护:
- 前端使用vue-sanitize过滤HTML内容
- 后端对用户输入进行转义处理
- 设置HttpOnly的Cookie
-
CSRF防护:
- 使用Spring Security的CSRF防护
- 敏感操作增加二次验证
-
SQL注入防护:
- 使用MyBatis预编译语句
- 禁止拼接SQL语句
- 使用Wrapper条件构造器
-
数据加密:
- 敏感信息如密码使用BCrypt加密
- 传输数据使用HTTPS
- 数据库敏感字段加密存储
6.2 业务安全防护
-
防薅羊毛:
- 新用户优惠券限制领取数量
- 设备指纹识别
- 行为分析检测异常账号
-
防恶意下单:
- 信用评级系统
- 频繁取消订单惩罚机制
- 预付款模式
-
评价真实性保障:
- 只有真实服务过的用户才能评价
- 评价与订单强关联
- 异常评价人工审核
7. 部署架构
7.1 生产环境部署方案
code复制前端部署:
- 使用Nginx作为静态资源服务器
- 开启Gzip压缩
- 配置HTTP/2
- CDN加速静态资源
后端部署:
- 使用Docker容器化部署
- Kubernetes集群管理
- 多实例负载均衡
- 弹性伸缩策略
数据库部署:
- MySQL主从复制
- 读写分离
- 定期备份
- 监控告警
中间件:
- Redis哨兵集群
- RabbitMQ消息队列
- ELK日志系统
- Prometheus监控
7.2 CI/CD流程
- 代码提交:GitLab代码仓库
- 代码检查:SonarQube静态分析
- 单元测试:Maven执行测试用例
- 构建镜像:Docker构建并推送到镜像仓库
- 部署测试环境:Kubernetes滚动更新
- 自动化测试:Postman测试集
- 生产发布:蓝绿部署或金丝雀发布
- 监控回滚:异常时自动回滚
8. 项目扩展方向
8.1 功能扩展
-
智能客服系统:
- 集成NLP引擎实现自动问答
- 常见问题知识库
- 人工客服转接
-
会员成长体系:
- 积分累计
- 等级特权
- 会员专属服务
-
增值服务:
- 服务保险
- 加急服务
- 定期套餐
8.2 技术深化
-
大数据分析:
- 用户行为分析
- 服务需求预测
- 智能定价策略
-
AI应用:
- 服务人员智能匹配
- 评价情感分析
- 图片自动审核
-
物联网集成:
- 智能门锁对接
- 服务过程监控
- 设备状态上报
9. 开发经验分享
9.1 前后端协作实践
-
接口规范:
- 使用Swagger维护API文档
- 统一的响应格式
json复制{ "code": 200, "message": "success", "data": {...}, "timestamp": 1630000000000 }- 明确的错误码体系
-
Mock数据:
- 使用EasyMock搭建Mock服务器
- 前端开发不依赖后端进度
- 定义接口契约先行开发
-
联调技巧:
- 使用Postman测试集
- 接口变更及时通知
- 定期同步开发进度
9.2 性能调优经验
-
前端性能优化:
- 组件懒加载
- 路由按需加载
- 图片懒加载
- 资源预加载
-
JVM调优:
- 合适的堆内存设置
- GC算法选择(G1)
- JVM参数调优
- 内存泄漏检测
-
SQL优化:
- 使用EXPLAIN分析执行计划
- 避免全表扫描
- 优化JOIN操作
- 合理使用索引
10. 常见问题排查
10.1 典型问题及解决方案
-
服务人员重复接单:
- 原因:并发控制不完善
- 解决:分布式锁+乐观锁双重保障
-
评价显示延迟:
- 原因:缓存未及时更新
- 解决:双删策略+消息队列通知
-
地理位置搜索不准:
- 原因:未使用空间索引
- 解决:MySQL空间函数+GeoHash
-
订单状态不同步:
- 原因:分布式事务问题
- 解决:最终一致性+补偿机制
10.2 线上问题处理流程
- 监控告警:Prometheus+Granfana监控关键指标
- 日志分析:ELK收集分析日志
- 问题定位:链路追踪定位瓶颈
- 应急处理:预案执行+服务降级
- 复盘改进:根因分析+流程优化
关键提示:线上问题处理要坚持"先恢复,后排查"原则,优先保证系统可用性,再深入分析根本原因。
