gradle 不支持多级子模块_Gradle子项目划分与微服务的代码结构

本文介绍了Gradle作为构建工具在微服务架构中的优势,并展示了如何进行子项目划分,包括主项目级别的配置文件、最小化构建工具、以及不同类型的子项目(如common、client、server、job)。通过实例详细解析了每个子项目的目录结构和作用,强调了代码组织的清晰性和可维护性。
摘要由CSDN通过智能技术生成

last modified by coder4

, 2019/08/30 18:34:26

Gradle子项目划分与微服务的代码结构

Gradle简介

如前序章节微服务技术栈概览所述,本书选用Java作为开发语言、Gradle作为构建工具。

与Maven相比,Gradle具有如下优势:

灵活性:Gradle内置了脚本支持,可以实现更强大、更灵活的构建功能。

高性能:Gradle支持并行编译、多级缓存,最高可节省90%的编译时间

易于维护:与xml相比,Gradle的依赖描述语言更简洁,更易于维护。

无缝兼容:Gradle无缝兼容Maven,已有的系统也可以轻松地迁移过来。

微服务架构下Gradle的子项目划分

在微服务的自动发现与负载均衡一章中,我们已经构建了一个微服务项目"lmsia-abc",让我们来看一下它的目录结构。为了清晰起见,只展示一层目录结构:

.

├── build.gradle

├── gradle

│ └── wrapper

├── gradlew

├── gradlew.bat

├── lmsia-abc-client

│ ├── build

│ ├── build.gradle

│ ├── out

│ └── src

├── lmsia-abc-common

│ ├── build

│ ├── build.gradle

│ ├── out

│ └── src

├── lmsia-abc.iml

├── lmsia-abc-job

│ ├── build

│ ├── build.gradle

│ ├── out

│ └── src

├── lmsia-abc-server

│ ├── build

│ ├── build.gradle

│ ├── out

│ └── src

├── settings.gradle

└── tool

├── compileThrift.sh

└── shutdown.sh

我们来逐一进行讲解:

主项目级别Gradle配置文件: build.gradle和settings.gradle,定义了子项目,以及子项目共用的依赖、仓库等,我们会在稍后展开讲解。

gradle最小化构建工具: gradle构建工具初始化后,会在项目中生成gradle、gradlew、gradlew.bat,这些是最小化的构建工具,方便项目移植后的构建。

lmsia-abc-common: 如前文所属,我们的项目采用Thrift RPC。我们将Thrift的dsl文件、自动生成的Java(客户端桩)代码放置在common子项目中。这样,如果有其他微服务需要依赖相关数据结构,只需要依赖'lmsia-abc-common'即可。

lmsia-abc-client: 在引用common包后,可以自行构造Thrift客户端,从而完成RPC调用。然而,这一过程较为繁琐。试想有一个提供用户信息的微服务,因为较为基础,有20个微服务依赖它,那么就需要20次书写重复的代码。"重复代码乃万恶之源",为了解决Thrift客户端重复生成的问题,我们创建了client子项目,负责生成Thrift客户端,并添加自动配置(如果没有接触过Spring Boot,可能会不理解自动配置,没有关系,我们很快就会作出解释)。

lmsia-abc-server: 微服务的核心,即提供"服务"。我们将Thrift、RPC服务的逻辑代码封装在server子项目中。

lmsia-abc-job: 在微服务业务的升级、演进过程中,可能会需要对数据作出修正。这些代码可能只需要执行一次,因此不需要放入server子项目提供服务,我们将他们放入job子项目中。

tool: 一些提升微服务开发的效率工具,我们将在开发效率脚本一节中进行介绍。

由于篇幅所限,我们不会对Thrift进行入门介绍,如果你无法理解上述Thrift的DSL、自动代码生成等内容,可以参考官方教程。

我们来看一下根路径下的build.gradle

buildscript {

ext {

springBootVersion = '1.5.6.RELEASE'

}

repositories {

maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }

maven { url 'https://jitpack.io' }

}

dependencies {

classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")

}

}

subprojects {

apply plugin: 'java'

apply plugin: 'idea'

apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8

targetCompatibility = 1.8

group = 'com.coder4.lmsia'

version = '0.0.1'

repositories {

maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }

maven { url 'https://jitpack.io' }

mavenLocal()

}

}

repositories {

maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }

maven { url 'https://jitpack.io' }

}

我们来顺序解释上述文件:

buildscript: 定义了gradle自身所需要使用的资源,包含Spring Boot插件和maven的仓库地址。

subprojects: 定义了子项目(common, client, job, server)所需要使用的共用部分,Java、IDEA、Spring Boot插件、Javac版本、项目的group, version,以及仓库,这里的仓库是给子项目使用的,看似与buildscript的定义重复,但确实是必要的。

repositories: 定义主项需要的仓库地址,与上面类似,这里也是必须的,并不是冗余定义。

在settings.gradle中,定义了各个子项目的路径:

include 'lmsia-abc-common'

include 'lmsia-abc-client'

include 'lmsia-abc-job'

include 'lmsia-abc-server'

下面,我们来看一下子项目中的gradle文件,以'lmsia-abc-server/build.gradle'为例:

dependencies {

compile project(':lmsia-abc-common')

compile 'org.springframework.boot:spring-boot-starter-web'

compile 'com.github.liheyuan:lmsia-thrift-server:0.0.1'

compile 'com.github.liheyuan:lmsia-commons-http:0.0.1'

testCompile 'org.springframework.boot:spring-boot-starter-test'

}

由于我们将子项目共用的部分抽取到根目录的build.gradle中,所以上述子项目的gradle文件就十分简单了。

上述文件表明:server子项目依赖common子项目,同时依赖了'spring-boot-starter-web'、'lmsia-thrift-server'、'lmsia-commons-http'两个项目,测试依赖'spring-boot-starter-test'。细心的读者可能已经发现,'spring-boot-starter-web'和'spring-boot-starter-test'并没有定义版本号。这就是我们在根文件中定义的'Spring Boot插件'所完成的工作之一。

common子项目的代码结构

我们来看一下common子项目的结构:

├── build.gradle

└── src

└── main

├── java

│ └── com

│ └── coder4

│ └── lmsia

│ └── abc

│ ├── constant

│ │ └── LmsiaAbcConstant.java

│ └── thrift

│ └── LmsiaAbcThrift.java

└── thrift

└── lmsiaAbc.thrift

我们解释一下目录结构:

除了build.gradle外,代码被放置在src/main/java下,这是gradle推荐的默认路径。

thrift的DSL文件放置在'src/main/thrift'下

编译好的Thrift桩文件在'src/main/java`下

client子项目的代码结构

接下来,我们看一下client子项目的目录结构:

├── build.gradle

└── src

├── main

│ ├── java

│ │ └── com

│ │ └── coder4

│ │ └── lmsia

│ │ └── abc

│ │ └── client

│ │ ├── configuration

│ │ │ └── LmsiaAbcClientConfiguration.java

│ │ ├── LmsiaAbcEasyClientBuilder.java

│ │ └── LmsiaK8ServiceClientBuilder.java

│ └── resources

│ └── META-INF

│ └── spring.factories

└── test

└── java

└── com

└── coder4

└── lmsia

└── abc

└── client

├── LmsiaAbcEasyClientTest.java

└── LmsiaAbcK8ServiceClientTest.java

自动配置: 代码包的LmsiaAbcClientConfiguration和资源包的spring.factories,一起实现了自动配置。当别的项目通过maven引用这个client包时,配置会自动生效,生成可注入的客户端实例。

Builder: 方便手动或自动配置的调用,用于生成客户端实例。

测试: 'src/test'里面内置了两个测试。

server子项目的代码结构

看一下server子项目的目录结构:

.

├── build.gradle

└── src

├── main

│ ├── java

│ │ └── com

│ │ └── coder4

│ │ └── lmsia

│ │ └── abc

│ │ └── server

│ │ ├── configuration

│ │ │ └── ThriftProcessorConfiguration.java

│ │ ├── LmsiaAbcApplication.java

│ │ ├── rest

│ │ │ ├── controller

│ │ │ │ └── AbcController.java

│ │ │ ├── logic

│ │ │ │ ├── impl

│ │ │ │ │ └── AbcLogicImpl.java

│ │ │ │ └── intf

│ │ │ │ └── AbcLogic.java

│ │ │ └── wrapper

│ │ ├── service

│ │ │ ├── impl

│ │ │ │ └── HelloServiceImpl.java

│ │ │ └── intf

│ │ │ └── HelloService.java

│ │ └── thrift

│ │ └── ThriftServerHandler.java

│ └── resources

│ ├── application.yaml

│ └── logback-spring.xml

└── test

└── java

└── com.coder4.lmsia.abc

└── server

└── LmsiaAbcTest.java

解释一下文件:

RPC服务相关:自动配置: 'server.configuration.ThriftProcessorConfiguration'是RPC服务的自动配置,用于自动启动RPC服务,我们后面会对此详细讲解。

RPC入口函数: server.thrift.thrift.ThriftServerHandler定义了RPC的入口函数

REST服务:REST服务放在server.rest包下,并进行了进一步分层Spring MVC: Controller在rest.controller下

REST逻辑: 为了防止Controller过于臃肿,我们将Controller的逻辑都放在了rest.logic中。该包又分为intf和impl,前者是Interface(接口),后者是Implementation(实现)。

Wrapper: 如果Logic中需要对REST接口进行包装,可以放在wrapper里

业务逻辑: 我们将所有业务逻辑抽象出来,放到server.service下,与Logic类似,也分为intf和impl

配置:Spring Boot配置:resources/application.yaml是Spring Boot的配置文件,如服务名、数据库配置等

日志配置:我们使用了默认的logback作为日志系统,配置在resources/logback-spring.xml中

测试用例:test下,与client和common类似,不再赘述。

上述分层看起来有些复杂,但会让各个层次的职责划分的更为清楚,如果你的项目中有更好的方案,也可以采用已有分层结构。

job子项目的代码结构

最后,我们看一下job子项目的目录结构:

├── build.gradle

└── src

└── main

├── java

│ └── com

│ └── coder4

│ └── lmsia

│ └── abc

│ └── job

│ ├── LmsiaAbcJob.java

│ └── LmsiaAbcJobStarter.java

└── resources

├── application.yaml

└── logback-spring.xml

简单解释下:

命令行入口: 本节开篇部分已经提到,job是可执行程序,LmsiaAbcJobStarter即是命令行的入口。

具体job: 这里只有一个LmsiaAbcJob,会通过参数与入口关联,后续会详细讲解。

至此,我们已经对lmsia这个示例项目的Gradle、子项目划分、子项目结构做了较为详尽的讲解。

需要说明的是:由于篇幅先后关系的问题,server子项目我们并未包含数据库、事件处理的相关文件和目录结构,我们会在后续章节视进度逐渐添加。

Copyright © 2019 coder4.

All rights reserved.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值