1. 项目概述
这个前后端分离的网上宠物店系统采用了当前主流的SpringBoot+Vue技术栈,为宠物用品电商领域提供了一个完整的解决方案。作为一名有多年全栈开发经验的工程师,我认为这种架构组合在中小型电商系统中具有显著优势:SpringBoot提供了稳健的后端服务,Vue.js则能打造流畅的前端交互体验。
系统主要包含六大核心模块:用户管理、商品展示、购物车、订单处理、支付集成和后台管理。我在实际开发中发现,这种模块化设计不仅便于团队协作,也使得后期功能扩展更加灵活。比如当需要增加宠物医疗服务时,可以独立开发新模块而不影响现有功能。
2. 技术架构解析
2.1 后端技术栈
SpringBoot 2.7作为后端框架,其自动配置特性大幅减少了XML配置。我在项目中特别使用了这些依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
数据库操作采用MyBatis而非JPA,这是考虑到电商系统需要更精细的SQL控制。比如商品搜索功能就需要编写复杂的多表联查SQL:
java复制@Select("SELECT p.* FROM pet_product p LEFT JOIN product_category c ON p.category_id=c.id " +
"WHERE p.product_name LIKE CONCAT('%',#{keyword},'%')")
List<Product> searchProducts(@Param("keyword") String keyword);
2.2 前端技术选型
Vue 3的组合式API让前端开发更加高效。项目中使用Element Plus作为UI组件库,其表格和表单组件非常适合电商后台管理界面。一个典型的商品列表组件实现如下:
vue复制<template>
<el-table :data="products" style="width: 100%">
<el-table-column prop="productName" label="商品名称" />
<el-table-column prop="price" label="价格" />
<el-table-column prop="stock" label="库存" />
</el-table>
</template>
3. 数据库设计详解
3.1 核心表结构优化
宠物商品表的设计考虑了电商系统的特殊需求:
sql复制CREATE TABLE `pet_product` (
`pet_product_id` BIGINT NOT NULL AUTO_INCREMENT,
`product_name` VARCHAR(100) NOT NULL COMMENT '商品名称',
`price` DECIMAL(10,2) NOT NULL DEFAULT 0,
`stock` INT NOT NULL DEFAULT 0 COMMENT '库存需大于等于0',
`category` VARCHAR(50) NOT NULL COMMENT '商品分类',
`sales` INT DEFAULT 0 COMMENT '销量统计',
`is_hot` TINYINT(1) DEFAULT 0 COMMENT '是否热销',
PRIMARY KEY (`pet_product_id`),
INDEX `idx_category` (`category`),
INDEX `idx_hot` (`is_hot`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特别注意:
- 价格字段使用DECIMAL而非FLOAT,避免浮点精度问题
- 为分类和热销字段建立索引,提高查询效率
- 添加销售统计字段,便于后续数据分析
3.2 订单表设计要点
订单系统采用了主从表结构设计:
sql复制-- 主表存储订单基本信息
CREATE TABLE `order_master` (
`order_id` VARCHAR(32) NOT NULL COMMENT '使用时间戳+随机数生成',
`user_id` BIGINT NOT NULL,
`payment_amount` DECIMAL(10,2) NOT NULL,
`payment_status` TINYINT NOT NULL DEFAULT 0 COMMENT '0未支付 1已支付',
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`order_id`),
INDEX `idx_user` (`user_id`)
);
-- 从表存储订单商品明细
CREATE TABLE `order_detail` (
`detail_id` BIGINT NOT NULL AUTO_INCREMENT,
`order_id` VARCHAR(32) NOT NULL,
`product_id` BIGINT NOT NULL,
`product_name` VARCHAR(100) NOT NULL,
`product_price` DECIMAL(10,2) NOT NULL,
`product_quantity` INT NOT NULL,
PRIMARY KEY (`detail_id`),
INDEX `idx_order` (`order_id`)
);
这种设计解决了:
- 订单ID使用字符串便于扩展
- 分离主从表提高查询效率
- 记录商品快照,避免价格变动影响历史订单
4. 关键功能实现
4.1 JWT认证实现
采用JJWT库实现安全的token机制:
java复制public class JwtUtil {
private static final String SECRET = "your-256-bit-secret";
private static final long EXPIRATION = 86400000L; // 24小时
public static String generateToken(UserDetails user) {
return Jwts.builder()
.setSubject(user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET)
.compact();
}
public static Boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
}
前端需要在axios拦截器中添加token:
javascript复制service.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = 'Bearer ' + token
}
return config
})
4.2 购物车实现方案
采用Redis存储购物车数据,结构设计:
code复制用户ID -> {
"productId1": {
"name": "狗粮",
"price": 68.00,
"quantity": 2
},
"productId2": {
...
}
}
核心操作代码:
java复制public void addToCart(Long userId, Long productId, Integer quantity) {
String key = "cart:" + userId;
Product product = productMapper.selectById(productId);
CartItem item = new CartItem();
item.setProductId(productId);
item.setProductName(product.getProductName());
item.setProductPrice(product.getPrice());
item.setQuantity(quantity);
redisTemplate.opsForHash().put(key, productId.toString(), item);
}
5. 性能优化实践
5.1 缓存策略
商品详情采用多级缓存方案:
- 使用Redis缓存热点商品
- 本地Caffeine缓存作为二级缓存
- 设置合理的过期时间避免脏读
配置示例:
java复制@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(1000));
return cacheManager;
}
}
5.2 数据库优化
针对商品查询的优化措施:
- 使用覆盖索引减少回表
sql复制ALTER TABLE pet_product ADD INDEX idx_search (category, price, sales);
- 大文本字段单独分表
- 定期执行ANALYZE TABLE更新统计信息
6. 部署方案
6.1 后端部署
推荐使用Docker Compose部署:
yaml复制version: '3'
services:
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: pet_store
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
redis:
image: redis:6
ports:
- "6379:6379"
app:
build: .
ports:
- "8080:8080"
depends_on:
- mysql
- redis
6.2 前端部署
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;
}
}
7. 开发经验分享
7.1 跨域问题解决
前后端分离常见跨域问题,推荐解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
7.2 接口文档生成
使用Swagger实现API文档自动化:
java复制@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.petstore.controller"))
.paths(PathSelectors.any())
.build();
}
}
访问地址:http://localhost:8080/swagger-ui.html
8. 扩展功能建议
基于现有系统可以扩展:
- 宠物健康档案管理
- 宠物社区互动功能
- 智能推荐系统
- 物流跟踪集成
- 会员积分体系
每个功能模块都可以作为独立组件开发,保持系统松耦合特性。例如推荐系统可以采用协同过滤算法:
python复制# 伪代码示例
def recommend_products(user_id):
user_behavior = get_user_behavior(user_id)
similar_users = find_similar_users(user_behavior)
return aggregate_products(similar_users)
在实际项目中,我建议采用渐进式开发策略,先完善核心电商功能,再逐步添加增值服务。这种架构设计已经为后续扩展预留了足够的灵活性,开发者可以根据实际需求选择合适的扩展方向。