ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Spring Cloud Alibaba电商微服务实战:Nacos+Gateway+多数据源

2026/9/13 11:14:49 拓冰建站 浏览量
Spring Cloud Alibaba电商微服务实战:Nacos+Gateway+多数据源 简介这是一套面向计算机专业本科生的高分毕业设计级分布式网上商城系统适用于课程设计、期末大作业及毕设参考帮助学习者系统掌握Spring Cloud微服务架构与Vue前后端分离开发实践。资源包共792个文件涵盖115个Java后端核心代码、45个Vue组件页面、164个JS逻辑脚本、53个CSS样式文件及1个完整SQL数据库脚本辅以bat部署脚本、yml配置文件和论文文档整体压缩包仅26.25MB轻量易部署。已有108人下载学习说明其调试充分、开箱即用——项目已通过导师验收含可直接运行的源码、MySQL 8.0建库脚本、Navicat可视化支持及配套毕业论文详细阐述了分布式服务拆分逻辑、JWT鉴权实现、购物车与订单状态机设计等关键模块结构清晰、注释规范便于理解微服务通信机制与前端路由管理。1. 这不是又一个“商城Demo”而是一套可跑通、可调试、可延展的分布式电商骨架你下载的这个.zip文件表面看是“高分毕业设计”实际承载的是 Java 工程师从单体走向分布式的第一块真实跳板。它不依赖 Docker Compose 一键启动的黑盒封装也不用 Spring Boot Admin 做花哨监控——而是用最朴素的spring-cloud-starter-alibaba-nacos-discoveryspring-cloud-starter-gatewayspring-cloud-starter-openfeign组合在本地 Windows 或 Linux 环境下手动拉起注册中心、网关、用户服务、商品服务、订单服务、支付服务共 6 个独立进程并让 Vue 前端通过 Nginx 反向代理访问后端 API。MySQL 不是只建三张表而是按业务域拆分user_db、product_db、order_db三个物理库每库含sharding_key字段支撑未来分库分表。论文里写的“熔断降级策略”不是空话对应到代码就是SentinelResource(fallback fallbackMethod)的真实调用链路。适合刚学完 Spring Cloud 五大组件Eureka/Nacos、Ribbon/LoadBalancer、Feign、Hystrix/Sentinel、Zuul/Gateway但还没在真实项目里串起来的同学也适合需要快速验证分布式事务、服务间鉴权、前端路由守卫与后端 JWT 拦截联动机制的中级开发者。2. 搭建 Nacos 注册中心与配置中心Spring Cloud Alibaba 的落地基座2.1 为什么选 Nacos 而非 Eureka关键在配置热更新与命名空间隔离Eureka 已进入维护模式Nacos 不仅提供服务注册发现更原生支持配置管理Config且能通过namespace实现开发/测试/生产环境配置物理隔离。毕业设计中常被忽略的点是服务注册名必须小写且无下划线如user-service否则 Feign Client 会因 Spring Cloud 默认的ServiceInstanceListSupplier解析失败而报No instances available for user-service。Nacos 控制台默认账号密码为nacos/nacos首次登录后务必修改——这是线上部署前的安全必选项。2.2 下载与启动 Nacos Server以 2.2.3 版本为例# Linux/macOS 下执行Windows 请用 cmd 替代 wget https://github.com/alibaba/nacos/releases/download/2.2.3/nacos-server-2.2.3.tar.gz tar -zxvf nacos-server-2.2.3.tar.gz cd nacos/bin # 单机模式启动开发用-p 指定端口避免冲突 ./startup.sh -m standalone -p 8848提示若提示JAVA_HOME not set需先配置 JDK 17Spring Cloud 2022.x 要求 JDK 17。Windows 用户请确保JAVA_HOME指向 JDK 根目录且Path中包含%JAVA_HOME%\bin。启动成功后访问http://localhost:8848/nacos登录后创建两个命名空间devID 自动生成如e9a5b3c1-xxxx-xxxx-xxxx-xxxxxxxxxxxxtest同上再在dev命名空间下新建配置Data ID user-service-dev.yamlGroup DEFAULT_GROUP内容如下spring: datasource: url: jdbc:mysql://localhost:3306/user_db?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver此配置将被user-service启动时自动加载无需硬编码数据库连接信息。2.3 在 user-service 中集成 Nacos Discovery 与 Configpom.xml必加依赖注意版本对齐dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId version2022.0.1.0/version !-- 对应 Spring Cloud 2022.0.x -- /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId version2022.0.1.0/version /dependencybootstrap.yml注意是 bootstrap不是 applicationspring: application: name: user-service cloud: nacos: discovery: server-addr: localhost:8848 namespace: e9a5b3c1-xxxx-xxxx-xxxx-xxxxxxxxxxxx # dev 命名空间 ID config: server-addr: localhost:8848 namespace: e9a5b3c1-xxxx-xxxx-xxxx-xxxxxxxxxxxx file-extension: yaml group: DEFAULT_GROUP启动UserApplication后刷新 Nacos 控制台「服务列表」应看到user-service实例状态为UP。此时服务已注册成功且配置已生效。3. 构建 Spring Cloud Gateway 网关层统一入口、路由转发与 JWT 鉴权3.1 网关为何不能只配路由必须处理跨域与 Token 透传Vue 前端运行在http://localhost:8080后端服务注册在 Nacos网关作为唯一对外入口需解决三个核心问题CORS 跨域浏览器同源策略拦截不能只靠CrossOrigin注解该注解作用于 Controller 层网关层无效JWT Token 透传前端登录后存Authorization: Bearer xxx网关需将其原样转发给下游服务而非自行解析后丢弃路由路径重写Vue Router 使用 history 模式请求/api/user/info应转发至user-service的/user/info需去除/api前缀3.2 gateway-service 的核心路由配置application.ymlspring: cloud: gateway: routes: - id: user-service uri: lb://user-service predicates: - Path/api/user/** filters: - StripPrefix1 # 去掉 /api - DedupeResponseHeaderAccess-Control-Allow-Origin Access-Control-Allow-Credentials # 解决跨域响应头重复 - id: product-service uri: lb://product-service predicates: - Path/api/product/** filters: - StripPrefix1 globalcors: add-to-simple-cors-configuration: true cors-configurations: [/**]: allowed-origins: http://localhost:8080 allowed-methods: GET,POST,PUT,DELETE,OPTIONS allowed-headers: * allow-credentials: true max-age: 3600注意lb://表示 LoadBalance即从 Nacos 获取user-service实例列表并负载均衡StripPrefix1是关键否则user-service收到的请求路径仍是/api/user/info而其 Controller 映射的是/user/info导致 404。3.3 实现 JWT Token 全链路透传非鉴权仅透传网关不校验 Token鉴权由各微服务自己完成但需确保Authorization头不被过滤。Spring Cloud Gateway 默认会删除部分敏感 Header需显式放行Configuration public class GatewayConfig { Bean public GlobalFilter customGlobalFilter() { return (exchange, chain) - { ServerHttpRequest request exchange.getRequest(); // 强制保留 Authorization 头 ServerHttpRequest newRequest request.mutate() .header(Authorization, request.getHeaders().getFirst(Authorization)) .build(); return chain.filter(exchange.mutate().request(newRequest).build()); }; } }此 Filter 确保下游user-service能通过request.getHeader(Authorization)获取原始 Token用于后续JwtUtil.parseToken()解析。4. Vue 前端与后端服务的联调要点Axios 拦截器、路由守卫与打包路径4.1 Vue 项目中 Axios 的请求 baseURL 与代理配置冲突真相很多同学在vue.config.js中配置了devServer.proxy却在生产环境打包后发现 API 请求 404——根本原因是proxy 仅在npm run serve开发模式下生效打包后npm run build生成的静态文件由 Nginx 托管proxy 不起作用。正确做法是开发时vue.config.js中配置 proxy避免 CORS生产时Nginx 配置反向代理将/api路径转发至http://localhost:8081Gateway 端口vue.config.js示例module.exports { devServer: { proxy: { /api: { target: http://localhost:8081, // Gateway 地址 changeOrigin: true, pathRewrite: { ^/api: // 开发时自动去掉 /api 前缀 } } } } }4.2 登录后 Token 存储与请求拦截器实现src/utils/request.jsimport axios from axios const service axios.create({ baseURL: process.env.NODE_ENV production ? /api : , // 生产环境走 NginxbaseURL 为空开发环境由 proxy 处理 timeout: 10000 }) // 请求拦截器携带 token service.interceptors.request.use( config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer ${token} } return config }, error Promise.reject(error) ) // 响应拦截器401 跳转登录页 service.interceptors.response.use( response response, error { if (error.response?.status 401) { localStorage.removeItem(token) router.push(/login) } return Promise.reject(error) } ) export default service注意baseURL在生产环境设为空字符串是因为 Nginx 已将/api路径代理到网关前端请求/api/user/login实际发往http://your-domain.com/api/user/loginNginx 再将其转发至http://localhost:8081/user/login。若此处误设为http://localhost:8081则生产环境会跨域。4.3 Vue Router 路由守卫与权限控制雏形src/router/index.js中添加全局前置守卫router.beforeEach((to, from, next) { const token localStorage.getItem(token) const whiteList [/login, /register] // 白名单页面 if (whiteList.includes(to.path)) { next() } else if (!token) { next(/login) } else { // 检查 token 是否过期简单版解析 payload 中的 exp 字段 try { const payload JSON.parse(atob(token.split(.)[1])) if (Date.now() payload.exp * 1000) { localStorage.removeItem(token) next(/login) } else { next() } } catch (e) { localStorage.removeItem(token) next(/login) } } })此守卫实现了基础的登录态校验比单纯检查token是否存在更可靠避免过期 Token 导致后续接口 401。5. MySQL 多库拆分与 MyBatis Plus 多数据源配置为分布式事务打基础5.1 为什么毕业设计要拆user_db、product_db、order_db不只是为了“高大上”单库单表在并发量 1000 QPS 时必然成为瓶颈。拆库的核心目的有二物理隔离故障域order_db出现慢 SQL不会拖垮user_db的登录接口为 Seata 分布式事务铺路Seata 的 AT 模式要求每个业务库都建undo_log表若所有表挤在一个库undo_log无法按业务归属划分事务回滚将混乱三库结构示意库名主要表说明user_dbsys_user,sys_role,sys_user_role用户认证与权限product_dbpms_product,pms_category,pms_sku商品中心order_dboms_order,oms_order_item,oms_payment订单与支付5.2 MyBatis Plus 多数据源配置以 user-service 为例user-service只需访问user_db但order-service需同时访问order_db主和user_db查用户信息、product_db查商品信息。因此order-service需配置多数据源。pom.xml加入dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-extension/artifactId version3.5.3.1/version /dependency dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.18/version /dependencyapplication-dev.yaml中定义数据源spring: datasource: dynamic: primary: order-ds # 默认数据源 strict: false datasource: order-ds: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/order_db?... username: root password: 123456 user-ds: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/user_db?... username: root password: 123456 product-ds: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/product_db?... username: root password: 123456Java 代码中使用DS(user-ds)切换数据源Service public class OrderServiceImpl implements OrderService { Autowired private OrderMapper orderMapper; Autowired private UserMapper userMapper; // 此 Mapper 对应 user-ds Override DS(order-ds) public void createOrder(Order order) { orderMapper.insert(order); // 查询用户信息跨库 User user userMapper.selectById(order.getUserId()); // 自动走 user-ds // ... } }提示DS注解需配合DynamicDataSourceRegister自动注册数据源 Bean否则会报Could not determine embedded database driver class。完整配置见DynamicDataSourceConfig.java核心是DataSourceRouter实现determineCurrentLookupKey()方法。5.3 数据库初始化脚本执行顺序与依赖关系解压包中的sql/目录下必须按以下顺序执行nacos-mysql.sql→ 初始化 Nacos 配置中心元数据表user_db.sql→ 创建user_db及表结构product_db.sql→ 创建product_db及表结构order_db.sql→ 创建order_db及表结构特别注意order_db.sql中的oms_order表含外键user_id但未实际关联user_db.sys_user.id跨库外键不生效因此user_id字段仅作逻辑引用应用层需通过 Feign 调用user-service接口获取用户详情。这是分布式架构的典型取舍放弃强一致性外键换取系统解耦与水平扩展能力。6. 验证分布式链路是否真正打通从浏览器 F12 到 Nacos 实例列表的全路径追踪6.1 用 Chrome DevTools Network 面板确认网关路由生效启动全部服务后打开http://localhost:8080Vue点击「登录」按钮。在 Chrome 的 Network 面板中筛选XHR找到POST /api/user/login请求Headers → General查看Request URL是否为http://localhost:8080/api/user/login前端发出Headers → Response Headers确认access-control-allow-origin: http://localhost:8080存在且vary: Origin字段出现证明网关 CORS 配置生效Preview返回 JSON 中含token字段且Authorization头已出现在 Request Headers 中此时请求流为Vue (8080)→Nginx (80)→Gateway (8081)→Nacos 查找 user-service 实例→user-service (8082)→user_db6.2 在 Nacos 控制台验证服务健康状态与实例数登录http://localhost:8848/nacos进入「服务列表」user-service显示 1 个实例IP 为127.0.0.1端口8082状态UPproduct-service同上端口8083order-service同上端口8084gateway-service同上端口8081点击任一服务的「详情」查看「健康实例数」是否为 1「不健康实例数」为 0。若显示0常见原因有user-service的application.yml中spring.cloud.nacos.discovery.server-addr地址错误如写成http://localhost:8848应为localhost:8848防火墙阻止了8082端口Windows 用户需在「高级安全 Windows 防火墙」中放行该端口6.3 日志串联用 traceId 验证全链路唯一标识在user-service的UserController.login()方法开头加入GetMapping(/info) public ResultUser getUserInfo() { String traceId MDC.get(X-B3-TraceId); // Spring Cloud Sleuth 默认注入 log.info(getUserInfo traceId: {}, traceId); // ... }启动时添加 JVM 参数启用 Sleuthuser-service的VM options-Dspring.sleuth.enabledtrue -Dspring.sleuth.web.skipPattern(^/actuator.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html|/favicon.ico|/webjars/.*)然后在 Gateway 和 user-service 的日志中搜索traceId应能在两处日志中找到完全相同的 ID证明链路已贯通。这是排查分布式环境下性能瓶颈或异常的黄金线索。本文还有配套的精品资源点击获取