1. 项目概述:当Spring Boot遇上Vue
去年团队重构遗留系统时,我们选择了Spring Boot+Vue的微服务架构方案。这个组合就像咖啡遇上牛奶——Spring Boot提供稳健的后台支撑,Vue负责灵活的前端交互,两者通过RESTful API默契配合。典型的应用场景包括电商平台(商品服务、订单服务独立部署)、SaaS应用(多租户隔离)以及物联网数据处理平台(设备管理、数据分析微服务化)。
这个开源项目的核心价值在于:
- 前后端完全分离的开发模式
- 基于Spring Cloud的分布式系统解决方案
- Vue3+TypeScript的现代化前端工程
- 开箱即用的微服务基础设施(注册中心、配置中心、API网关)
提示:微服务不是银弹,2-3人开发的小型项目可能更适合单体架构。当系统模块超过10个,且团队规模在5人以上时,微服务的优势才会真正显现。
2. 架构设计与技术选型
2.1 后端技术栈解析
Spring Boot作为基础框架,我们做了这些关键扩展:
-
Spring Cloud Alibaba全家桶:
- Nacos:同时作为服务注册中心和配置中心
- Sentinel:熔断降级规则配置QPS阈值设为1000(经验值)
- RocketMQ:消息队列做异步解耦
-
数据持久层方案:
java复制// MyBatis-Plus配置示例
@Configuration
@MapperScan("com.example.mapper")
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
- 特别值得说的鉴权设计:
- 采用JWT+Spring Security组合
- 访问令牌有效期设为2小时(security.jwt.expiration=7200)
- 刷新令牌有效期7天,存储在Redis中
2.2 前端架构亮点
Vue3的组合式API让代码组织更灵活:
typescript复制// 典型组合式函数示例
export function useUser() {
const user = ref<User>()
const loading = ref(false)
const fetchUser = async (id: number) => {
loading.value = true
try {
const { data } = await axios.get(`/api/users/${id}`)
user.value = data
} finally {
loading.value = false
}
}
return { user, loading, fetchUser }
}
工程化方面的关键配置:
- Vite构建速度比Webpack快3-5倍
- ESLint+Prettier保证代码风格统一
- 按需引入Element Plus组件(节省30%打包体积)
3. 微服务核心模块实现
3.1 服务注册与发现
Nacos的注册流程值得细说:
- 服务启动时向Nacos发送注册请求
- 心跳检测间隔设为5秒(nacos.discovery.heartBeatInterval=5000)
- 服务下线时主动发送注销请求
我们在实践中发现:
- 服务实例metadata中添加zone字段便于流量调度
- 权重配置不要超过100,新版本建议初始值设为1
- 生产环境一定要开启鉴权(nacos.core.auth.enabled=true)
3.2 分布式配置管理
配置中心的典型使用场景:
yaml复制# bootstrap.yml
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
shared-configs:
- data-id: common.yaml
refresh: true
重要经验:配置项命名遵循"服务名.功能组.参数名"格式,如order-service.redis.timeout=3000
3.3 API网关设计
Spring Cloud Gateway的核心配置:
yaml复制spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
我们踩过的坑:
- 路由顺序影响匹配优先级(order字段)
- 过滤器链执行顺序与配置顺序相反
- 文件上传需要特殊处理(RemoveRequestHeader=Content-Length)
4. 前后端协作实践
4.1 接口规范设计
我们采用的RESTful规范:
| 操作类型 | HTTP方法 | 路径示例 | 状态码 |
|---|---|---|---|
| 创建 | POST | /api/articles | 201 |
| 批量查询 | GET | /api/articles?page=1 | 200 |
| 单条查询 | GET | /api/articles/ | 200/404 |
| 全量更新 | PUT | /api/articles/ | 200 |
| 部分更新 | PATCH | /api/articles/ | 200 |
| 删除 | DELETE | /api/articles/ | 204 |
4.2 联调技巧
Mock数据的正确打开方式:
- 使用MSW(Mock Service Worker)
javascript复制// src/mocks/handlers.js
import { rest } from 'msw'
export const handlers = [
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.delay(150), // 模拟网络延迟
ctx.json([{ id: 1, name: '测试用户' }])
)
})
]
- 后端Swagger配置要点:
java复制@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller"))
.paths(PathSelectors.any())
.build()
.apiInfo(metaData());
}
5. 部署与监控方案
5.1 容器化部署
Dockerfile优化技巧:
dockerfile复制# 前端Dockerfile多阶段构建
FROM node:16 as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
关键参数:
- 基础镜像选择alpine版本(体积小)
- 使用.dockerignore过滤不需要的文件
- 设置合理的资源限制(--memory=512m)
5.2 监控告警体系
Prometheus+Grafana监控看板配置:
- Spring Boot暴露指标端点:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
tags:
application: ${spring.application.name}
- 关键监控指标:
- JVM内存使用(jvm_memory_used_bytes)
- HTTP请求耗时(http_server_requests_seconds_sum)
- 数据库连接池(hikaricp_connections_active)
6. 常见问题排坑指南
6.1 跨域问题终极解决方案
不只是加@CrossOrigin注解:
java复制@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
特别注意:
- 网关层和资源服务只需一处配置
- 生产环境要指定具体域名而非通配符
- 预检请求缓存时间设为24小时(maxAge=86400)
6.2 分布式事务处理
Seata的AT模式实践:
- 关键配置:
properties复制# seata.conf
service.vgroupMapping.default_tx_group=default
service.default.grouplist=127.0.0.1:8091
- 业务代码示例:
java复制@GlobalTransactional
public void createOrder(OrderDTO orderDTO) {
// 扣减库存
storageFeignClient.deduct(orderDTO.getCommodityCode(), orderDTO.getCount());
// 创建订单
orderMapper.insert(orderDTO);
}
避坑经验:
- undo_log表要提前创建
- 超时时间不宜过短(默认60秒)
- 高并发场景建议改用TCC模式
这个架构方案在我们支付系统中日均处理50万+订单时表现稳定,JVM平均GC时间控制在200ms以内。对于刚开始尝试微服务的团队,建议先从3-5个核心服务做起,逐步积累分布式系统经验。