1. 项目概述:Spring Boot+Vue全栈宠物管理系统
去年接手某连锁宠物医院数字化改造项目时,我首次将Spring Boot+Vue技术栈应用于宠物管理场景。这个看似常见的组合在实际落地中遇到了许多架构设计上的挑战,比如高并发预约挂号时的分布式锁问题、宠物健康档案的PDF动态生成等。本文将分享经过三个版本迭代后沉淀出的实战方案,包含从技术选型到性能优化的完整闭环。
传统宠物店使用Excel记录客户信息的方式存在数据易丢失、统计困难等问题。我们开发的系统实现了宠物档案电子化、服务预约、健康记录追踪等核心功能,日均承载2000+订单量。后端采用Spring Boot 2.7 + MyBatis Plus架构,前端使用Vue 3组合式API,通过RESTful API进行数据交互。
关键数据:系统包含28张核心数据表,宠物档案模块支持10种常见宠物类型的特征字段动态扩展,预约模块峰值QPS达到152(实测数据)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构深度解析
2.1 后端技术栈设计
Spring Boot的选择基于其快速启动特性(平均项目初始化时间比传统SSM框架节省65%),特别适合快速迭代的互联网应用。我们采用分层架构:
code复制com.pet
├── config # 安全及第三方配置
├── controller # 响应式REST接口
├── service # 业务逻辑层
│ ├── impl # 实现类
├── dao # MyBatis Plus映射
├── entity # 领域对象
└── util # 工具包
数据库选用MySQL 8.0,主要考虑宠物医疗数据的关系型特性。连接池使用HikariCP,配置参数经过JMeter压测优化:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
2.2 前端工程化实践
Vue 3的组合式API相比Options API更适合复杂业务场景。通过Pinia进行状态管理,解决多组件间数据共享问题。项目结构采用功能模块划分:
code复制src/
├── api # Axios封装
├── assets # 静态资源
├── components # 公共组件
│ ├── pet # 宠物相关组件
│ ├── order # 订单组件
├── router # 路由配置
├── stores # Pinia状态库
└── views # 页面视图
采用Vite构建工具,冷启动时间比Webpack快4倍。通过动态导入实现路由懒加载,首屏加载时间控制在1.2秒内。
3. 核心功能实现细节
3.1 宠物档案管理
采用策略模式处理不同宠物类型的特征字段。例如犬类需要记录肩高、毛长等属性,而爬宠类需要记录蜕皮周期等特殊字段。
java复制// 策略接口
public interface PetAttributeStrategy {
Map<String, FieldConfig> getAttributes();
}
// 犬类实现
@Service("dogStrategy")
public class DogAttributeStrategy implements PetAttributeStrategy {
@Override
public Map<String, FieldConfig> getAttributes() {
return Map.of(
"shoulderHeight", new FieldConfig("肩高", "cm", InputType.NUMBER),
"furLength", new FieldConfig("毛长", "cm", InputType.SELECT)
);
}
}
前端使用动态表单生成器,根据宠物类型渲染不同字段:
vue复制<template>
<div v-for="(config, key) in attributeConfigs" :key="key">
<component
:is="getComponent(config.inputType)"
v-model="formData.attributes[key]"
:config="config"
/>
</div>
</template>
3.2 预约排队系统
使用Redis实现分布式锁,解决高并发下的超订问题:
java复制public boolean tryLock(String lockKey, long expireSeconds) {
String requestId = UUID.randomUUID().toString();
Boolean result = redisTemplate.opsForValue()
.setIfAbsent(lockKey, requestId, expireSeconds, TimeUnit.SECONDS);
if (Boolean.TRUE.equals(result)) {
// 获取锁成功
return true;
}
return false;
}
采用分段锁设计,将不同时间段的预约分配到不同的锁粒度,降低冲突概率。测试数据显示该方案将并发处理能力提升40%。
4. 典型问题解决方案
4.1 宠物健康报告PDF生成
使用Flying Saucer + Thymeleaf方案解决中文字体渲染问题:
java复制// 模板引擎配置
@Bean
public ITemplateResolver pdfTemplateResolver() {
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
resolver.setPrefix("pdf-templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML");
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
// PDF生成核心代码
public byte[] generateReport(PetHealthData data) throws Exception {
Context context = new Context();
context.setVariable("pet", data);
String html = templateEngine.process("health-report", context);
ITextRenderer renderer = new ITextRenderer();
renderer.getFontResolver().addFont(
"fonts/simhei.ttf",
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED
);
renderer.setDocumentFromString(html);
renderer.layout();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
renderer.createPDF(outputStream);
return outputStream.toByteArray();
}
4.2 前后端数据交互优化
针对宠物列表的复杂查询,设计专用DTO减少网络传输:
java复制@Data
public class PetListDTO {
private Long id;
private String name;
private String petType;
private String ownerName;
private String avatarUrl;
// 自定义转换逻辑
public static PetListDTO fromEntity(Pet pet) {
PetListDTO dto = new PetListDTO();
BeanUtils.copyProperties(pet, dto);
dto.setOwnerName(pet.getOwner().getRealName());
return dto;
}
}
前端采用虚拟滚动技术处理万级数据列表:
vue复制<template>
<VirtualList
:size="60"
:remain="8"
:items="filteredPets"
>
<template #default="{ item }">
<PetCard :data="item" />
</template>
</VirtualList>
</template>
5. 性能优化实战
5.1 数据库查询优化
针对宠物-主人联查场景,使用MyBatis Plus的@TableField注解实现自动关联查询:
java复制@Data
@TableName("pet")
public class Pet {
private Long id;
private String name;
@TableField(exist = false)
private Owner owner;
}
// Mapper接口
public interface PetMapper extends BaseMapper<Pet> {
@Select("SELECT p.*, o.* FROM pet p LEFT JOIN owner o ON p.owner_id = o.id WHERE p.id = #{id}")
@Results({
@Result(property = "owner.id", column = "o_id"),
@Result(property = "owner.realName", column = "o_real_name")
})
Pet selectWithOwner(Long id);
}
5.2 缓存策略设计
采用多级缓存架构:
- 本地Caffeine缓存:存储高频访问的宠物基础信息(有效期5分钟)
- Redis缓存:存储套餐价格等业务数据(有效期2小时)
- MySQL:持久化存储
java复制@Cacheable(value = "pet", key = "#id", unless = "#result == null")
public Pet getById(Long id) {
return getById(id);
}
@CacheEvict(value = "pet", key = "#pet.id")
public void updatePet(Pet pet) {
updateById(pet);
}
6. 安全防护方案
6.1 接口权限控制
使用Spring Security + JWT实现细粒度权限控制:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/pet/**").hasAnyRole("STAFF", "ADMIN")
.antMatchers("/api/medical/**").hasRole("VET")
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
return http.build();
}
}
6.2 敏感数据加密
宠物主人身份证号等字段采用AES加密存储:
java复制public class CryptoConverter implements AttributeConverter<String, String> {
private static final String KEY = "your-256-bit-secret";
private static final String ALGORITHM = "AES/GCM/NoPadding";
@Override
public String convertToDatabaseColumn(String attribute) {
// 实现加密逻辑
}
@Override
public String convertToEntityAttribute(String dbData) {
// 实现解密逻辑
}
}
@Entity
public class Owner {
@Convert(converter = CryptoConverter.class)
private String idNumber;
}
7. 部署与监控
7.1 Docker容器化部署
后端服务Dockerfile配置:
dockerfile复制FROM openjdk:17-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
使用docker-compose编排:
yaml复制version: '3'
services:
backend:
build: ./pet-backend
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
frontend:
build: ./pet-frontend
ports:
- "80:80"
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=pet@123
volumes:
- mysql_data:/var/lib/mysql
7.2 Prometheus监控
Spring Boot集成Prometheus:
yaml复制management:
endpoints:
web:
exposure:
include: health,metrics,prometheus
metrics:
tags:
application: pet-management
配置Grafana监控看板,关键指标包括:
- 接口响应时间P99
- JVM内存使用率
- 数据库连接池活跃连接数
- Redis缓存命中率
8. 项目演进方向
当前系统已在12家宠物医院落地运行,下一步计划:
- 接入微信小程序端,支持主人自助预约
- 引入Elasticsearch实现宠物健康数据全文检索
- 开发AI辅助诊断模块(基于宠物症状大数据分析)
在最近一次架构评审中,我们发现当宠物照片存储超过50万张时,文件系统性能下降明显。解决方案是引入MinIO对象存储,通过分片上传和CDN加速提升用户体验。
