搭建微服务项目骨架:通过 Maven 多模块方式

相关概念

在搭建项目之前,先了解一下相关概念。

什么是单体架构

image-20260202200454590

单体架构是一种传统的软件架构模式,通常将整个应用作为一个单一的、独立部署的单元来开发、构建和部署。在单体架构中,所有的功能模块和业务逻辑都打包在同一个应用程序中,比如 weblog 项目,最终是打包成一个 Jar 包来部署。这包括业务逻辑、数据访问和数据存储等。整个应用程序通常部署在一个应用服务器上,与外部系统通过接口进行通信。

单体架构开发简单,部署方便,适合流量不大的应用。但随着应用规模的增长,往往会遇到可扩展性差、维护困难、部署风险高等问题。

微服务架构是一种将应用程序拆分为多个小型、自治的服务的架构模式。可以通过上图本项目的架构图来理解。每个服务都专注于实现一个特定的业务功能,并通过轻量级的通信机制(如 HTTP 或 RPC)与其他服务进行通信。微服务架构将整个应用程序拆分成多个松耦合的服务单元,每个服务单元都可以独立开发、测试、部署和扩展。微服务架构有助于提高灵活性、可扩展性和可维护性,适合大流量型应用。但也增加了部署和运维的复杂性,需要考虑服务间通信、服务注册与发现、服务监控等方面的问题。

Spring Cloud

img

Spring Cloud 是基于 Spring Boot 的微服务架构开发工具包,提供了一系列开发工具和库,用于快速构建、部署和管理分布式系统中的微服务应用。Spring Cloud提供了诸如服务发现、服务注册、负载均衡、断路器、配置管理、消息总线等功能,帮助开发人员解决了微服务架构中的常见问题,简化了微服务应用的开发和部署流程。

Spring Cloud Alibaba

Spring Cloud Alibaba 是 Spring Cloud 生态的一部分,提供了一系列基于阿里巴巴开源产品的分布式解决方案和工具,用于构建和管理基于 Spring Cloud 的微服务应用。Spring Cloud Alibaba 集成了阿里巴巴开源的服务,如 Nacos(服务注册与发现)、Sentinel(流量控制和熔断降级)、Dubbo(远程服务调用)、RocketMQ(消息队列)等,为开发人员提供了一站式的微服务解决方案。Spring Cloud Alibaba 与 Spring Cloud 兼容,并且提供了额外的功能和工具,帮助开发人员更轻松地构建、部署和管理微服务应用。

多模块项目

什么是多模块项目?

多模块项目是项目构建中的概念。拿 Maven 来说,多模块项目(Multi-Module Project)是其一个重要特性,它允许我们在一个项目中管理多个子模块。

在一个 Maven 多模块项目中,每个模块都是一个独立的项目,拥有自己的 POM 文件(Project Object Model,项目对象模型)。这些模块可以互相依赖,也可以被其他项目依赖。但是,所有的模块都会被统一管理,它们共享同一套构建系统和依赖管理。

Maven 多模块项目的结构大概是下面这样的:

my-app/  (父项目)
  |- pom.xml
  |- my-module1/  (子模块1)
  |    |- pom.xml
  |- my-module2/  (子模块2)
       |- pom.xml
  | ... (实际企业级项目中,会分非常多的模块)   

在这个例子中,my-app 是父项目,my-module1my-module2 是它的子模块。每个模块都有自己的 pom.xml 文件。

为什么需要多模块项目?

主要有以下几个原因:

  • 代码组织:在大型项目中,我们经常需要把代码分成多个模块,以便更好地组织代码。每个模块可以聚焦于一个特定的功能或领域,这样可以提高代码的可读性和可维护性。
  • 依赖管理:Maven 多模块项目可以帮助我们更好地管理项目的依赖。在父项目的 POM 文件中,我们可以定义所有模块共享的依赖,这样可以避免重复的依赖定义,也方便我们管理和升级依赖。
  • 构建和部署:Maven 多模块项目的另一个优点是它可以统一管理项目的构建和部署。我们只需要在父项目中执行 Maven 命令,就可以对所有模块进行构建和部署。这大大简化了开发者的工作。

IDEA 搭建微服务多模块工程骨架

创建父模块

打开 IDEA, 这里我使用的是 2025 版本,即最新的IDEA不同版本的IDEA操作类似。依次点击左上角菜单 File | New | Project , 开始创建项目:

image-20260202201136339

解释一下标注的地方:

  • ①:选择 Maven Archetype 来创建一个 Maven 项目;
  • ②:项目名称,hannote;
  • ③:项目创建的位置;
  • ④:项目使用的 JDK 版本,本项目使用的是 JDK 25 ,因为有虚拟线程这一大杀器;
  • ⑤:IDEA 需要知道 Maven Archetype Catalog 的位置,以便从中获取可用的 Archetype 列表。这个 Catalog 文件通常包含了 Maven 官方仓库或其他远程仓库中可用的 Archetype 信息。选择 Internal 即可。
  • ⑥:通过使用 Archetype,你可以基于已有的项目模板创建一个新项目。这里选择 maven-archetype-quickstart
  • ⑦:填写 Group 组织名称,通常为公司域名倒写,如 com.hanserwei
  • ⑧:项目的唯一标识符;
  • ⑨:项目版本号,默认就行;

创建完毕之后,第一步删除掉src目录:

image-20260202201416674

父模块仅需要保留一个 pom.xml 文件,用于统一管理依赖、插件等。如下图所示:

截至目前:2026年2月2日,Spring Cloud Alibaba 2025.1.0的正式版还没发布,我目前先使用快照版本,正式版据issue说,一个星期内发布!

  <servers>
    <server>
      <id>github</id>
      <username>${env.GITHUB_ACTOR}</username>
      <password>${env.GITHUB_TOKEN}</password>
    </server>
  </servers>

创建 GitHub Token 地址:https://github.com/settings/tokens。然后替换掉上面的两个为你自己的token和名字。


<repositories>
    <repository>
        <id>github</id>
        <url>https://maven.pkg.github.com/alibaba/spring-cloud-alibaba</url>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>

以下是我的settings.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">

  <servers>
    <server>
      <id>github</id>
      <username>替换为你自己的</username>
      <password>替换为你自己的</password>
    </server>
  </servers>

  <mirrors>
    <mirror>
      <id>maven-default-http-blocker</id>
      <mirrorOf>external:http:*</mirrorOf>
      <name>Pseudo repository to mirror external repositories initially using HTTP.</name>
      <url>http://0.0.0.0/</url>
      <blocked>true</blocked>
    </mirror>
  </mirrors>

  <profiles>
    <profile>
      <id>github-repo</id>
      <repositories>
        <repository>
          <id>github</id>
          <url>https://maven.pkg.github.com/alibaba/spring-cloud-alibaba</url>
          <releases>
            <enabled>false</enabled>
          </releases>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
        </repository>
      </repositories>
    </profile>
  </profiles>

  <activeProfiles>
    <activeProfile>github-repo</activeProfile>
  </activeProfiles>
</settings>

然后修改顶层的pom文件如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <!-- Maven 项目对象模型版本 -->
    <modelVersion>4.0.0</modelVersion>

    <!-- 项目坐标信息 -->
    <groupId>com.hanserwei</groupId>
    <artifactId>hannote</artifactId>
    <version>${revision}</version>
    <name>${project.artifactId}</name>
    <description>小憨书(仿小红书),基于 Spring Cloud Alibaba 2025.1.0 微服务架构</description>

    <!-- 打包方式:pom 表示这是一个父项目 -->
    <packaging>pom</packaging>

    <!-- 子模块列表 -->
    <modules>
    </modules>

    <!-- 项目属性配置 -->
    <properties>
        <!-- 项目版本号 -->
        <revision>0.0.1-SNAPSHOT</revision>

        <!-- Java 版本配置 -->
        <java.version>25</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>

        <!-- 项目编码配置 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <!-- Spring Boot 版本 -->
        <spring-boot.version>4.0.2</spring-boot.version>

        <!-- Spring Cloud 版本 -->
        <spring-cloud.version>2025.1.1</spring-cloud.version>

        <!-- Spring Cloud Alibaba 版本 -->
        <spring-cloud-alibaba.version>2025.1.0.0-SNAPSHOT</spring-cloud-alibaba.version>

        <!-- Maven 编译插件版本 -->
        <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>

        <!-- Lombok 版本 -->
        <lombok.version>1.18.38</lombok.version>
    </properties>

    <!-- 依赖管理:统一管理项目依赖版本 -->
    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot 依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Spring Cloud 依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Spring Cloud Alibaba 依赖 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Lombok 依赖:用于简化 Java 代码 -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 构建配置 -->
    <build>
        <!-- 插件管理:统一管理构建插件 -->
        <pluginManagement>
            <plugins>
                <!-- Spring Boot Maven 插件:用于打包 Spring Boot 应用 -->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <executions>
                        <execution>
                            <id>repackage</id>
                            <goals>
                                <!-- 重新打包为可执行的 jar 文件 -->
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

                <!-- Maven 编译插件:配置 Java 编译参数 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven-compiler-plugin.version}</version>
                    <configuration>
                        <!-- 源码版本 -->
                        <source>${java.version}</source>
                        <!-- 目标版本 -->
                        <target>${java.version}</target>
                        <!-- 编码格式 -->
                        <encoding>${project.build.sourceEncoding}</encoding>
                        <!-- 注解处理器路径:配置 Lombok 注解处理器 -->
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${lombok.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

非常完美,到此为止,我们已经把多模块的maven项目的骨架搭建起来了,现在我们来引入第一个模块,用户认证微服务。

在父项目右键 | New | Module... , 来创建一个子模块:

image-20260202204441953

image-20260202204603732

我这里使用maven骨架来创建Spring Boot项目,这样我可以按需导入锁需要的依赖,这样整个工程看起来要更加清爽一些!如果你使用Spring Boot来创建,当然也是可以的。

auth服务的pom文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 父项目配置 -->
    <parent>
        <!-- 父项目的组织标识 -->
        <groupId>com.hanserwei</groupId>
        <!-- 父项目的唯一标识 -->
        <artifactId>hannote</artifactId>
        <!-- 父项目版本号,使用变量${revision}便于统一管理 -->
        <version>${revision}</version>
    </parent>

    <!-- 当前模块的唯一标识 -->
    <artifactId>hannote-auth</artifactId>
    <!-- 打包方式:jar包 -->
    <packaging>jar</packaging>

    <!-- 项目名称,使用Maven内置变量 -->
    <name>${project.artifactId}</name>
    <!-- 项目描述信息 -->
    <description>小憨书:认证服务(负责处理用户登录、注册、账号注销等)</description>

    <!-- 项目属性配置 -->
    <properties>
        <!-- 项目源代码和编译输出使用UTF-8编码 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!-- 项目依赖配置 -->
    <dependencies>
        <!-- Spring Boot Web启动器:用于构建Web应用,包含RESTful、Spring MVC等功能 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Boot测试启动器:用于单元测试和集成测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <!-- 作用域:仅在测试阶段使用,不会打包到最终的jar中 -->
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 项目构建配置 -->
    <build>
        <!-- 插件配置 -->
        <plugins>
            <!-- Spring Boot Maven插件:用于将应用打包成可执行的jar包 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

image-20260202205213539

完善一下启动类:

package com.hanserwei.hannote.auth;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author hanser
 */
@SpringBootApplication
public class HannoteAuthApplication {
    static void main() {
        SpringApplication.run(HannoteAuthApplication.class);
    }
}

添加一下配置文件:

image-20260202205526133

测试打包是否正常

接下来,我们测试一下多模块项目打包是否正常。对右侧栏中的父项目进行 clean package , 观察控制台日志,确认一下项目打包是否正常:

image-20260202205813333

启动认证服务

打包没问题后,再来测试一下认证服务是否能够正常运行。点击 XiaohashuAuthApplication 启动类的 main 方法左侧的运行按钮,来启动服务:

image-20260202210237841

若看到控制台输出 Tomcat started on port(s): 8080 信息,则表示服务成功运行在了 8080 端口上。打开浏览器,访问地址 localhost:8080 ,即可看到 Spring Boot 项目的页面提示信息了,如下图所示:

image-20260202210310774

看到这个就说明我们已经成功了。

结语

本小结中,我们了解了什么是单体架构、微服务架构,以及 Spring Cloud 、Spring Cloud Alibaba 之间的关系。然后,上手搭建了一个 Maven 多模块项目,并引入了 Spring Cloud Alibaba 2025.1.0 依赖, 还创建了一个子模块 —— 认证服务,并成功运行了起来。但是,目前还只是简单的多模块的项目,还没实际使用到微服务,后续小节中,将一点一点引入 Spring Cloud Alibaba 相关组件,将整个微服务体系渐进式的搭建起来。

扩展

众所周知,Java21开始引入了一个叫做虚拟虚拟线程的东西,这个玩意可以说是Java跨时代的东西,那么我们Spring Boot4对它支持如何呢,答案是支持非常的完美!现在我们来看看如何在Spring Boot4中开启虚拟线程的功能!

image-20260202210613893

写一个测试接口来看一下是否生效:

package com.hanserwei.hannote.auth.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author hanser
 */
@RestController
public class ThreadCheckController {

    @GetMapping("/check")
    public String check() {
        Thread thread = Thread.currentThread();
        return "Current Thread: " + thread.toString();
    }
}

访问这个接口:

image-20260202211131172

完美,可以看到tomcat已经由原来的平台线程池变成了虚拟线程。完美的蜕变!如果上述方式不起作用,可以尝试配置类的方式:

package com.hanserwei.hannote.auth.config;

import org.springframework.boot.tomcat.TomcatProtocolHandlerCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Executors;

/**
 * @author hanser
 */
@Configuration
public class TomcatConfiguration {


    /**
     * 配置Tomcat协议处理器使用虚拟线程执行器
     * 虚拟线程是Java 21引入的轻量级线程,可以大幅提升并发处理能力
     * 
     * @return Tomcat协议处理器自定义器
     */
    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> {
            // 为Tomcat的协议处理器设置虚拟线程执行器,每个任务创建一个新的虚拟线程
            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
        };
    }
}

这样也可以达到同样的效果!

当然,虚拟线程的作用远不止于此,在后续的章节我会给大家带来更多的它的用法。