社区团购作为一种新兴的电商模式,通过集中采购和配送来降低商品成本,提高供应链效率。传统社区团购系统往往采用单体架构,前后端耦合度高,导致开发效率低下、维护困难。本系统采用SpringBoot+Vue+MyBatis+MySQL技术栈实现前后端分离架构,解决了传统系统的痛点问题。
在实际开发中,前后端分离架构带来了显著的效率提升。前端团队可以专注于页面交互和用户体验优化,后端团队则专注于业务逻辑和API设计。这种分工模式使得我们的开发周期缩短了约40%,特别是在需求变更时,前后端可以独立进行修改和部署。
提示:选择前后端分离架构时,建议在项目初期就定义好API规范(如RESTful接口设计),并建立完善的接口文档管理机制,这将大幅减少前后端联调时的问题。
Spring Boot作为后端框架的核心选择,主要基于以下考虑:
我们在项目中特别使用了Spring Boot 2.7.3版本,这个版本在性能和稳定性方面都有显著提升。以下是核心依赖配置示例:
xml复制<dependencies>
<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.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
Vue.js 3.x作为前端框架的选择主要基于:
我们采用了Vue CLI 5.x作为项目脚手架,配合Vite构建工具大幅提升了开发时的热更新速度。典型项目结构如下:
code复制src/
├── api/ # API请求封装
├── assets/ # 静态资源
├── components/ # 公共组件
├── router/ # 路由配置
├── store/ # 状态管理
├── utils/ # 工具函数
└── views/ # 页面组件
用户表(user_info)的设计考虑了以下业务需求:
sql复制CREATE TABLE `user_info` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '登录名',
`password_hash` varchar(100) NOT NULL COMMENT '加密密码',
`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
`phone_number` varchar(20) NOT NULL COMMENT '手机号',
`register_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_login` datetime DEFAULT NULL COMMENT '最后登录时间',
`role_type` tinyint NOT NULL COMMENT '1-管理员 2-团长 3-用户',
PRIMARY KEY (`user_id`),
UNIQUE KEY `idx_username` (`username`),
UNIQUE KEY `idx_phone` (`phone_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
商品表(product_detail)与订单表(order_record)采用外键关联确保数据一致性:
sql复制CREATE TABLE `order_record` (
`order_id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL,
`product_id` bigint NOT NULL,
`quantity` int NOT NULL DEFAULT '1',
`total_amount` decimal(10,2) NOT NULL,
`order_status` tinyint NOT NULL DEFAULT '1' COMMENT '1-待支付 2-已支付 3-已发货 4-已完成',
`payment_method` varchar(20) DEFAULT NULL,
`shipping_address` varchar(200) NOT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`order_id`),
KEY `idx_user` (`user_id`),
KEY `idx_product` (`product_id`),
CONSTRAINT `fk_order_product` FOREIGN KEY (`product_id`) REFERENCES `product_detail` (`product_id`),
CONSTRAINT `fk_order_user` FOREIGN KEY (`user_id`) REFERENCES `user_info` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
注意:在实际生产环境中,外键约束可能会影响性能。我们采用了应用层校验+数据库约束的双重保障机制,在开发环境开启外键约束确保数据完整性,生产环境则根据性能需求选择性使用。
采用Spring Security + JWT实现安全的认证流程:
核心认证服务代码:
java复制@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
public String login(String username, String password) {
// 加载用户详情
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 校验密码
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadCredentialsException("密码错误");
}
// 生成JWT令牌
return jwtTokenUtil.generateToken(userDetails);
}
// 其他认证相关方法...
}
团购活动是系统的核心业务模块,主要功能包括:
我们使用Spring的@Scheduled注解实现了活动状态的自动更新:
java复制@Service
public class GroupBuyServiceImpl implements GroupBuyService {
@Autowired
private GroupBuyMapper groupBuyMapper;
@Scheduled(cron = "0 0/5 * * * ?") // 每5分钟执行一次
public void autoUpdateGroupBuyStatus() {
// 更新超时未支付订单
groupBuyMapper.updateExpiredOrders();
// 自动开始到达开始时间的活动
groupBuyMapper.autoStartGroupBuy();
// 自动结束到达结束时间的活动
groupBuyMapper.autoEndGroupBuy();
}
// 其他业务方法...
}
我们制定了统一的API设计规范:
典型商品API示例:
java复制@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping
public ResponseEntity<PageInfo<Product>> listProducts(
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize) {
PageInfo<Product> pageInfo = productService.getProducts(pageNum, pageSize);
return ResponseEntity.ok(pageInfo);
}
@PostMapping
public ResponseEntity<Product> createProduct(@Valid @RequestBody Product product) {
Product savedProduct = productService.createProduct(product);
return ResponseEntity.status(HttpStatus.CREATED).body(savedProduct);
}
// 其他API方法...
}
前端使用axios封装了统一的请求处理:
javascript复制// src/api/request.js
import axios from 'axios'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000
})
// 请求拦截器
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 => {
return response.data
},
error => {
if (error.response.status === 401) {
// 处理token过期
store.dispatch('user/resetToken').then(() => {
location.reload()
})
}
return Promise.reject(error)
}
)
export default service
采用Docker容器化部署方案,Dockerfile配置示例:
dockerfile复制# 基础镜像
FROM openjdk:11-jre-slim
# 维护者信息
LABEL maintainer="dev@example.com"
# 设置工作目录
WORKDIR /app
# 复制JAR文件
COPY target/community-groupbuy.jar app.jar
# 暴露端口
EXPOSE 8080
# 启动命令
ENTRYPOINT ["java", "-jar", "app.jar"]
使用docker-compose编排MySQL和Spring Boot应用:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: groupbuy
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/groupbuy
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root123
depends_on:
- mysql
volumes:
mysql_data:
使用Nginx作为前端静态资源服务器,典型配置:
nginx复制server {
listen 80;
server_name localhost;
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;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
数据库查询优化:
API响应优化:
前端性能优化:
跨域问题:
JWT令牌失效:
MyBatis映射问题:
在实际开发中,我们建立了完善的日志系统,使用ELK(Elasticsearch+Logstash+Kibana)堆栈进行日志收集和分析,这对快速定位线上问题非常有帮助。