微服务需要根据业务模块拆分,做到单一职责,不要重复开发相同业务。

父工程

微服务是一种分布式开发,要将一个项目拆分为若干个服务,所以会有很多个服务模块。而要统一管理这些服务模块,可以创建一个父工程来管理。

在Maven中,用来统一管理的父工程是一个不包含实际代码,只含有pom.xml的模块。通过在pom.xml定义一些统一的信息(如依赖、依赖的版本等等),从而来管理整个工程。

父工程Maven依赖(pom.xml):

<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>

    <groupId>asia.linner.demo</groupId>
    <artifactId>cloud-demo</artifactId>
    <version>1.0</version>

    <!-- 声明子模块 -->
    <modules>
        <module>user-service</module>
        <module>order-service</module>

        <!-- ... -->
    </modules>

    <!-- 打包方式 -->
    <packaging>pom</packaging>

    <!-- 父工程 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.9.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <mysql.version>5.1.47</mysql.version>
        <mybatis.version>2.1.1</mybatis.version>
    </properties>

    <!-- 声明依赖,并不进行导入(子模块依然需要导入,但不用指定版面) -->
    <dependencyManagement>
        <dependencies>
            <!-- SpringCloud依赖库 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- MySQL驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!-- MyBatis -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>

            <!-- ... -->
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- ... -->
    </dependencies>
</project>

其中主要的有:

  • 父工程:和SpringBoot一样,使用SpringCloud需要导入父工程。

    <!-- 父工程 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.9.RELEASE</version>
        <relativePath/>
    </parent>
    
  • SpringCloud依赖:

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

    声明在<dependencyManagement><dependencies>中。SpringCloud依赖库定义了SpringCloud的依赖以及它们的版本。

    <dependencyManagement>是对整个项目的依赖版本的管理。在<dependencyManagement>元素中声明所依赖的jar包的版本号等信息,那么所有子项目再次引入此依赖jar包时则无需显式的列出版本号,Maven会沿着父子层级向上寻找拥有<dependencyManagement>元素的项目,然后使用它指定的版本号。

    例如在SpringBoot中,引入了父工程spring-boot-starter-parent,那么引入spring-boot-starter-web这些在父工程中已经将版本定义好了的依赖,就无需在当前工程的pom.xml中指定版本。

    在当前<dependencies>(不是<dependencyManagement>下的<dependencies>中声明的依赖,会直接被导入,并且被子子项目所继承。

  • <modules>:利用<modules>可以很好地进行多模块开发。

    <!-- 声明模块 -->
    <modules>
        <module>user-service</module>
        <module>order-service</module>
    
        <!-- ... -->
    </modules>
    

    在构建当前项目时,Maven会根据<modules>中的声明,去寻找相应的模块并自动完成构建。

    <modules>的值是对应模块的<artifactId>的值。

微服务拆分

子模块Maven依赖示例(pom.xml):

<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">

    <!-- 与父工程中所定义的相对应 -->
    <parent>
        <groupId>asia.linner.demo</groupId>
        <artifactId>cloud-demo</artifactId>
        <version>1.0</version>
    </parent>
    
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>app</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

其中,该项目的父工程为

<parent>
    <groupId>asia.linner.demo</groupId>
    <artifactId>cloud-demo</artifactId>
    <version>1.0</version>
</parent>

模块声明的父工程对应父工程中定义的<groupId><artifactId><version>。当前项目会继承父工程中定义的版本号和依赖。所以spring-boot-starter-webmysql-connector-javamybatis-spring-boot-starter都无需显式地声明版本。