springboot模块化搭建nacos微服务

为什么要模块化

随着项目的不断发展,需求和业务的不断细化与添加,工程代码会越来越庞大,包结构也越来越复杂,不同方面的代码之间相互耦合,杂乱而无章,并且开发人员也都同时在这一个项目里修改,合并代码时必然会出现各种各样的问题,而且当一位新的人员参与进项目,很难对项目有一个直观的感受,这间接的导致了开发效率的下降。
多模块化,正式解决上述问题而产生的,总的来说模块化开发有以下几点好处:

  • 降低耦合度。每个模块都有自己的解释,开发者可以更清晰的定制自己模块的内容
  • 项目代码更加清晰。功能模块划分,项目结构更加赏心悦目,并且可以对项目有一个更加直观的认识
  • 对于开发人员的配置,也有了更好的划分。每个人或每个小组更清楚自己要负责那一模块的开发,也可以大大降低合并代码时带来的冲突问题
  • 可以让新加入的开发人员,更快速的熟悉代码
  • 对于当下流行的微服务架构,多模块化也带来了很多方便。比如把公用实体类pojo提取出来,在微服务之间用feign互相调用的时候,遇到实体类的参数,就可以直接使用了

springboot模块化项目搭建

本文以springboot集成nacos的注册中心和feign为例,编译器用的Intellij IDEA,Java版本是1.8。
其实我用模块化开发,主要原因是微服务之间用feign互相调用接口的时候,发现实体类的参数没法传递啊,传个map感觉又不太雅观不正规,所以就想到了这个办法,把公用的实体类放到pom里面,直接搞成模块化

创建父模块

File—>New—>Project
springboot模块化搭建nacos微服务_第1张图片
最外层的父模块,无须启动类,直接创建maven工程
springboot模块化搭建nacos微服务_第2张图片
springboot模块化搭建nacos微服务_第3张图片
自定义创建好了,直接Next,Next,Finish完事!springboot模块化搭建nacos微服务_第4张图片
下面看一下父模块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">
    <!--声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。 -->
    <modelVersion>4.0.0</modelVersion>

    <!--父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。 坐标包括group ID,artifact ID和
      version。 -->
    <!--父模块为springboot-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
    </parent>

    <!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
    <!--项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。并且构建时生成的路径也是由此生成, 如com.mycompany.app生成的相对路径为:/com/mycompany/app -->
    <groupId>com.shopping.nacos</groupId>
    <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
    <!-- 构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID;在某个
       特定的group ID下,artifact ID也必须是唯一的。构件是项目产生的或使用的一个东西,Maven为项目产生的构件包括:JARs,源 码,二进制发布和WARs等。 -->
    <artifactId>shopping</artifactId>
    <!-- 版本号 -->
    <version>1.0-SNAPSHOT</version>
    <!--打包方式,项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型 -->
    <packaging>pom</packaging>
    <!--统一管理版本号-->
    <properties>
        <java.version>1.8</java.version>
        <spingboot.version>2.3.1.RELEASE</spingboot.version>
        <cloud.version>Greenwich.SR2</cloud.version>
        <cloud.alibaba.version>0.2.2.RELEASE</cloud.alibaba.version>
        <mybatis-plus.version>3.1.0</mybatis-plus.version>
    </properties>


    <!--引入的下一层级的所有子模块-->
    <modules>
       
    </modules>


    <!--<dependencyManagement>主要管理版本,对于子类继承同一个父类是很有用的,集中管理依赖版本不添加依赖关系,对于其中定义的版本,子pom不一定要继承父pom所定义的版本。-->
    <!--指定cloud的版本和nacos的版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${
     cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${
     cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <!--引入的依赖,这里引入了,子模块就默认继承了父模块的依赖-->
    <dependencies>
        <!--公用依赖:springboot web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--公用依赖:springboot test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--&lt;!&ndash;lombok&ndash;&gt;-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--StringUtils工具包-->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>
    <!--这里是打包时候的设置,如果有入口类,还需要加一个入口类的设置.还有其他问题什么的,自行百度吧-->
    <build>
        <plugins>
            <!--这是因为测试代码时遇到错误,它会停止编译。只需要在pom.xml的<project>里添加以下配置,使得测试出错不影响项目的编译。-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <testFailureIgnore>true</testFailureIgnore>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

pom可以分为几块去看

  • 指定父模块
  • 定义自己的groupId,artifactId,version,packaging,name等等
  • properties 统一管理的版本号
  • modules 引入的下一层的子模块,这个在创建子模块的时候会自动引入
  • dependencyManagement 指定管理依赖的版本,对于子继承同一个父类是很有用的,子模块再引入标签内的依赖,不指定版本的话,就默认用父类的版本,当然子类也可以自己指定版本。还有一点,注意这里并不是引入依赖,dependencies才是引入依赖
  • dependencies 引入的依赖,这里是真的引入了。引入了以后,子模块就默认继承了父模块的依赖
  • build plugins 这里是打包时候的设置

创建公用子模块

公用子模块,顾名思义,就是都能用到的功能,抽离出来,然后谁用,就在Pom里引入就行了。
比如下面这个例子中,mybatis的分页插件,我单独抽出来了,其实好像并没有什么必要,一是因为举例说明,二是如果以后又什么新功能配置加入,好做横向扩展,到时候就看出作用。
公用的pojo我也抽离出来了,这的作用主要是一些微服务之间共享的实体类
下面我们从父模块下面创建公用的子模块
公用子模块就是用来放公用的接口,方法,配置,还有实体类等等
springboot模块化搭建nacos微服务_第5张图片
springboot模块化搭建nacos微服务_第6张图片
因为这个模块是公用的模块,比如放一些基本配置啊,pojo实体类啊什么的,所以这里不用启动类,直接创建个maven工程就可以了,基本流程还是和上面一样,选择Module,选择Maven,创建就完事
springboot模块化搭建nacos微服务_第7张图片
这是创建好的公用子模块,里面还要放各种公用的模块,依然把src删了。
配置一下这个公用子模块的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">
    <!--父模块,创建好了就有了-->
    <parent>
        <artifactId>shopping</artifactId>
        <groupId>com.shopping.nacos</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <!--项目的唯一ID,就是刚才创建时候的名字-->
    <artifactId>shopping-common</artifactId>
    <!--因为这里下面还有子模块,这里的打包方式也要用pom-->
    <packaging>pom</packaging>
    <description>公用模块</description>
    <!--下面的子模块-->
    <modules>

    </modules>
</project>

然后再以相同的步骤,在这个子模块里,再创建子模块,依然是创建maven工程。这个嵌套的子模块,就是具体的公用功能了
不同的是src目录别删,因为要写具体的功能springboot模块化搭建nacos微服务_第8张图片springboot模块化搭建nacos微服务_第9张图片
在java文件夹下,创建目录
首先把java文件夹变成蓝色文件夹,Sources类型,这样才能在下面创建java class
springboot模块化搭建nacos微服务_第10张图片
springboot模块化搭建nacos微服务_第11张图片
创建目录结构,之所以这样创建,是因为整个项目总体需要统一起来,当引入其他模块的时候,其他模块的启动类才可以把这里的启动配置加载进去
springboot模块化搭建nacos微服务_第12张图片
创建好了Mybatisplus的分页插件

下面贴出mybatis子模块的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">
    <parent>
        <artifactId>shopping-common</artifactId>
        <groupId>com.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shopping-common-mybatis</artifactId>
    <!--这里具体到功能了,需要打成jar包了-->
    <packaging>jar</packaging>

    <description>mybatis公用类</description>

    <dependencies>
        <!--=========mybatis plus======================-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${
     mybatis-plus.version}</version>
        </dependency>
        <!--&lt;!&ndash;&lt;!&ndash;=========mysql======================&ndash;&gt;&ndash;&gt;-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
</project>

注意,这里的packaging要设置成jar了,因为具体到功能模块了

公用子模块的创建就到这了,其他需要啥公用的功能,往里加就完事了

下面再创建一个pojo公用实体类的模块
前面创建步骤和上面一样
springboot模块化搭建nacos微服务_第13张图片
这里需要引入刚才创建的mybatisplus模块,因为实体类需要mybatisplus的@TableName等注解

还有什么其他的公用的模块,比如日志,权限,工具类等等公用的模块都可以像上述模块一样往里加,下面将功能模块的创建,以及如何调用这些公用的模块

创建微服务功能模块

订单服务

功能模块就是具体到业务里的某个功能了,作为微服务,是需要有启动类的,所以需要创建springboot项目,并且打包方式为jar
首先我们创建一个模块,暂且就定义为订单服务吧
创建流程
springboot模块化搭建nacos微服务_第14张图片
springboot模块化搭建nacos微服务_第15张图片
springboot模块化搭建nacos微服务_第16张图片
springboot模块化搭建nacos微服务_第17张图片
springboot模块化搭建nacos微服务_第18张图片
首先要做的是
springboot模块化搭建nacos微服务_第19张图片
注意,是删掉这个文件夹,把启动类,复制到nacos文件夹下。因为所有模块的启动类,这里尽量都要保证在com.shopping.nacos下,因为这样启动的时候才会正确加载启动所有要引入的配置项。往后的模块也需要这样做,都统一起来

下面我们来修改一下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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--指定父依赖-->
    <parent>
        <groupId>com.shopping.nacos</groupId>
        <artifactId>shopping</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.shopping.nacos</groupId>
    <artifactId>shopping-order</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>shopping-order</name>
    <packaging>jar</packaging>
    <description>订单信息微服务</description>


    <dependencies>
        <!--引入自定义mybatis插件模块-->
        <dependency>
            <groupId>com.shopping.nacos</groupId>
            <artifactId>shopping-common-mybatis</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--引入alibaba nacos注册中心依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.shopping.nacos</groupId>
            <artifactId>shopping-common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- Redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--Redisson-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.8.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--这里引入了spring-boot-maven-plugin,打包时会去扫描项目main方法入口,也就是说引入该配置,你就必须在项目src/main/java/下创建一个spring-boot启动类:-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

修改了parent为自己的父类,packaging打包方式为jar,还有把指定版本的properties删掉,因为这些都要写在父依赖的pom里。下面dependencies里面需要引入本模块需要的依赖。
注意这里引入了上面自己的Mybatis和Pojo,这样确实方便和舒适很多。

然后,找到最外层父依赖的pom,把这个模块加进去
springboot模块化搭建nacos微服务_第20张图片
很清楚了吧兄弟

下面,来配置订单服务模块的配置文件

server:
  port: 8001
spring:
  application:
    #服务名,微服务用此名字注册服务并发现服务
    name: shopping-order
  cloud:
    nacos:
      discovery:
        #nacos服务注册与发现地址
        server-addr: IP:8848
    #数据源配置
  datasource:
    username: root
    password: 密码
    url: jdbc:mysql://IP:3306/shopping_mall?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    driver-class-name: com.mysql.jdbc.Driver

  #Redis配置
  redis:
    database: 0
    host: IP
    port: 6379
    password: 密码
    timeout: 1000


mybatis-plus:
  # 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*Mapper.xml
  mapper-locations: classpath:mybatis/*Mapper.xml
  typeAliasesPackage: com.shoppingmall.wares.pojo
  global-config:
    db-config:
      #id-type: uuid
      #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
      field-strategy: 1
        #驼峰下划线转换
        #db-column-underline: true
        #刷新mapper 调试神器
        #refresh-mapper: true
        #数据库大写下划线转换
        #capital-mode: true
        # Sequence序列接口实现类配置
        #key-generator: com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
        #逻辑删除配置(下面3个配置)
      #logic-delete-value: 1
      #logic-not-delete-value: 0
      #sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
      #自定义填充策略接口实现
      #meta-object-handler: com.baomidou.springboot.MyMetaObjectHandler
  configuration:
    #配置返回数据库(column下划线命名&&返回java实体是驼峰命名),自动匹配无需as(没开启这个,SQL需要写as: select user_id as userId)
    #true:开启数据库下划线对应实体类转驼峰;false:不开启
    map-underscore-to-camel-case: true
    cache-enabled: false
    #配置JdbcTypeForNull, oracle数据库必须配置
    jdbc-type-for-null: 'null'
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    database-id: mysql

注意name: shopping-order这个服务名字很重要,服务之间通信全靠他了。

下面,启动类加入@EnableDiscoveryClient,开启Naocs服务与发现注册中心
springboot模块化搭建nacos微服务_第21张图片
然后创建个controller,写个post请求的接口
springboot模块化搭建nacos微服务_第22张图片
启动订单模块,看nacos控制台,服务列表,已经有shopping-order这个服务了
springboot模块化搭建nacos微服务_第23张图片

库存模块

下面我们创建一个消费服务的库存模块
和上面的步骤一样,我就不重复贴了。这里测试一下,库存模块来消费订单模块的接口,所以加入了feign。

 <!--引入alibaba nacos-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.shopping.nacos</groupId>
            <artifactId>shopping-common-mybatis</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.shopping.nacos</groupId>
            <artifactId>shopping-common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

这是需要引入的依赖

启动类上加入2个注解,一个是nacos注册中心服务发现的注解@EnableDiscoveryClient,另一个是feign的注解@EnableFeignClients
springboot模块化搭建nacos微服务_第24张图片

配置文件,贴代码

server:
  port: 8002
spring:
  application:
    name: shopping-order
  cloud:
    nacos:
      discovery:
        server-addr: IP:8848

  datasource:
    username: root
    password: zaqxsw
    url: jdbc:mysql://IP:3306/shopping_mall?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    driver-class-name: com.mysql.jdbc.Driver

mybatis-plus:
  mapper-locations: classpath:mybatis/*Mapper.xml
  typeAliasesPackage: com.shoppingmall.wares.pojo
  global-config:
    db-config:
      field-strategy: 1

  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false
    jdbc-type-for-null: 'null'
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    database-id: mysql
#fengin请求超时时间,单位毫秒
ribbon:
  ReadTimeout: 5000
  ConnectTimeout: 5000
创建feign Service类

springboot模块化搭建nacos微服务_第25张图片
@FeignClient(“shopping-order”)注解,表明了这是个feign类,括号里是调用的服务名字,下面的写的接口,是调用"shopping-order"服务暴露的接口方法,对照上面的订单服务
然后在controller层去调用这个接口,去测试一下,feign的接口是不需要实现的
controller层
springboot模块化搭建nacos微服务_第26张图片
启动库存服务,看一下nacos操作平台,库存服务也注册到服务发现的列表里去了
springboot模块化搭建nacos微服务_第27张图片

测试

然后用postman测试一下,库存服务的端口是8002
springboot模块化搭建nacos微服务_第28张图片
好了,feign消费微服务成功!

下面我们将这这2个服务打包,放到不同的服务器上
订单服务放在201服务器上,库存服务放在202服务器上
springboot模块化搭建nacos微服务_第29张图片
springboot模块化搭建nacos微服务_第30张图片
OK,完事。
如果服务之间的feign接口,有实体类参数的话,直接pom里引入公用的pojo实体类,这么干,也可以搞定了。

你可能感兴趣的:(java,分布式,Spring,Cloud,Ali,Nacos,注册中心,maven)