SpringBoot+Vue全流程宠物领养平台架构设计与实践
2026/8/8 3:44:25 网站建设 项目流程

1. 项目概述:全流程宠物管理领养平台的设计初衷

去年参与本地流浪动物救助站信息化改造时,我深刻体会到传统纸质登记和微信群管理的局限性。丢失的领养记录、混乱的疫苗提醒、难以追踪的宠物信息,这些问题促使我开发了这套基于SpringBoot+Vue的全流程管理系统。平台实现了从宠物入驻、健康管理到领养匹配的完整闭环,目前已在3个救助站稳定运行8个月,累计处理600+例领养案例。

这个系统最核心的价值在于:

  • 对救助机构:电子化档案替代Excel表格,自动化的疫苗/驱虫提醒
  • 对领养人:可视化的宠物成长记录和在线申请流程
  • 对志愿者:移动端友好的任务分配和进度跟踪界面

技术选型上,后端采用SpringBoot 2.7 + MyBatis-Plus的组合,前端使用Vue3 + Element Plus构建管理后台,配合uniapp打包跨平台小程序。这种架构既保证了后台管理系统的开发效率,又满足了移动端用户的使用需求。

2. 技术架构设计与核心模块解析

2.1 前后端分离架构实践

系统采用经典的前后端分离模式,通过RESTful API进行数据交互。特别之处在于我们设计了双重网关体系:

  • SpringCloud Gateway作为API网关(端口8080)
  • Nginx作为静态资源网关(端口80)

这种设计带来两个实际好处:

  1. 前端打包后的dist目录直接由Nginx托管,减轻应用服务器压力
  2. API网关可以灵活配置熔断策略,我们在宠物图片上传接口特别添加了限流保护
// 网关限流配置示例 @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("upload_route", r -> r.path("/api/v1/upload/**") .filters(f -> f.requestRateLimiter(config -> { config.setRateLimiter(redisRateLimiter()); config.setStatusCode(HttpStatus.TOO_MANY_REQUESTS); })) .uri("lb://pet-service")) .build(); }

2.2 宠物核心数据模型设计

数据库采用MySQL 8.0,关键表结构设计体现了业务特性:

CREATE TABLE `pet` ( `id` bigint NOT NULL AUTO_INCREMENT, `rescue_id` varchar(20) COMMENT '救助编号', `name` varchar(50) COMMENT '宠物名字', `animal_type` enum('DOG','CAT','OTHER') NOT NULL, `breed` varchar(100) COMMENT '品种', `birth_date` date COMMENT '预估出生日期', `rescue_date` date NOT NULL, `health_status` enum('HEALTHY','IN_TREATMENT','CRITICAL') NOT NULL, `adoption_status` enum('WAITING','PROCESSING','ADOPTED') NOT NULL, `qr_code` varchar(255) COMMENT '宠物唯一二维码', PRIMARY KEY (`id`), UNIQUE KEY `idx_rescue_id` (`rescue_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

特别注意的点:

  • 使用utf8mb4字符集支持emoji昵称(比如"旺财🐶")
  • 救助编号采用"区域码+年月+序号"的生成规则(如BJ202405001)
  • 二维码存储的是加密后的宠物详情页URL,扫描直接跳转

3. 关键业务逻辑实现细节

3.1 领养审核流程引擎

领养流程采用状态机模式实现,核心状态转换如下:

stateDiagram-v2 [*] --> 待审核 待审核 --> 初审通过: 基础资料审核 待审核 --> 初审驳回: 资料不全 初审通过 --> 家访安排: 生成家访任务 家访安排 --> 家访完成: 上传报告 家访完成 --> 终审通过: 符合标准 家访完成 --> 终审驳回: 环境不符 终审通过 --> 签订协议: 电子签约 签订协议 --> 完成领养: 交接宠物

代码实现上,我们使用了Spring StateMachine框架:

@Configuration @EnableStateMachineFactory public class AdoptionStateMachineConfig extends EnumStateMachineConfigurerAdapter<AdoptionStates, AdoptionEvents> { @Override public void configure(StateMachineStateConfigurer<AdoptionStates, AdoptionEvents> states) throws Exception { states.withStates() .initial(AdoptionStates.PENDING_REVIEW) .states(EnumSet.allOf(AdoptionStates.class)); } @Override public void configure(StateMachineTransitionConfigurer<AdoptionStates, AdoptionEvents> transitions) throws Exception { transitions .withExternal() .source(AdoptionStates.PENDING_REVIEW) .target(AdoptionStates.FIRST_APPROVED) .event(AdoptionEvents.BASIC_APPROVE) .and() .withExternal() .source(AdoptionStates.PENDING_REVIEW) .target(AdoptionStates.REJECTED) .event(AdoptionEvents.BASIC_REJECT); // 其他转换规则... } }

3.2 宠物健康日历实现

健康管理模块有两个技术亮点:

  1. 基于Quartz的定时提醒:
public class VaccinationReminderJob implements Job { @Override public void execute(JobExecutionContext context) { List<PetVaccination> dueVaccinations = vaccinationMapper.selectDueVaccinations(); dueVaccinations.forEach(vaccination -> { String message = String.format("%s的%s疫苗即将到期", vaccination.getPetName(), vaccination.getVaccineType()); wechatService.pushTemplateMsg( vaccination.getKeeperId(), "VACCINE_REMINDER", message); }); } }
  1. 前端使用FullCalendar组件渲染健康日历:
<template> <FullCalendar :options="calendarOptions" /> </template> <script> export default { data() { return { calendarOptions: { initialView: 'dayGridMonth', events: '/api/pet/health-events', eventClick: this.handleEventClick, headerToolbar: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek' } } } }, methods: { async handleEventClick(info) { const res = await this.$axios.get(`/events/${info.event.id}`); this.$modal.show('event-detail', res.data); } } } </script>

4. 性能优化与安全实践

4.1 图片处理方案

考虑到宠物图片的高频访问特性,我们采用如下方案:

  1. 上传时自动生成三种尺寸:
    • 原图(存储到OSS)
    • 中等尺寸(800px宽,WebP格式)
    • 缩略图(200px宽,WebP格式)

使用Thumbnailator库实现:

public class ImageUtils { public static void generateThumbnails(InputStream input, String ossKey) { // 原图上传 ossClient.putObject(bucketName, ossKey, input); // 中尺寸处理 ByteArrayOutputStream mediumOs = new ByteArrayOutputStream(); Thumbnails.of(input) .size(800, 800) .outputFormat("webp") .toOutputStream(mediumOs); ossClient.putObject(bucketName, getMediumKey(ossKey), new ByteArrayInputStream(mediumOs.toByteArray())); // 缩略图处理同理... } }

4.2 安全防护措施

  1. 领养人身份证信息加密:
@Converter public class IdCardEncryptConverter implements AttributeConverter<String, String> { private final String key = "your-encryption-key"; @Override public String convertToDatabaseColumn(String attribute) { return AESUtil.encrypt(attribute, key); } @Override public String convertToEntityAttribute(String dbData) { return AESUtil.decrypt(dbData, key); } }
  1. 接口防刷策略:
  • 领养申请接口:1次/分钟
  • 短信验证码接口:1次/5分钟
  • 使用Redis实现计数器:
public boolean tryAcquire(String key, int limit, int timeout) { String redisKey = "rate_limit:" + key; Long count = redisTemplate.opsForValue().increment(redisKey); if (count != null && count == 1) { redisTemplate.expire(redisKey, timeout, TimeUnit.SECONDS); } return count != null && count <= limit; }

5. 部署与监控方案

5.1 Docker Compose部署

生产环境采用容器化部署,关键服务包括:

version: '3.8' services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS} volumes: - mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] redis: image: redis:6-alpine ports: - "6379:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] backend: build: ./backend depends_on: mysql: condition: service_healthy environment: SPRING_PROFILES_ACTIVE: prod ports: - "8080:8080" frontend: build: ./frontend ports: - "80:80" volumes: mysql_data:

5.2 监控配置

  1. SpringBoot Actuator端点安全暴露:
# application-prod.properties management.endpoints.web.exposure.include=health,metrics,prometheus management.endpoint.health.show-details=always management.metrics.export.prometheus.enabled=true
  1. 前端性能监控(使用Sentry):
// main.js import * as Sentry from "@sentry/vue"; import { BrowserTracing } from "@sentry/tracing"; Sentry.init({ dsn: "your-dsn", integrations: [ new BrowserTracing({ routingInstrumentation: Sentry.vueRouterInstrumentation(router), tracingOrigins: ["localhost", "your-domain.com"], }), ], tracesSampleRate: 0.2, });

6. 典型问题排查实录

6.1 Vuex数据持久化问题

场景:用户刷新页面后表单数据丢失 解决方案:配合vuex-persistedstate实现:

// store/index.js import createPersistedState from "vuex-persistedstate"; export default new Vuex.Store({ plugins: [ createPersistedState({ storage: window.sessionStorage, reducer: (state) => ({ adoptionForm: state.adoptionForm }) }) ], // ... });

6.2 MyBatis批量插入优化

原始方案(性能差):

@Insert("<script>" + "INSERT INTO pet_vaccination (pet_id, vaccine_type, date) VALUES " + "<foreach collection='list' item='item' separator=','>" + "(#{item.petId}, #{item.vaccineType}, #{item.date})" + "</foreach>" + "</script>") void batchInsert(@Param("list") List<Vaccination> vaccinations);

优化方案(使用rewriteBatchedStatements):

  1. 在jdbc url添加参数:
spring.datasource.url=jdbc:mysql://localhost:3306/pet_db?rewriteBatchedStatements=true
  1. 使用MyBatis-Plus的saveBatch方法:
vaccinationService.saveBatch(vaccinations, 1000); // 每批1000条

实测性能对比:

数据量原始方案优化方案
100条1200ms300ms
1000条15s1.2s

7. 项目演进方向

  1. 智能匹配算法:基于用户画像和宠物特征的匹配度计算
# 伪代码示例 def calculate_match_score(user, pet): score = 0 # 居住环境匹配 if user.house_type == 'APARTMENT' and pet.size == 'SMALL': score += 30 # 活动时间匹配 score += min(user.available_hours, pet.required_exercise) * 2 # 经验加分 if user.has_pet_experience and pet.is_first_pet == False: score += 20 return score
  1. 宠物行为分析:通过领养后定期上传的视频进行AI分析
  • 使用OpenCV检测进食/排泄规律
  • TensorFlow Lite模型识别焦虑行为(如过度舔舐)
  1. 区块链存证:将关键领养流程上链
  • Hyperledger Fabric构建私有链
  • 智能合约记录领养协议签署、疫苗记录等关键节点

这个项目给我的深刻体会是:技术方案必须服从业务场景。比如最初设计的复杂审核流程在实际运行中简化为三步,而原本认为简单的宠物档案模块却因为医疗记录的专业性变得异常复杂。建议开发类似系统的同行,一定要先深入救助站跟进行3-5个完整领养案例,才能真正理解业务痛点。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询