1. 项目概述:宠物猫认养系统的技术架构与核心价值
这个基于SpringBoot+Vue+MyBatis+MySQL的宠物猫认养系统,是一个典型的现代化前后端分离Web应用。我在实际开发中发现,这类系统相比传统单体架构,能更好地应对宠物领养场景中的高并发浏览和复杂交互需求。前端采用Vue.js构建响应式用户界面,后端使用SpringBoot提供RESTful API,通过MyBatis与MySQL数据库交互,形成了清晰的三层架构。
系统主要解决传统宠物领养平台存在的几个痛点:页面响应慢导致用户流失、管理后台操作繁琐、领养流程不透明等。通过前后端分离架构,我们实现了:
- 领养者可以流畅浏览猫咪信息、查看健康档案
- 管理员能高效管理猫咪信息和领养申请
- 整个领养流程可追踪、可验证
提示:选择前后端分离架构时,需要考虑团队技术栈匹配度。Vue+SpringBoot的组合对全栈开发者更友好,学习曲线相对平缓。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术栈选型与核心组件解析
2.1 后端技术栈深度配置
SpringBoot 2.7.x作为后端框架,我特别推荐使用这个长期支持版本而非最新的3.x系列。在实际项目中验证过,2.7.x与各种中间件的兼容性更稳定。关键配置要点:
java复制// application.yml典型配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/pet_adoption?useSSL=false&serverTimezone=UTC
username: root
password: 你的密码
driver-class-name: com.mysql.cj.jdbc.Driver
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
MyBatis的Mapper配置有个实用技巧 - 使用@MapperScan注解批量扫描,避免每个Mapper接口都加@Mapper:
java复制@SpringBootApplication
@MapperScan("com.pet.adoption.mapper")
public class AdoptionApplication {
public static void main(String[] args) {
SpringApplication.run(AdoptionApplication.class, args);
}
}
2.2 前端工程化实践
Vue 3.x组合式API相比Options API更适合复杂交互场景。项目中使用Vue Router处理路由,关键配置示例:
javascript复制// router/index.js
const routes = [
{
path: '/cats',
component: () => import('../views/CatList.vue'),
meta: { requiresAuth: true }
},
{
path: '/cats/:id',
component: () => import('../views/CatDetail.vue'),
props: true
}
]
注意:Vue 3默认不支持IE11,如果必须兼容旧浏览器,需要额外配置polyfill。
3. 数据库设计与核心业务实现
3.1 MySQL数据库优化方案
宠物猫认养系统的ER图核心实体包括:猫咪(cat)、用户(user)、领养记录(adoption)。建表时特别注意:
sql复制CREATE TABLE `cat` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`age` int DEFAULT NULL,
`gender` enum('MALE','FEMALE') DEFAULT NULL,
`health_status` varchar(50) DEFAULT NULL,
`vaccination` tinyint(1) DEFAULT '0',
`description` text,
`avatar_url` varchar(255) DEFAULT NULL,
`is_adopted` tinyint(1) DEFAULT '0',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
FULLTEXT KEY `ft_idx` (`name`,`description`) -- 全文检索优化
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
3.2 领养业务核心逻辑实现
领养申请的业务逻辑包含几个关键校验:
- 检查猫咪是否已被领养
- 验证用户资格(如年龄、居住环境等)
- 生成电子协议
SpringBoot中典型的服务层实现:
java复制@Service
@Transactional
public class AdoptionService {
@Autowired
private CatMapper catMapper;
@Autowired
private AdoptionMapper adoptionMapper;
public AdoptionResult applyAdoption(AdoptionApplyDTO dto) {
// 检查猫咪状态
Cat cat = catMapper.selectById(dto.getCatId());
if (cat == null) {
throw new BusinessException("猫咪不存在");
}
if (cat.getIsAdopted()) {
throw new BusinessException("该猫咪已被领养");
}
// 验证用户资格
if (!userQualificationService.check(dto.getUserId())) {
throw new BusinessException("不符合领养条件");
}
// 创建领养记录
AdoptionRecord record = new AdoptionRecord();
record.setCatId(dto.getCatId());
record.setUserId(dto.getUserId());
record.setApplyTime(LocalDateTime.now());
record.setStatus(AdoptionStatus.PENDING);
adoptionMapper.insert(record);
// 生成电子协议
String contractUrl = contractService.generateAdoptionContract(record);
return new AdoptionResult(record.getId(), contractUrl);
}
}
4. 前后端交互关键实现
4.1 RESTful API设计规范
遵循Richardson成熟度模型Level 3标准设计API。以猫咪相关接口为例:
| 端点 | 方法 | 描述 | 参数 |
|---|---|---|---|
| /api/cats | GET | 分页查询猫咪列表 | page, size, sort |
| /api/cats/ | GET | 获取猫咪详情 | - |
| /api/cats/search | GET | 条件搜索猫咪 | name, age, gender |
| /api/cats/{id}/adoptions | POST | 提交领养申请 | AdoptionApplyDTO |
使用SpringBoot实现分页查询接口:
java复制@RestController
@RequestMapping("/api/cats")
public class CatController {
@Autowired
private CatService catService;
@GetMapping
public PageResult<CatVO> listCats(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String sort) {
PageHelper.startPage(page, size);
if (sort != null) {
PageHelper.orderBy(sort);
}
List<CatVO> list = catService.listCats();
PageInfo<CatVO> pageInfo = new PageInfo<>(list);
return new PageResult<>(
pageInfo.getList(),
pageInfo.getTotal(),
pageInfo.getPageNum(),
pageInfo.getPageSize()
);
}
}
4.2 前端Axios封装技巧
在Vue中封装通用的API请求工具:
javascript复制// utils/request.js
import axios from 'axios'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 10000
})
// 请求拦截器
service.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = 'Bearer ' + token
}
return config
},
error => {
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data
if (res.code !== 200) {
if (res.code === 401) {
// 跳转登录
}
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
return Promise.reject(error)
}
)
export default service
5. 系统部署实战指南
5.1 生产环境部署方案
推荐使用Docker Compose进行容器化部署,docker-compose.yml示例:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
container_name: pet-mysql
environment:
MYSQL_ROOT_PASSWORD: yourpassword
MYSQL_DATABASE: pet_adoption
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
restart: always
backend:
build: ./backend
container_name: pet-backend
ports:
- "8080:8080"
depends_on:
- mysql
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/pet_adoption
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: yourpassword
restart: always
frontend:
build: ./frontend
container_name: pet-frontend
ports:
- "80:80"
restart: always
5.2 Nginx关键配置
前端项目部署的Nginx配置要点:
nginx复制server {
listen 80;
server_name yourdomain.com;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1y;
add_header Cache-Control "public, no-transform";
}
}
6. 开发中的典型问题与解决方案
6.1 跨域问题深度解决
开发阶段常见的跨域问题,除了简单的CORS配置,还需要注意:
- 带Cookie的跨域请求需要特殊处理
- 预检请求(OPTIONS)的处理
- 生产环境与开发环境的不同配置策略
SpringBoot中的全局CORS配置:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("Authorization")
.allowCredentials(true)
.maxAge(3600);
}
}
对应的前端Axios配置:
javascript复制axios.defaults.withCredentials = true // 允许携带cookie
6.2 MyBatis动态SQL优化
复杂查询场景下的MyBatis动态SQL编写技巧:
xml复制<select id="selectCatsByCondition" resultType="CatVO">
SELECT * FROM cat
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="minAge != null">
AND age >= #{minAge}
</if>
<if test="maxAge != null">
AND age <= #{maxAge}
</if>
<if test="gender != null">
AND gender = #{gender}
</if>
<if test="healthStatus != null">
AND health_status = #{healthStatus}
</if>
<if test="!includeAdopted">
AND is_adopted = 0
</if>
</where>
ORDER BY create_time DESC
</select>
7. 性能优化与安全加固
7.1 图片存储与访问优化
宠物图片采用CDN加速方案:
- 上传时压缩图片(使用Thumbnailator)
- 存储到OSS而非本地磁盘
- 通过CDN域名访问
SpringBoot文件上传示例:
java复制@PostMapping("/upload")
public String uploadImage(@RequestParam("file") MultipartFile file) {
// 校验文件类型
String contentType = file.getContentType();
if (!Arrays.asList("image/jpeg", "image/png").contains(contentType)) {
throw new BusinessException("仅支持JPEG/PNG格式");
}
// 压缩图片
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Thumbnails.of(file.getInputStream())
.size(800, 800)
.outputFormat("jpg")
.toOutputStream(outputStream);
// 上传到OSS
String fileName = UUID.randomUUID() + ".jpg";
ossClient.putObject(bucketName, fileName,
new ByteArrayInputStream(outputStream.toByteArray()));
return cdnDomain + "/" + fileName;
}
7.2 安全防护措施
必须实现的安全防护:
- SQL注入防护(MyBatis使用#{}而非${})
- XSS防护(前端使用vue-sanitize)
- CSRF防护(Spring Security)
- 接口幂等性设计(重要操作使用token)
Spring Security核心配置:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // 前后端分离通常禁用CSRF
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
8. 项目扩展方向与进阶建议
8.1 微服务化改造
当系统规模扩大时,可考虑拆分为微服务:
- 用户服务
- 猫咪信息服务
- 领养流程服务
- 支付服务
- 通知服务
使用Spring Cloud Alibaba技术栈:
- Nacos服务发现与配置中心
- Sentinel流量控制
- Seata分布式事务
8.2 大数据分析扩展
收集用户行为数据后,可以:
- 使用ELK搭建日志分析系统
- 基于用户浏览记录推荐猫咪
- 使用Spark分析领养成功率影响因素
典型的数据分析流程:
python复制# PySpark示例:分析猫咪特征与领养速度的关系
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("AdoptionAnalysis").getOrCreate()
df = spark.read.jdbc(url, "adoption_records", properties=props)
result = df.groupBy("cat_breed", "cat_age") \
.agg({"days_to_adopt": "avg"}) \
.orderBy("avg(days_to_adopt)")
9. 开发环境搭建完整指南
9.1 后端开发环境
- JDK 11+(推荐Amazon Corretto)
- IntelliJ IDEA(安装Lombok插件)
- MySQL 8.0(配置大小写敏感)
- Redis(用于会话缓存)
初始化数据库脚本示例:
sql复制CREATE DATABASE pet_adoption CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建用户并授权
CREATE USER 'petadmin'@'%' IDENTIFIED BY 'securepassword';
GRANT ALL PRIVILEGES ON pet_adoption.* TO 'petadmin'@'%';
FLUSH PRIVILEGES;
9.2 前端开发环境
- Node.js 16+
- Vue CLI 5
- VS Code(推荐插件:Volar、ESLint)
项目初始化命令:
bash复制# 安装依赖
npm install
# 开发模式运行
npm run serve
# 生产构建
npm run build
10. 项目文档与协作规范
10.1 API文档生成
使用Swagger UI自动生成API文档,SpringBoot配置:
java复制@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.pet.adoption.controller"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("宠物猫认养系统API文档")
.description("前后端分离架构的RESTful API文档")
.version("1.0")
.build();
}
}
10.2 Git协作流程
推荐使用Git Flow工作流:
master分支 - 生产环境代码develop分支 - 集成开发分支feature/xxx- 功能开发分支hotfix/xxx- 紧急修复分支
典型开发命令序列:
bash复制# 创建新功能分支
git checkout -b feature/user-auth develop
# 开发完成后合并到develop
git checkout develop
git merge --no-ff feature/user-auth
git branch -d feature/user-auth
# 发布版本
git checkout master
git merge --no-ff develop
git tag -a v1.0.0 -m "Release version 1.0.0"
