# 简介
这篇文章展示了如何基于 Gradle
逐步构建多模块的 Spring Boot
工程, 并编写了足够的单元测试以确保样板工程的稳定.
它实现了 app
模块使用 lib
模块提供的 Component
和 lib
模块依赖的其他第三方类库的能力.
相关代码已上传至 GitHub 仓库 https://github.com/DevDengChao/multi-module-spring-boot-gradle-demo (opens new window), 后续如有更新, 请以 GitHub 仓库为准.
文章中的 实现方式
章节包含较多的代码块, 建议使用电脑屏幕进行阅读以便获得更好的阅读体验.
# 为什么要基于多模块构建 Spring Boot 应用
多模块构建一方面解决了代码复用问题, 另一方面可以将不相关的功能单独拿出来进行开发和测试, 降低了代码之间的耦合性.
# 实现方式
# 1. 初始化空白工程
新建 build.gradle
文件, 并向其中添加:
group 'dev.dengchao'
version '0.0.0-SNAPSHOT'
# 2. 添加 lib
模块
新建 settings.gradle
文件, 并向其中添加:
include "lib"
向 build.gradle
文件中添加:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:2.5.3"
}
}
// ...
新建 lib/build.gradle
文件, 并向其中添加:
apply {
plugin 'java'
plugin 'org.springframework.boot'
plugin 'io.spring.dependency-management'
}
repositories {
mavenCentral()
}
test {
useJUnitPlatform()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
# 3. 添加并测试 LibComponent
新建 lib/src/main/java/dev/dengchao/LibComponent.java
文件, 并向其中添加:
@Component
public class LibComponent {
private static final Logger log = LoggerFactory.getLogger(LibComponent.class);
public String hello(@NonNull String name) {
String res = "Hello " + name;
log.info("{}", res);
return res;
}
}
新建 lib/src/test/java/dev/dengchao/LibTestApplication.java
文件, 并向其中添加:
@SpringBootApplication
class LibTestApplication {
}
新建 lib/src/test/java/dev/dengchao/LibComponentTest.java
文件, 并向其中添加:
@SpringBootTest
class LibComponentTest {
@Autowired
private LibComponent component;
@Test
void test() {
Assertions.assertEquals("Hello World", component.hello("World"));
}
}
通过命令 gradle :lib:test
确认单元测试通过.
# 4. 添加 app
模块
复制 lib/build.gradle
到 app/build.gradle
, 并向 settings.gradle
文件中添加:
// ...
include "app"
# 5. 添加 Application
和 AppService
并进行测试
新建 app/src/main/java/dev/dengchao/Application.java
文件, 并向其中添加:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
新建 app/src/main/java/dev/dengchao/AppService.java
文件, 并向其中添加:
@Service
public class AppService {
}
新建 app/src/test/java/dev/dengchao/AppServiceTest.java
文件, 并向其中添加:
@SpringBootTest
class AppServiceTest {
@Autowired
private AppService service;
@Test
void test() {
Assertions.assertNotNull(service);
}
}
通过命令 gradle :app:test
确认单元测试通过.
# 6. 向 app
模块添加 lib
模块作为依赖
向 app/build.gradle
文件的 dependencies
中添加:
//...
implementation project(":lib")
# 7. 测试 lib
模块中的类在 app
模块运行时可以被使用
修改 app/src/main/java/dev/dengchao/AppService.java
:
@Service
public class AppService {
private static final Logger log = LoggerFactory.getLogger(AppService.class);
@NonNull
private final LibComponent component;
public AppService(@NonNull LibComponent component) {
this.component = component;
log.info("Component injected {}", component);
}
@NonNull
public String hello(@NonNull String name) {
String res = component.hello(name);
log.info("{}", res);
return res;
}
}
修改 app/src/test/java/dev/dengchao/AppServiceTest.java
:
@Test
void test() {
Assertions.assertNotNull(service);
+ Assertions.assertEquals("Hello World", service.hello("World"));
}
通过命令 gradle :app:test
确认单元测试通过.
现在 app
模块能够复用 lib
模块提供的 Component
了.
# 8. 向 lib
模块添加第三方依赖, 并进行测试
向 lib/build.gradle
文件的 dependencies
中添加:
//...
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
新建 lib/src/main/dev/dengchao/LibConfiguration.java
文件, 并向其中添加:
@Configuration
public class LibConfiguration {
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient();
}
}
新建 lib/src/test/dev/dengchao/LibConfigurationTest.java
文件, 并向其中添加:
@SpringBootTest
class LibConfigurationTest {
@Autowired
private OkHttpClient client;
@Test
void test() {
Assertions.assertNotNull(client);
}
}
通过命令 gradle :lib:test
确认单元测试通过.
# 9. 向 lib
模块添加 java-library
插件并修改第三方库的依赖方式
向 lib/build.gradle
文件的 apply
中添加:
//...
plugin 'java-library'
修改 lib/build.gradle
文件的 dependencies
:
//...
- implementation 'com.squareup.okhttp3:okhttp:4.9.1'
+ api 'com.squareup.okhttp3:okhttp:4.9.1'
# 10. 测试 app
模块可以使用 lib
模块的第三方依赖
修改 app/src/main/java/dev/dengchao/AppService.java
:
@Service
public class AppService {
private static final Logger log = LoggerFactory.getLogger(AppService.class);
@NonNull
private final LibComponent component;
@NonNull
private final OkHttpClient okHttpClient;
public AppService(@NonNull LibComponent component, @NonNull OkHttpClient okHttpClient) {
this.component = component;
this.okHttpClient = okHttpClient;
log.info("Component injected {}", component);
log.info("3rd party library injected {}", okHttpClient);
}
@NonNull
public String hello(@NonNull String name) {
String res = component.hello(name);
log.info("{}", res);
return res;
}
@NonNull
public OkHttpClient getOkHttpClient() {
return okHttpClient;
}
}
修改 app/src/test/java/dev/dengchao/AppServiceTest.java
:
@Test
void test(){
Assertions.assertNotNull(service);
Assertions.assertEquals("Hello World",service.hello("World"));
+ Assertions.assertNotNull(service.getOkHttpClient());
}
通过命令 gradle :app:test
确认单元测试通过.
现在 app
模块能够使用 lib
模块提供的其他第三方依赖了.
# 参考
- Spring Guide: Creating a Multi Module Project (opens new window)
- Gradle Guide: The Java Library Plugin (opens new window)
- Gradle Sample: Building Java Libraries (opens new window)
# 推广
欢迎加入 Spring Cloud 交流群: 617143034 (opens new window)
欢迎大家点击下方的图片领取限量 阿里云优惠券 (opens new window), 新购续费更优惠 ! (opens new window)