Gradle构建多模块spring boot项目

一、创建项目

1、创建主项目

按创建springboot项目的创建方式创建就行,创建完的结构。然后删除src目录。

2、创建模块项目

创建模块项目New-》Module-》New Module(或Spring Initializr)。

依次创建service删除文件,然后创建工程等,创建后如下:

3、setting.gradle文件

创建完工程后,会自动在这个文件中添加下面的内容,表示将子模块引入

二、配置build.gradle文件

构建单体的多模块项目,demo-web作为启动项目,依赖service

说明文档:https://docs.gradle.org/current/userguide/gradle_directories.htmlGradle Directorieshttps://docs.gradle.org/current/userguide/gradle_directories.html

1、修改根目录的build.gradle

用于管理子模块。主要是hi设置下载仓库、依赖包、插件等信息。主要定义一些公共的内容。

打包相关的定义也可以统一在跟目录下的这个文件写,暂时定义到各模块自己的文件里。

bash 复制代码
buildscript {
	// 指定插件的仓库
	repositories {
		jcenter()
		mavenCentral()
		maven { url 'https://jitpack.io' } // 添加这一行
	}
	// 定义插件及其版本
//	dependencies {
//		classpath "org.springframework.boot:spring-boot-gradle-plugin:2.5.5"
//	}
}

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.2.7'
	id 'io.spring.dependency-management' version '1.1.5'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

subprojects {
	apply plugin: 'java'
	apply plugin: 'org.springframework.boot'
	apply plugin: 'io.spring.dependency-management'

	repositories {
		mavenCentral()
	}

//	dependencies {
//		implementation 'org.springframework.boot:spring-boot-starter'
//	}
	dependencies {
		implementation 'org.springframework.boot:spring-boot-starter-web'
		testImplementation 'org.springframework.boot:spring-boot-starter-test'
		testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
	}

	tasks.named('test') {
		useJUnitPlatform()
	}
}

2、修改模块项目的build.gradle

以demo-web为例。增加依赖的项目包,也可以增加其他的依赖

bash 复制代码
bootJar {
    archiveBaseName = 'demo-web'
    archiveVersion = '0.0.1-SNAPSHOT'
}

dependencies {
    implementation project(':service:demo-api')
    implementation project(':service:demo-service')
}

demo-service工程。定义只打jar。bootjar定位false

bash 复制代码
bootJar {
    enabled(false)
    archiveBaseName = 'demo-service'
    archiveVersion = '0.0.1-SNAPSHOT'
}

jar {
    enabled(true)
}

dependencies {
    implementation project(':service:demo-api')
}

三、启动打包测试

1、编写接口服务等

注意要增加@service注解

java 复制代码
public interface IDemoService {

    String test();
}
java 复制代码
@Service
public class DemoService implements IDemoService {
    @Override
    public String test() {
        return "demo service";
    }
}

2、编写controller

java 复制代码
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private IDemoService demoService;

    @GetMapping("test")
    public String test(){
        return demoService.test();
    }
}

3、编写启动类

注意加@SpringBootApplication注解。最好放在包的最外层

java 复制代码
@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

4、启动测试

可以用idea启动测试或打jar启动测试

5、打包验证

点击gradle的bootjar可以生成jar包

通过 jar tf .\demo-web-0.0.1-SNAPSHOT.jar 命令可以查看生成的jar文件

bash 复制代码
PS C:\study\demo\web\demo-web\build\libs> jar tf .\demo-web-0.0.1-SNAPSHOT.jar
META-INF/
META-INF/MANIFEST.MF
META-INF/services/
META-INF/services/java.nio.file.spi.FileSystemProvider
org/
org/springframework/
org/springframework/boot/
org/springframework/boot/loader/
org/springframework/boot/loader/jar/
org/springframework/boot/loader/jar/ManifestInfo.class
org/springframework/boot/loader/jar/MetaInfVersionsInfo.class
org/springframework/boot/loader/jar/NestedJarFile$JarEntriesEnumeration.class
org/springframework/boot/loader/jar/NestedJarFile$JarEntryInflaterInputStream.class
org/springframework/boot/loader/jar/NestedJarFile$JarEntryInputStream.class
org/springframework/boot/loader/jar/NestedJarFile$NestedJarEntry.class
org/springframework/boot/loader/jar/NestedJarFile$RawZipDataInputStream.class
org/springframework/boot/loader/jar/NestedJarFile$ZipContentEntriesSpliterator.class
org/springframework/boot/loader/jar/NestedJarFile.class
org/springframework/boot/loader/jar/NestedJarFileResources.class
org/springframework/boot/loader/jar/SecurityInfo.class
org/springframework/boot/loader/jar/ZipInflaterInputStream.class
org/springframework/boot/loader/jarmode/
org/springframework/boot/loader/jarmode/JarMode.class
org/springframework/boot/loader/launch/
org/springframework/boot/loader/launch/Archive$Entry.class
org/springframework/boot/loader/launch/Archive.class
org/springframework/boot/loader/launch/ClassPathIndexFile.class
org/springframework/boot/loader/launch/ExecutableArchiveLauncher.class
org/springframework/boot/loader/launch/ExplodedArchive$FileArchiveEntry.class
org/springframework/boot/loader/launch/ExplodedArchive.class
org/springframework/boot/loader/launch/JarFileArchive$JarArchiveEntry.class
org/springframework/boot/loader/launch/JarFileArchive.class
org/springframework/boot/loader/launch/JarLauncher.class
org/springframework/boot/loader/launch/JarModeRunner.class
org/springframework/boot/loader/launch/LaunchedClassLoader$DefinePackageCallType.class
org/springframework/boot/loader/launch/LaunchedClassLoader.class
org/springframework/boot/loader/launch/Launcher.class
org/springframework/boot/loader/launch/PropertiesLauncher$Instantiator$Using.class
org/springframework/boot/loader/launch/PropertiesLauncher$Instantiator.class
org/springframework/boot/loader/launch/PropertiesLauncher.class
org/springframework/boot/loader/launch/SystemPropertyUtils.class
org/springframework/boot/loader/launch/WarLauncher.class
org/springframework/boot/loader/log/
org/springframework/boot/loader/log/DebugLogger$DisabledDebugLogger.class
org/springframework/boot/loader/log/DebugLogger$SystemErrDebugLogger.class
org/springframework/boot/loader/log/DebugLogger.class
org/springframework/boot/loader/net/
org/springframework/boot/loader/net/protocol/
org/springframework/boot/loader/net/protocol/Handlers.class
org/springframework/boot/loader/net/protocol/jar/
org/springframework/boot/loader/net/protocol/jar/Canonicalizer.class
org/springframework/boot/loader/net/protocol/jar/Handler.class
org/springframework/boot/loader/net/protocol/jar/JarFileUrlKey.class
org/springframework/boot/loader/net/protocol/jar/JarUrl.class
org/springframework/boot/loader/net/protocol/jar/JarUrlClassLoader$OptimizedEnumeration.class
org/springframework/boot/loader/net/protocol/jar/JarUrlClassLoader.class
org/springframework/boot/loader/net/protocol/jar/JarUrlConnection$ConnectionInputStream.class
org/springframework/boot/loader/net/protocol/jar/JarUrlConnection$EmptyUrlStreamHandler.class
org/springframework/boot/loader/net/protocol/jar/JarUrlConnection.class
org/springframework/boot/loader/net/protocol/jar/LazyDelegatingInputStream.class
org/springframework/boot/loader/net/protocol/jar/Optimizations.class
org/springframework/boot/loader/net/protocol/jar/UrlJarEntry.class
org/springframework/boot/loader/net/protocol/jar/UrlJarFile.class
org/springframework/boot/loader/net/protocol/jar/UrlJarFileFactory.class
org/springframework/boot/loader/net/protocol/jar/UrlJarFiles$Cache.class
org/springframework/boot/loader/net/protocol/jar/UrlJarFiles.class
org/springframework/boot/loader/net/protocol/jar/UrlJarManifest$ManifestSupplier.class
org/springframework/boot/loader/net/protocol/jar/UrlJarManifest.class
org/springframework/boot/loader/net/protocol/jar/UrlNestedJarFile.class
org/springframework/boot/loader/net/protocol/nested/
org/springframework/boot/loader/net/protocol/nested/Handler.class
org/springframework/boot/loader/net/protocol/nested/NestedLocation.class
org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection$ConnectionInputStream.class
org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.class
org/springframework/boot/loader/net/protocol/nested/NestedUrlConnectionResources.class
org/springframework/boot/loader/net/util/
org/springframework/boot/loader/net/util/UrlDecoder.class
org/springframework/boot/loader/nio/
org/springframework/boot/loader/nio/file/
org/springframework/boot/loader/nio/file/NestedByteChannel$Resources.class
org/springframework/boot/loader/nio/file/NestedByteChannel.class
org/springframework/boot/loader/nio/file/NestedFileStore.class
org/springframework/boot/loader/nio/file/NestedFileSystem.class
org/springframework/boot/loader/nio/file/NestedFileSystemProvider.class
org/springframework/boot/loader/nio/file/NestedPath.class
org/springframework/boot/loader/nio/file/UriPathEncoder.class
org/springframework/boot/loader/ref/
org/springframework/boot/loader/ref/Cleaner.class
org/springframework/boot/loader/ref/DefaultCleaner.class
org/springframework/boot/loader/zip/
org/springframework/boot/loader/zip/ByteArrayDataBlock.class
org/springframework/boot/loader/zip/CloseableDataBlock.class
org/springframework/boot/loader/zip/DataBlock.class
org/springframework/boot/loader/zip/DataBlockInputStream.class
org/springframework/boot/loader/zip/FileDataBlock$FileAccess.class
org/springframework/boot/loader/zip/FileDataBlock$Tracker$1.class
org/springframework/boot/loader/zip/FileDataBlock$Tracker.class
org/springframework/boot/loader/zip/FileDataBlock.class
org/springframework/boot/loader/zip/NameOffsetLookups.class
org/springframework/boot/loader/zip/VirtualDataBlock.class
org/springframework/boot/loader/zip/VirtualZipDataBlock$DataPart.class
org/springframework/boot/loader/zip/VirtualZipDataBlock.class
org/springframework/boot/loader/zip/Zip64EndOfCentralDirectoryLocator.class
org/springframework/boot/loader/zip/Zip64EndOfCentralDirectoryRecord.class
org/springframework/boot/loader/zip/ZipCentralDirectoryFileHeaderRecord.class
org/springframework/boot/loader/zip/ZipContent$Entry.class
org/springframework/boot/loader/zip/ZipContent$Kind.class
org/springframework/boot/loader/zip/ZipContent$Loader.class
org/springframework/boot/loader/zip/ZipContent$Source.class
org/springframework/boot/loader/zip/ZipContent.class
org/springframework/boot/loader/zip/ZipDataDescriptorRecord.class
org/springframework/boot/loader/zip/ZipEndOfCentralDirectoryRecord$Located.class
org/springframework/boot/loader/zip/ZipEndOfCentralDirectoryRecord.class
org/springframework/boot/loader/zip/ZipLocalFileHeaderRecord.class
org/springframework/boot/loader/zip/ZipString$CompareType.class
org/springframework/boot/loader/zip/ZipString.class
BOOT-INF/
BOOT-INF/classes/
BOOT-INF/classes/com/
BOOT-INF/classes/com/example/
BOOT-INF/classes/com/example/controller/
BOOT-INF/classes/com/example/controller/DemoController.class
BOOT-INF/classes/com/example/DemoApplication.class
BOOT-INF/classes/application.properties
BOOT-INF/lib/
BOOT-INF/lib/demo-service-plain.jar
BOOT-INF/lib/demo-api-plain.jar
BOOT-INF/lib/micrometer-observation-1.12.7.jar
BOOT-INF/lib/micrometer-observation-1.12.7.jar
BOOT-INF/lib/logback-classic-1.4.14.jar
BOOT-INF/lib/log4j-to-slf4j-2.21.1.jar
BOOT-INF/lib/jul-to-slf4j-2.0.13.jar
BOOT-INF/lib/spring-jcl-6.1.10.jar
BOOT-INF/lib/micrometer-commons-1.12.7.jar
BOOT-INF/lib/logback-core-1.4.14.jar
BOOT-INF/lib/slf4j-api-2.0.13.jar
BOOT-INF/lib/log4j-api-2.21.1.jar
BOOT-INF/lib/spring-boot-jarmode-layertools-3.2.7.jar
BOOT-INF/classpath.idx
BOOT-INF/layers.idx

可以通过这个命令启动jar包,注意jdk版本要一致

bash 复制代码
 java -jar .\demo-web-0.0.1-SNAPSHOT.jar

四、遇到的问题

1、通过根目录下的bootJar打包失败

各项目下的bootJar不报错,只有根目录下的报错

报错1:

bash 复制代码
Execution failed for task ':bootJar'.
> Could not resolve all artifacts for configuration ':detachedConfiguration1'.
   > Cannot resolve external dependency org.springframework.boot:spring-boot-dependencies:3.2.7 because no repositories are defined.
     Required by:
         project :

Possible solution:
 - Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html

解决方案:

根目录下的build.gradle没有定义allproject,把subproject改成allproject后包另外一个错

报错2:

bash 复制代码
Execution failed for task ':bootJar'.
> Error while evaluating property 'mainClass' of task ':bootJar'.
   > Failed to calculate the value of task ':bootJar' property 'mainClass'.
      > Main class name has not been configured and it could not be resolved from classpath 

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
BUILD FAILED in 10s
2 actionable tasks: 1 executed, 1 up-to-date

解决方案:

增加mainClass的指定。两种方案都可以

bash 复制代码
springBoot {
    mainClass = 'com.example.DemoApplication'
}

bootJar {
    archiveBaseName = 'demo-web'
    archiveVersion = '0.0.1-SNAPSHOT'
    includeEmptyDirs = true
//    mainClass = 'com.example.DemoApplication'
}

dependencies {
    implementation project(':service:demo-api')
    implementation project(':service:demo-service')
}

报错3:

bash 复制代码
Execution failed for task ':service:bootJar'.
> Error while evaluating property 'mainClass' of task ':service:bootJar'.
   > Failed to calculate the value of task ':service:bootJar' property 'mainClass'.
      > Main class name has not been configured and it could not be resolved from classpath 

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.8/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD FAILED in 346ms
2 actionable tasks: 2 executed
相关推荐
向前看-2 小时前
验证码机制
前端·后端
xlsw_2 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭3 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫3 小时前
泛型(2)
java
超爱吃士力架3 小时前
邀请逻辑
java·linux·后端
南宫生3 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java
李小白664 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp4 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea