1. 项目背景与需求分析
灰灰宠物美容网站是一个基于SpringBoot和SSM框架开发的宠物美容服务平台。随着城市宠物数量的快速增长,专业宠物美容服务的需求呈现爆发式趋势。根据2023年宠物行业白皮书显示,我国城镇宠物美容市场规模已突破200亿元,年增长率保持在25%以上。
这个项目主要解决三个核心痛点:
- 传统宠物店预约方式效率低下(电话/到店登记)
- 服务项目和价格不透明
- 美容师与宠物主人缺乏有效沟通渠道
技术选型上采用SpringBoot 2.7 + MyBatis组合,主要基于以下考虑:
- 快速迭代需求:SpringBoot的自动配置特性适合快速原型开发
- 中等规模数据量:预计日订单量在500-1000单,SSM框架完全能胜任
- 团队技术栈:开发成员对MyBatis更熟悉,相比JPA有更多调优经验
实际开发中发现,宠物美容业务有几个特殊需求:需要记录宠物健康状态、美容前后对比照片管理、服务项目自定义组合计价等,这些都需要在架构设计阶段重点考虑。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 整体技术架构
采用经典的三层架构,但针对宠物美容业务做了特殊调整:
code复制表现层:Thymeleaf + Bootstrap
↓
业务层:SpringBoot + Spring MVC
↓
数据层:MyBatis + MySQL
↑
中间件:Redis(缓存预约时段) + RabbitMQ(异步处理订单)
2.2 核心业务模块设计
2.2.1 预约系统设计
采用时间片管理算法,每个美容师每天划分为48个30分钟时段。使用Redis的BitMap结构存储预约状态,关键数据结构:
java复制// Redis键设计
pet:appoint:{shopId}:{date}
// 值为BitMap,每位代表一个时段(0可约,1已约)
// Java实体类
public class Appointment {
private Long petId;
private LocalDateTime startTime;
private Integer duration; // 单位:分钟
private Integer status; // 0待确认,1已预约,2已完成
private List<ServiceItem> items;
}
2.2.2 服务项目定价策略
采用组合模式(Composite Pattern)实现服务包嵌套:
java复制public interface ServicePricing {
BigDecimal getPrice();
}
// 基础服务
public class BasicService implements ServicePricing {
private BigDecimal basePrice;
// getter...
}
// 服务套餐
public class ServicePackage implements ServicePricing {
private List<ServicePricing> items;
@Override
public BigDecimal getPrice() {
return items.stream()
.map(ServicePricing::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add)
.multiply(DISCOUNT_RATE);
}
}
3. 关键技术实现
3.1 宠物健康档案管理
使用DDD的聚合根设计,将宠物作为聚合根:
java复制public class Pet {
@Id
private Long id;
private String name;
private Integer age;
private String breed;
@Embedded
private HealthRecord healthRecord;
@OneToMany(mappedBy = "pet")
private List<Appointment> appointments;
}
@Embeddable
public class HealthRecord {
private String allergies;
private String specialNotes;
private String vaccinationStatus;
// 其他健康指标...
}
3.2 美容前后对比功能
采用策略模式处理不同图片处理需求:
java复制public interface PhotoProcessor {
BufferedImage process(BufferedImage original);
}
// 实现类示例
public class WatermarkProcessor implements PhotoProcessor {
@Override
public BufferedImage process(BufferedImage original) {
// 添加水印逻辑
}
}
// 使用示例
public class PhotoService {
private Map<String, PhotoProcessor> processors;
public BufferedImage processPhoto(String type, BufferedImage image) {
return processors.get(type).process(image);
}
}
图片存储采用阿里云OSS,数据库只保存URL引用。
4. 开发中的典型问题与解决方案
4.1 并发预约冲突
初期采用乐观锁方案仍出现超卖问题,最终解决方案:
- 使用Redis分布式锁控制时段修改
- 前端采用倒计时保留机制(15分钟未支付自动释放)
- 数据库增加唯一索引:
UNIQUE KEY uk_shop_time (shop_id, time_slot)
关键代码:
java复制public boolean tryLock(String key, long expireSeconds) {
return redisTemplate.opsForValue()
.setIfAbsent(key, "LOCK", expireSeconds, TimeUnit.SECONDS);
}
// 使用示例
String lockKey = "lock:appoint:" + shopId + ":" + timeSlot;
try {
if (tryLock(lockKey, 900)) {
// 处理预约逻辑
}
} finally {
redisTemplate.delete(lockKey);
}
4.2 服务组合价格计算性能
当服务项超过20个时,价格计算出现明显延迟。优化方案:
- 引入缓存计算结果
- 预生成常用组合套餐
- 使用并行流计算:
java复制public BigDecimal calculateTotalPrice(List<ServiceItem> items) {
return items.parallelStream()
.map(item -> pricingService.getPrice(item.getId()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
实测性能提升:50个服务项的计算时间从320ms降至85ms。
5. 安全防护措施
5.1 XSS防护方案
针对宠物描述等富文本字段,采用以下多层防护:
- 前端:使用DOMPurify过滤
- 后端:自定义Jackson反序列化器
- 存储层:入库前使用Jsoup清理
配置示例:
java复制@Bean
public HttpMessageConverters customConverters() {
StringHttpMessageConverter converter = new StringHttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_HTML));
return new HttpMessageConverters(false,
Collections.singletonList(converter));
}
// 清理逻辑
public String sanitize(String input) {
return Jsoup.clean(input,
Safelist.relaxed()
.addTags("span")
.addAttributes("span", "style"));
}
5.2 敏感数据保护
宠物主人联系方式加密存储:
- 使用Jasypt进行字段级加密
- 密钥通过HashiCorp Vault管理
- 日志脱敏处理
配置示例:
properties复制# application.properties
jasypt.encryptor.bean=encryptorBean
jasypt.encryptor.password=${VAULT_ENC_KEY}
6. 部署与监控
6.1 容器化部署
采用分层Docker镜像构建:
dockerfile复制FROM adoptopenjdk:11-jre-hotspot as runtime
COPY --from=build /app/target/*.jar /app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
# 构建命令
docker build --build-arg PROFILE=prod -t pet-beauty:1.0 .
6.2 健康检查配置
SpringBoot Actuator扩展配置:
yaml复制management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
endpoint:
health:
show-details: always
probes:
enabled: true
metrics:
export:
prometheus:
enabled: true
自定义健康指标:
java复制@Component
public class AppointmentHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCount = getRecentErrors();
if (errorCount > 10) {
return Health.down()
.withDetail("error_count", errorCount)
.build();
}
return Health.up().build();
}
}
7. 项目优化经验
7.1 缓存策略优化
经过压测发现的两个关键点:
-
预约时段缓存采用"预加载+实时更新"策略
- 每天0点加载未来7天时段数据
- 变更时双写数据库和缓存
-
使用Caffeine本地缓存减少Redis访问
配置示例:
java复制@Bean
public CaffeineCacheManager cacheManager() {
Caffeine<Object, Object> caffeine = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(5, TimeUnit.MINUTES);
return new CaffeineCacheManager("petInfo", "serviceItems", caffeine);
}
7.2 数据库优化实践
- 宠物表分片策略:按用户ID范围分片
- 预约表索引优化:
sql复制ALTER TABLE appointment ADD INDEX idx_shop_time (shop_id, appointment_time), ADD INDEX idx_user_status (user_id, status); - 大字段分离:将宠物健康备注等文本内容单独存表
8. 扩展功能设计
8.1 智能推荐系统
基于历史数据推荐服务组合:
- 使用Mahout实现协同过滤
- 特征向量设计:
python复制# Python伪代码 from pyspark.ml.feature import VectorAssembler assembler = VectorAssembler( inputCols=["breed", "age", "prev_services"], outputCol="features" ) - 推荐结果缓存到Redis
8.2 微信小程序集成
对接微信生态的关键步骤:
- 获取OpenID流程优化
java复制public String getOpenId(String code) { String url = String.format( "https://api.weixin.qq.com/sns/jscode2session?" + "appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appId, appSecret, code); return restTemplate.getForObject(url, String.class); } - 模板消息推送
- 小程序支付对接
9. 项目演进方向
- 美容师端APP开发:使用React Native跨平台方案
- 引入计算机视觉技术:通过宠物照片自动识别品种和毛发状况
- 会员成长体系设计:积分、等级、特权等闭环设计
- 智能排班系统:基于历史数据预测各时段需求
技术栈扩展考虑:
- 实时通信:WebSocket通知预约状态变化
- 大数据分析:Flink实时计算各门店运营指标
- 微服务化:将预约、支付、评价等模块拆分为独立服务
