news 2026/4/2 12:50:46

从0到1构建企业级微服务项目实战手册(精简版)(Spring Boot + Docker + CI/CD)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从0到1构建企业级微服务项目实战手册(精简版)(Spring Boot + Docker + CI/CD)

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!


本手册将手把手带你从零搭建一个生产可用的分布式微服务系统,涵盖架构设计、核心组件封装、中间件集成、容器化部署与自动化流水线。内容面向 Java 项目 Leader,注重工程落地性可维护性

全书分为六章,每章均含详细说明、代码示例、反例警示与最佳实践。


第一章:从0到1构建微服务架构

1.1 微服务选型与项目结构

✅ 正确做法:多模块 Maven 项目结构
my-shop/ ├── pom.xml # 父POM,统一管理依赖版本 ├── my-shop-gateway/ # API网关 ├── my-shop-auth/ # 鉴权中心(JWT/OAuth2) ├── my-shop-user/ # 用户服务 ├── my-shop-order/ # 订单服务 ├── my-shop-common/ # 公共模块(工具类、异常、DTO等) └── my-shop-starter/ # 自定义Starter(如租户、上下文)

父 POM 关键配置(pom.xml)

<properties> <spring-boot.version>3.2.5</spring-boot.version> <spring-cloud.version>2023.0.0</spring-cloud.version> <mybatis-plus.version>3.5.5</mybatis-plus.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> </dependencies> </dependencyManagement>

💡为什么这样用?
统一依赖版本避免“Jar Hell”,多模块解耦便于团队协作和独立部署。


1.2 网关(Spring Cloud Gateway)

场景:所有请求经网关路由 + 鉴权

my-shop-gateway/pom.xml

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>

application.yml

spring: cloud: gateway: routes: - id: user-service uri: lb://my-shop-user # 基于Nacos服务发现 predicates: - Path=/api/user/** filters: - StripPrefix=1
自定义全局过滤器(鉴权)
@Component public class AuthGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getHeaders().getFirst("Authorization"); if (token == null || !token.startsWith("Bearer ")) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } // 可调用 auth 服务校验 token return chain.filter(exchange); } @Override public int getOrder() { return -100; // 优先级高 } }

反例:在每个微服务里重复写鉴权逻辑 → 代码冗余、难以维护。
正解:网关统一拦截,auth 服务提供 token 校验 API。


1.3 鉴权中心(JWT + Spring Security)

my-shop-auth 模块核心逻辑

// 登录接口 @PostMapping("/login") public ResponseEntity<TokenDTO> login(@RequestBody LoginDTO dto) { // 1. 校验用户名密码 User user = userService.validate(dto.getUsername(), dto.getPassword()); if (user == null) throw new BadCredentialsException("Invalid credentials"); // 2. 生成 JWT(含用户ID、租户ID、角色) String token = JwtUtil.createToken(user.getId(), user.getTenantId(), user.getRoles()); return ResponseEntity.ok(new TokenDTO(token)); }

JwtUtil.java

public class JwtUtil { private static final String SECRET = "myShopSecretKey2025"; private static final long EXPIRATION = 86400000; // 24h public static String createToken(Long userId, String tenantId, List<String> roles) { return Jwts.builder() .claim("userId", userId) .claim("tenantId", tenantId) .claim("roles", roles) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION)) .signWith(SignatureAlgorithm.HS512, SECRET) .compact(); } public static Claims parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token.replace("Bearer ", "")) .getBody(); } }

⚠️注意事项

  • SECRET 必须配置在配置中心(如 Nacos),不可硬编码。
  • 生产环境建议使用 RSA 非对称加密。

第二章:核心组件封装

2.1 MyBatis-Plus 封装

my-shop-common 模块中定义 BaseMapper

@Mapper public interface MyBaseMapper<T> extends BaseMapper<T> { // 可扩展逻辑删除、自动填充等 }

实体类自动填充创建时间/更新时间

@Data public class BaseEntity { @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; } @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class); this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); } }

优势:避免每个实体重复写时间字段,提升开发效率。


2.2 多租户支持(基于 Schema 隔离)

场景:SaaS 系统,每个租户数据独立。

方案:动态数据源 + MyBatis-Plus 租户插件

  1. 租户上下文
public class TenantContext { private static final ThreadLocal<String> TENANT_ID = new ThreadLocal<>(); public static void setTenantId(String tenantId) { TENANT_ID.set(tenantId); } public static String getTenantId() { return TENANT_ID.get(); } public static void clear() { TENANT_ID.remove(); } }
  1. 自定义租户处理器
@Component public class MyTenantLineHandler implements TenantLineHandler { @Override public Expression getTenantId() { String tenantId = TenantContext.getTenantId(); if (tenantId == null) { throw new RuntimeException("Tenant ID not found in context!"); } return new StringValue(tenantId); } @Override public boolean ignoreTable(String tableName) { return "sys_tenant".equals(tableName); // 租户表不加条件 } }
  1. 注册插件
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterpreter(); interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new MyTenantLineHandler())); return interceptor; }

反例:在 SQL 中手动拼接WHERE tenant_id = ?→ 容易遗漏,安全风险高。
正解:通过插件自动注入,100% 覆盖。


2.3 上下文信息封装(Request Context)

目标:在任意 Service 层获取当前用户、租户、TraceID。

public class RequestContext { private static final ThreadLocal<UserInfo> USER_INFO = new ThreadLocal<>(); public static void set(UserInfo info) { USER_INFO.set(info); } public static UserInfo getUserInfo() { return USER_INFO.get(); } public static void clear() { USER_INFO.remove(); } }

在网关或拦截器中设置

// 在 AuthGlobalFilter 或 WebMvcConfigurer 中 Claims claims = JwtUtil.parseToken(token); UserInfo user = new UserInfo(claims.get("userId", Long.class), claims.get("tenantId", String.class)); RequestContext.set(user);

⚠️重要:必须在请求结束时clear(),否则 ThreadLocal 内存泄漏!


第三章:中间件容器化部署与集成

3.1 使用 Docker Compose 一键启动中间件

docker-compose.yml

version: '3.8' services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: my_shop ports: - "3306:3306" volumes: - ./mysql/data:/var/lib/mysql redis: image: redis:7.0 ports: - "6379:6379" rabbitmq: image: rabbitmq:3.12-management ports: - "5672:5672" - "15672:15672" environment: RABBITMQ_DEFAULT_USER: admin RABBITMQ_DEFAULT_PASS: admin123 elasticsearch: image: elasticsearch:8.9.0 environment: discovery.type: single-node xpack.security.enabled: "false" ports: - "9200:9200" kibana: image: kibana:8.9.0 depends_on: - elasticsearch ports: - "5601:5601"

启动命令:

docker-compose up -d

3.2 Spring Boot 集成各中间件

Redis 配置(application.yml):
spring: redis: host: localhost port: 6379 lettuce: pool: max-active: 8
RabbitMQ 生产者示例:
@Autowired private RabbitTemplate rabbitTemplate; public void sendOrderCreated(Long orderId) { rabbitTemplate.convertAndSend("order.exchange", "order.created", orderId); }
Elasticsearch Repository:
public interface ProductRepository extends ElasticsearchRepository<Product, String> { List<Product> findByNameContaining(String name); }

最佳实践:所有中间件连接信息应从配置中心读取,而非写死在 yml。


第四章:Docker 容器化部署

4.1 为每个微服务编写 Dockerfile

my-shop-user/Dockerfile

FROM openjdk:17-jdk-slim COPY target/my-shop-user.jar /app.jar EXPOSE 8081 ENTRYPOINT ["java", "-jar", "/app.jar"]

4.2 构建镜像并运行

# 构建 ./mvnw clean package -DskipTests docker build -t my-shop-user:1.0 . # 运行(连接到 docker-compose 网络) docker run --network my-shop_default -p 8081:8081 my-shop-user:1.0

⚠️注意:微服务之间通过服务名通信(如http://my-shop-user:8081),而非 localhost。


第五章:CI/CD 流水线搭建(GitLab CI 示例)

.gitlab-ci.yml

stages: - build - test - deploy variables: DOCKER_HOST: tcp://docker:2375 DOCKER_TLS_CERTDIR: "" build: stage: build script: - ./mvnw clean package -DskipTests - docker build -t $CI_REGISTRY_IMAGE/user:$CI_COMMIT_SHORT_SHA ./my-shop-user - docker push $CI_REGISTRY_IMAGE/user:$CI_COMMIT_SHORT_SHA deploy-prod: stage: deploy script: - ssh user@prod-server "docker pull $CI_REGISTRY_IMAGE/user:$CI_COMMIT_SHORT_SHA && docker stop user || true && docker rm user || true" - ssh user@prod-server "docker run -d --name user --network host $CI_REGISTRY_IMAGE/user:$CI_COMMIT_SHORT_SHA" only: - main

关键点:自动化测试、镜像版本控制、滚动发布。


第六章:Nginx 反向代理与 HTTPS

6.1 nginx.conf 配置

upstream gateway { server my-shop-gateway:8080; # Docker 内部服务名 } server { listen 80; server_name api.myshop.com; location / { proxy_pass http://gateway; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

6.2 前端静态资源托管

server { listen 80; server_name www.myshop.com; root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ /index.html; } }

🔒生产建议:配置 Let's Encrypt 免费 SSL 证书,强制 HTTPS。


总结

作为 Java 项目 Leader,你不仅要会写代码,更要掌控整个交付链路

  • 架构清晰(网关+鉴权+服务拆分)
  • 组件可复用(租户、上下文、MyBatis-Plus)
  • 中间件标准化(Docker Compose 管理)
  • 部署自动化(CI/CD + Docker)
  • 运维可观测(Nginx + ELK)

这套体系已在多个 SaaS 项目中验证,稳定支撑日活百万用户。

从0-1搞一个分布式微服务系统上线,要是细讲内容还是很多的,先写个大概,看下数据,后面有没有必要出一个超级详细版的

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/31 18:11:01

Open-AutoGLM究竟有多强?:谷歌AI工程师不愿公开的5大核心技术细节

第一章&#xff1a;Open-AutoGLM究竟有多强&#xff1f;——重新定义自动化大模型工程Open-AutoGLM 是新一代开源自动化大语言模型工程框架&#xff0c;旨在打通从模型训练、微调、推理优化到部署的全链路闭环。它不仅支持多模态任务自动调度&#xff0c;还引入了基于强化学习的…

作者头像 李华
网站建设 2026/4/1 8:35:00

Dify平台节日祝福语批量生成技巧分享

Dify平台节日祝福语批量生成技巧分享 在春节临近、客户关怀密集的营销高峰期&#xff0c;如何为成百上千的用户送出既个性化又不失温度的节日祝福&#xff1f;这是许多运营团队年复一年面临的挑战。过去&#xff0c;文案人员需要逐条撰写、反复修改&#xff1b;如今&#xff0c…

作者头像 李华
网站建设 2026/4/2 9:48:25

Dify平台园艺种植建议生成功能探索

Dify平台园艺种植建议生成功能探索 在城市阳台种菜越来越流行&#xff0c;但很多人面对“什么时候播种”“土壤要不要加酸”这类问题时&#xff0c;仍只能靠搜索碎片信息或凭经验试错。有没有可能让AI像一位懂气候、识植物的老园丁一样&#xff0c;根据你所在的城市和想种的作物…

作者头像 李华
网站建设 2026/3/28 9:18:33

终极论文AI神器:7款工具告别写作恐惧,一键搞定无压力!

引言&#xff1a;为什么你需要AI论文工具&#xff1f; 论文写作是每个科研人绕不开的“噩梦”&#xff1a;选题时抓耳挠腮、初稿时无从下笔、改稿时被导师批注淹没、查重时反复降重……这些痛点不仅消耗时间&#xff0c;更消磨学术热情。2024年&#xff0c;AI论文工具已从“辅…

作者头像 李华
网站建设 2026/4/1 18:30:13

Open-AutoGLM谷歌实战指南(从零搭建自动化大模型)

第一章&#xff1a;Open-AutoGLM谷歌实战指南概述Open-AutoGLM 是一款面向自动化大语言模型任务的开源工具&#xff0c;专为在谷歌云平台&#xff08;GCP&#xff09;上高效部署和调优 GLM 系列模型而设计。它集成了模型微调、推理服务、资源调度与监控能力&#xff0c;适用于 …

作者头像 李华
网站建设 2026/3/28 16:55:28

22、神经网络模型训练与逻辑回归从零实现

神经网络模型训练与逻辑回归从零实现 1. 模型训练 首先,我们要构建一个简单的三层神经网络,每层包含 5 个神经元。以下是构建网络的代码: import tensorflow as tf import numpy as nptf.reset_default_graph() n1 = 5 # Number of neurons in layer 1 n2 = 5 # Numbe…

作者头像 李华