Building Java & JVM projects
- Introduction
- Declaring your source files via source sets
- Managing your dependencies
- Compiling your code
- Managing resources
- Running tests
- Packaging and publishing
- Generating API documentation
- Cleaning the build
- Building JVM components
- Building Java libraries
- Building Java applications
- Building Java web applications
- Building Java EE applications
- Building Java Platforms
- Building other JVM language projects
Gradle使用基于配置的约定方法来构建基于JVM的项目,该方法借鉴了Apache Maven的几种约定. 特别是,它对源文件和资源使用相同的默认目录结构,并且可与Maven兼容的存储库一起使用.
We will look at Java projects in detail in this chapter, but most of the topics apply to other supported JVM languages as well, such as Kotlin, Groovy and Scala. If you don’t have much experience with building JVM-based projects with Gradle, take a look at the Java tutorials for step-by-step instructions on how to build various types of basic Java projects.
✨
|
本节中的示例使用Java库插件. 但是,所有JVM插件都共享所描述的功能. 不同插件的详细信息可在其专用文档中找到. |
Introduction
Java项目的最简单构建脚本应用Java库插件,并可以选择设置项目版本和Java兼容版本:
plugins {
id 'java-library'
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
version = '1.2.1'
plugins {
`java-library`
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
version = "1.2.1"
通过应用Java库插件,您可以获得许多功能:
-
一个
compileJava
任务,用于编译src / main / java下的所有Java源文件 -
src / test / java下源文件的
compileTestJava
任务 -
从src / test / java运行测试的
test
任务 -
一个
jar
任务,它将src / main / resources中的main
编译类和资源打包到单个名为<project>-<version> .jar的 JAR中. -
一个为
main
类生成Javadoc的javadoc
任务
这还不足以构建任何重要的Java项目-至少,您可能会有一些文件依赖性. 但它意味着你的构建脚本只需要特定于项目的信息.
✨
|
尽管示例中的属性是可选的,但我们建议您在项目中指定它们. 兼容性选项可以缓解使用不同Java编译器版本构建的项目的问题,并且版本字符串对于跟踪项目的进度很重要. 默认情况下,项目版本也用于归档名称中. |
Java库插件还将上述任务集成到标准的基础插件生命周期任务中 :
-
jar
附assemble
[ 1 ] -
test
附带check
本章的其余部分介绍了根据需要自定义构建的不同方法. 稍后,您还将看到如何调整库,应用程序,Web应用程序和企业应用程序的构建.
Declaring your source files via source sets
Gradle对Java的支持是第一个引入用于构建基于源代码的项目的新概念的方法: 源代码集 . 主要思想是源文件和资源通常按类型进行逻辑分组,例如应用程序代码,单元测试和集成测试. 每个逻辑组通常都有其自己的文件依赖项集,类路径等. 重要的是,构成源集的文件不必位于同一目录中 !
源集是一个强大的概念,将编译的几个方面联系在一起:
-
源文件及其位置
-
编译类路径,包括任何必需的依赖项(通过Gradle 配置 )
-
where the compiled class files are placed
您可以在此图中看到它们之间的相互关系:

阴影框代表源集本身的属性. 最重要的是,Java库插件会为您或插件定义的每个源集(称为compile SourceSet Java
)以及几个依赖项配置自动创建一个编译任务.
✨
|
main 来源集 大多数语言插件(包括Java)会自动创建一个名为 |
Java项目通常包括源文件以外的资源,例如属性文件,这些资源可能需要处理(例如,通过替换文件中的标记)并打包在最终JAR中. Java库插件通过自动为每个定义的源集(称为process SourceSet Resources
(或main
源集的processResources
))创建专用任务来处理此问题. 下图显示了源集如何适合此任务:

和以前一样,阴影框表示源集的属性,在这种情况下,它包括资源文件的位置以及将它们复制到的位置.
除了main
源集之外,Java库插件还定义了一个代表项目测试的test
源集. 此源集由运行测试的test
任务使用. 您可以在Java测试一章中了解有关此任务和相关主题的更多信息.
项目通常使用此源集进行单元测试,但如果需要,也可以将其用于集成,验收和其他类型的测试. 另一种方法是为其他每种测试类型定义一个新的源集 ,通常是出于以下两个或多个原因:
-
您想要使测试彼此分开以保持美观和可管理性
-
不同的测试类型需要不同的编译或运行时类路径或设置上的其他差异
您将了解有关源集及其提供的功能的更多信息:
Managing your dependencies
绝大多数Java项目都依赖于库,因此管理项目的依赖关系是构建Java项目的重要组成部分. 依赖管理是一个大话题,因此我们将在这里重点介绍Java项目的基础知识. 如果您想深入研究细节,请查看依赖管理的介绍 .
为Java项目指定依赖项仅需要三点信息:
-
您需要哪个依赖项,例如名称和版本
-
它需要什么,例如编译或运行
-
在哪里寻找
前两个在dependencies {}
块中指定,第三个在repositories {}
块中指定. 例如,要告诉Gradle您的项目需要3.6.7版的Hibernate Core来编译和运行生产代码,并且您想从Maven Central存储库下载该库,可以使用以下片段:
repositories {
mavenCentral()
}
dependencies {
implementation 'org.hibernate:hibernate-core:3.6.7.Final'
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.hibernate:hibernate-core:3.6.7.Final")
}
三个元素的Gradle术语如下:
-
存储库 (例如:
mavenCentral()
)—在哪里查找声明为依赖项的模块 -
配置 (例如:
implementation
)-命名的依赖项集合,针对特定目标分组在一起,例如编译或运行模块-一种更灵活的Maven范围形式 -
模块坐标 (例如:
org.hibernate:hibernate-core-3.6.7.Final
)—依赖项的ID,通常为' <group> : <module> : <version> '(或' <groupId> : Mart术语中的<artifactId> : <version> ')
您可以在此处找到更全面的依赖项管理术语表.
就配置而言,主要感兴趣的是:
-
compileOnly
— for dependencies that are necessary to compile your production code but shouldn’t be part of the runtime classpath -
implementation
(取代compile
)—用于编译和运行时 -
runtimeOnly
(取代runtime
)—仅在运行时使用,而不用于编译 -
testCompileOnly
—与compileOnly
相同,只是用于测试 -
testImplementation
—测试implementation
等效项 -
testRuntimeOnly
—测试等效于runtimeOnly
您可以在插件参考一章中了解有关它们的更多信息以及它们之间的关系.
请注意, Java库插件为编译模块和依赖该模块的任何模块所需的依赖项创建了一个附加配置api
.
✨
|
为什么没有
compile 配置? Java库插件在历史上一直使用 |
我们仅在此处进行了介绍,因此,一旦您熟悉使用Gradle构建Java项目的基础知识,我们建议您阅读专用的依赖管理章节. 需要进一步阅读的一些常见方案包括:
-
使用本地文件系统目录中的依赖项
-
通过组合构建测试对第三方依赖关系的修复(这是发布到Maven Local和从Maven Local消费的更好的替代方法)
您会发现Gradle具有丰富的API用于处理依赖关系-一种需要花费时间来掌握的API,但对于常见的情况却很容易使用.
Compiling your code
如果遵循以下约定,则可以同时轻松地编译生产代码和测试代码:
-
将生产源代码放在src / main / java目录下
-
将测试源代码放在src / test / java下
-
在
compileOnly
或implementation
配置中声明您的生产编译依赖项(请参阅上一节) -
在
testCompileOnly
或testImplementation
配置中声明您的测试编译依赖testImplementation
-
运行
compileJava
生产代码和任务compileTestJava
为测试
其他JVM语言插件,例如Groovy的插件,遵循相同的约定模式. 我们建议您尽可能遵循这些约定,但不必这样做. 有几种自定义选项,您将在下面看到.
Customizing file and directory locations
假设您有一个旧项目,该项目使用src目录存储生产代码并测试测试代码. 传统的目录结构不起作用,因此您需要告诉Gradle在哪里可以找到源文件. 您可以通过源集配置来实现.
每个源集定义其源代码所在的位置,以及类文件的资源和输出目录. 您可以使用以下语法覆盖约定值:
sourceSets {
main {
java {
srcDirs = ['src']
}
}
test {
java {
srcDirs = ['test']
}
}
}
sourceSets {
main {
java {
setSrcDirs(listOf("src"))
}
}
test {
java {
setSrcDirs(listOf("test"))
}
}
}
现在Gradle将只在src中直接搜索并测试相应的源代码. 如果您不想覆盖约定,而只想添加一个额外的源目录,该目录可能包含一些您想分开的第三方源代码,该怎么办? 语法类似:
sourceSets {
main {
java {
srcDir 'thirdParty/src/main/java'
}
}
}
sourceSets {
main {
java {
srcDir("thirdParty/src/main/java")
}
}
}
至关重要的是,我们在这里使用方法 srcDir()
追加目录路径,而设置srcDirs
属性将替换所有现有值. 这是Gradle中的常见约定:设置属性将替换值,而相应的方法将附加值.
您可以在DSL参考中的SourceSet和SourceDirectorySet上查看源集上可用的所有属性和方法. 请注意, srcDirs
和srcDir()
都在SourceDirectorySet
.
Changing compiler options
大多数编译器选项可通过相应的任务访问,例如compileJava
和compileTestJava
. 这些任务的类型为JavaCompile ,因此,请阅读任务参考以获取最新,最全面的选项列表.
例如,如果要为编译器使用单独的JVM进程并防止编译失败使构建失败,则可以使用以下配置:
compileJava {
options.incremental = true
options.fork = true
options.failOnError = false
}
tasks.compileJava {
options.isIncremental = true
options.isFork = true
options.isFailOnError = false
}
这也是您可以更改编译器的详细程度,禁用字节码中的调试输出以及配置编译器可以在何处找到注释处理器的方式.
在项目级别定义了Java编译器的两个常用选项:
sourceCompatibility
-
定义应将源文件视为Java的语言版本.
targetCompatibility
-
定义您的代码应在其上运行的最低JVM版本,即,它确定编译器生成的字节码的版本.
如果出于任何原因需要或想要多个编译任务,则可以创建一个新的源集 ,也可以简单地定义一个JavaCompile类型的新任务. 接下来,我们来看设置新的源集.
Compiling and testing Java 6/7
Gradle只能在Java版本8或更高版本上运行.
Gradle仍然支持Java 6和Java 7的编译,测试,生成Javadoc并执行应用程序.不支持Java 5.
要使用Java 6或Java 7,需要配置以下任务:
-
JavaCompile
任务派生并使用正确的Java主页 -
Javadoc
任务以使用正确的javadoc
可执行文件 -
Test
JavaExec
任务以使用正确的java
可执行文件.
以下示例显示了如何调整build.gradle
. 为了能够独立于构建机器,应在每台开发人员机器的用户主目录中的GRADLE_USER_HOME/gradle.properties
[ 2 ]中配置旧Java主目录和目标版本的位置,如示例所示.
Example: Configure Java 7 build
# in $HOME/.gradle/gradle.properties
javaHome=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
targetJavaVersion=1.7
assert hasProperty('javaHome'): "Set the property 'javaHome' in your your gradle.properties pointing to a Java 6 or 7 installation"
assert hasProperty('targetJavaVersion'): "Set the property 'targetJavaVersion' in your your gradle.properties to '1.6' or '1.7'"
java {
sourceCompatibility = JavaVersion.toVersion(targetJavaVersion)
}
def javaExecutablesPath = new File(javaHome, 'bin')
def javaExecutables = [:].withDefault { execName ->
def executable = new File(javaExecutablesPath, execName)
assert executable.exists(): "There is no ${execName} executable in ${javaExecutablesPath}"
executable
}
tasks.withType(AbstractCompile) {
options.with {
fork = true
forkOptions.javaHome = file(javaHome)
}
}
tasks.withType(Javadoc) {
executable = javaExecutables.javadoc
}
tasks.withType(Test) {
executable = javaExecutables.java
}
tasks.withType(JavaExec) {
executable = javaExecutables.java
}
require(hasProperty("javaHome")) { "Set the property 'javaHome' in your your gradle.properties pointing to a Java 6 or 7 installation" }
require(hasProperty("targetJavaVersion")) { "Set the property 'targetJavaVersion' in your your gradle.properties to '1.6' or '1.7'" }
val javaHome: String by project
val targetJavaVersion: String by project
java {
sourceCompatibility = JavaVersion.toVersion(targetJavaVersion)
}
val javaExecutablesPath = File(javaHome, "bin")
fun javaExecutable(execName: String): String {
val executable = File(javaExecutablesPath, execName)
require(executable.exists()) { "There is no ${execName} executable in ${javaExecutablesPath}" }
return executable.toString()
}
tasks.withType<JavaCompile>().configureEach {
options.apply {
isFork = true
forkOptions.javaHome = file(javaHome)
}
}
tasks.withType<Javadoc>().configureEach {
executable = javaExecutable("javadoc")
}
tasks.withType<Test>().configureEach {
executable = javaExecutable("java")
}
tasks.withType<JavaExec>().configureEach {
executable = javaExecutable("java")
}
Compiling independent sources separately
大多数项目至少有两个独立的源集:生产代码和测试代码. Gradle已经将此场景作为其Java约定的一部分,但是如果您有其他来源的话该怎么办? 最常见的情况之一是当您进行某种形式或其他形式的单独集成测试时. 在这种情况下,自定义源集可能正是您所需要的.
您可以在Java测试一章中看到设置集成测试的完整示例. 您可以设置以相同方式担当不同角色的其他源集. 问题就变成了:什么时候应该定义自定义源集?
要回答该问题,请考虑以下来源:
-
需要使用唯一的类路径进行编译
-
生成与
main
和test
类的处理方式不同的类 -
构成项目的自然组成部分
如果您对3和其他任何一个的回答都是肯定的,那么自定义源集可能是正确的方法. 例如,集成测试通常是项目的一部分,因为它们测试main
的代码. 此外,它们通常具有独立于test
源集的独立性,或者需要与自定义Test
任务一起运行.
其他常见方案不太明确,可能有更好的解决方案. 例如:
-
Separate API and implementation JARs — it may make sense to have these as separate projects, particularly if you already have a multi-project build
-
生成的源-如果生成的源应使用生产代码进行编译,则将其路径添加到
main
源集中,并确保compileJava
任务依赖于生成源的任务
如果不确定是否要创建自定义源集,请继续进行操作. 它应该很简单,如果不是,则可能不是适合该工作的工具.
Managing resources
Many Java projects make use of resources beyond source files, such as images, configuration files and localization data. Sometimes these files simply need to be packaged unchanged and sometimes they need to be processed as template files or in some other way. Either way, the Java Library Plugin adds a specific Copy task for each source set that handles the processing of its associated resources.
任务的名称遵循process SourceSet Resources
的约定(或main
源集的processResources
,它将自动将src / [sourceSet] / resources中的所有文件复制到将包含在生产JAR中的目录中. 该目标目录也将包含在测试的运行时类路径中.
由于processResources
是" Copy
任务的实例,因此您可以执行" 使用文件"一章中描述的任何处理.
Java properties files and reproducible builds
您可以通过WriteProperties任务轻松创建Java属性文件,该任务解决了Properties.store()
一个众所周知的问题,该问题可能会减少增量构建的用处.
即使使用相同的属性和值,用于编写属性文件的标准Java API也会每次生成一个唯一的文件,因为注释中包括了时间戳. 如果未更改任何属性,则Gradle的WriteProperties
任务逐字节生成完全相同的输出. 这是通过对属性文件的生成方式进行一些调整来实现的:
-
没有时间戳注释添加到输出
-
行分隔符与系统无关,但是可以显式配置(默认为
'\n'
) -
属性按字母顺序排序
有时可能需要在不同的计算机上以字节为单位重新创建归档. 您要确保从源代码构建工件,无论在何时何地构建,都逐字节产生相同的结果. 这对于诸如reproducible-builds.org之类的项目是必需的.
这些调整不仅可以导致更好的增量构建集成,而且还有助于可复制的构建 . 本质上,可重现的构建可确保您无论在何时何地在什么系统上运行,都可以从构建执行中看到相同的结果,包括测试结果和生产二进制文件.
Running tests
除了在src / test / java中提供单元测试的自动编译功能之外,Java库插件还对运行使用JUnit 3、4和5的测试( Gradle 4.6中提供了对 JUnit 5的支持)和TestNG的本地支持. 你得到:
-
使用
test
源集的Test类型的自动test
任务 -
HTML测试报告,其中包含运行的所有
Test
任务的结果 -
轻松过滤要运行的测试
-
精细控制测试的运行方式
-
有机会创建自己的测试执行和测试报告任务
您不会为声明的每个源集获得一个Test
任务,因为不是每个源集都代表测试! 这就是为什么您通常需要为集成和验收测试之类的东西创建自己的Test
任务 ,如果它们不能包含在test
源集中.
由于涉及测试的内容很多,因此该主题有其自己的章节 ,我们在其中进行介绍:
-
测试如何运行
-
如何通过过滤运行测试的子集
-
Gradle如何发现测试
-
如何配置测试报告并添加自己的报告任务
-
如何利用特定的JUnit和TestNG功能
您还可以在DSL参考中的Test上了解有关配置测试的更多信息.
Packaging and publishing
如何打包和潜在地发布Java项目取决于它是什么类型的项目. 库,应用程序,Web应用程序和企业应用程序都有不同的要求. 在本节中,我们将重点介绍Java库插件提供的基础知识.
默认情况下,Java库插件提供了jar
任务,该任务将所有已编译的生产类和资源打包到一个JAR中. 该JAR也是由assemble
任务自动构建的. 此外,如果需要,可以将插件配置为提供javadocJar
和sourcesJar
任务,以打包Javadoc和源代码. 如果使用发布插件,这些任务将在发布期间自动运行或可以直接调用.
java {
withJavadocJar()
withSourcesJar()
}
java {
withJavadocJar()
withSourcesJar()
}
如果要创建"超级"(又称"胖")JAR,则可以使用如下任务定义:
plugins {
id 'java'
}
version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
implementation 'commons-io:commons-io:2.6'
}
task uberJar(type: Jar) {
archiveClassifier = 'uber'
from sourceSets.main.output
dependsOn configurations.runtimeClasspath
from {
configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
}
}
plugins {
java
}
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
implementation("commons-io:commons-io:2.6")
}
tasks.register<Jar>("uberJar") {
archiveClassifier.set("uber")
from(sourceSets.main.get().output)
dependsOn(configurations.runtimeClasspath)
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
})
}
See Jar for more details on the configuration options available to you.
And note that you need to use archiveClassifier
rather than archiveAppendix
here for correct publication of the JAR.
您可以使用发布插件之一来发布由Java项目创建的JAR:
Modifying the JAR manifest
Jar
, War
和Ear
任务的每个实例都有一个manifest
属性,该属性允许您自定义进入相应归档文件的MANIFEST.MF文件. 下面的示例演示如何在JAR清单中设置属性:
jar {
manifest {
attributes("Implementation-Title": "Gradle",
"Implementation-Version": archiveVersion)
}
}
tasks.jar {
manifest {
attributes(
"Implementation-Title" to "Gradle",
"Implementation-Version" to archiveVersion
)
}
}
请参阅清单以获取其提供的配置选项.
您还可以创建Manifest
独立实例. 这样做的原因之一是在JAR之间共享清单信息. 下面的示例演示如何在JAR之间共享通用属性:
ext.sharedManifest = manifest {
attributes("Implementation-Title": "Gradle",
"Implementation-Version": version)
}
task fooJar(type: Jar) {
manifest = project.manifest {
from sharedManifest
}
}
val sharedManifest = the<JavaPluginConvention>().manifest {
attributes (
"Implementation-Title" to "Gradle",
"Implementation-Version" to version
)
}
tasks.register<Jar>("fooJar") {
manifest = project.the<JavaPluginConvention>().manifest {
from(sharedManifest)
}
}
您可以使用的另一种选择是将清单合并到单个Manifest
对象中. 这些源清单可以采用文本的形式,也可以采用另一个Manifest
对象的形式. 在以下示例中,源清单是所有文本文件,但sharedManifest
除外,后者是上一示例中的Manifest
对象:
task barJar(type: Jar) {
manifest {
attributes key1: 'value1'
from sharedManifest, 'src/config/basemanifest.txt'
from(['src/config/javabasemanifest.txt', 'src/config/libbasemanifest.txt']) {
eachEntry { details ->
if (details.baseValue != details.mergeValue) {
details.value = baseValue
}
if (details.key == 'foo') {
details.exclude()
}
}
}
}
}
tasks.register<Jar>("barJar") {
manifest {
attributes("key1" to "value1")
from(sharedManifest, "src/config/basemanifest.txt")
from(listOf("src/config/javabasemanifest.txt", "src/config/libbasemanifest.txt")) {
eachEntry(Action<ManifestMergeDetails> {
if (baseValue != mergeValue) {
value = baseValue
}
if (key == "foo") {
exclude()
}
})
}
}
}
清单按照在from
语句中声明的顺序合并. 如果基本清单和合并清单都定义了相同键的值,则默认情况下合并清单将获胜. 您可以通过添加eachEntry
动作来完全自定义合并行为,在其中您可以访问结果清单的每个条目的ManifestMergeDetails实例. 请注意,在生成JAR时或在调用Manifest.writeTo()
或Manifest.getEffectiveManifest()
时,合并都是延迟进行的.
说到writeTo()
,您可以使用它轻松地随时将清单写入磁盘,如下所示:
jar.manifest.writeTo("$buildDir/mymanifest.mf")
tasks.named<Jar>("jar") { manifest.writeTo("$buildDir/mymanifest.mf") }
Generating API documentation
Java库插件提供javadoc
类型的任务的Javadoc ,将生成标准的Javadoc文档所有的生产代码,即无论来源是main
来源集. 该任务支持Javadoc参考文档中描述的核心Javadoc和标准doclet选项. 有关这些选项的完整列表,请参见CoreJavadocOptions和StandardJavadocDocletOptions .
作为您可以做的事的一个例子,想象一下您想在Javadoc注释中使用Asciidoc语法. 为此,您需要将Asciidoclet添加到Javadoc的doclet路径. 这是一个执行此操作的示例:
configurations {
asciidoclet
}
dependencies {
asciidoclet 'org.asciidoctor:asciidoclet:1.+'
}
task configureJavadoc {
doLast {
javadoc {
options.doclet = 'org.asciidoctor.Asciidoclet'
options.docletpath = configurations.asciidoclet.files.toList()
}
}
}
javadoc {
dependsOn configureJavadoc
}
val asciidoclet by configurations.creating
dependencies {
asciidoclet("org.asciidoctor:asciidoclet:1.+")
}
tasks.register("configureJavadoc") {
doLast {
tasks.javadoc {
options.doclet = "org.asciidoctor.Asciidoclet"
options.docletpath = asciidoclet.files.toList()
}
}
}
tasks.javadoc {
dependsOn("configureJavadoc")
}
您不必为此创建配置,但这是一种处理独特目的所需依赖项的绝妙方法.
您可能还想创建自己的Javadoc任务,例如为测试生成API文档:
task testJavadoc(type: Javadoc) {
source = sourceSets.test.allJava
}
tasks.register<Javadoc>("testJavadoc") {
source = sourceSets.test.get().allJava
}
这些只是您可能会遇到的两个不重要但常见的自定义.
Building JVM components
所有特定的JVM插件都构建在Java插件之上. 上面的示例仅说明了此基本插件提供的概念,并与所有JVM插件共享.
继续阅读以了解哪些插件适合哪种项目类型,因为建议选择特定的插件而不是直接应用Java插件.
Building Java libraries
Building Java web applications
Java Web应用程序可以根据您使用的技术以多种方式打包和部署. 例如,您可以将Spring Boot与胖JAR或Netty上运行的基于Reactive的系统一起使用. 无论您使用什么技术,Gradle及其庞大的插件社区都可以满足您的需求. 但是,Core Gradle仅直接支持部署为WAR文件的传统基于Servlet的Web应用程序.
-
将静态资源从src / main / webapp复制到WAR的根目录中
-
将编译后的生产类复制到WAR的WEB-INF / classes子目录中
-
将库依赖项复制到WAR的WEB-INF / lib子目录中
这是由war
任务完成的, war
任务有效地替换了jar
任务(尽管该任务仍然存在),并附加到了assemble
生命周期任务. 有关更多详细信息和配置选项,请参见插件的章节.
没有直接从内部版本运行Web应用程序的核心支持,但是我们建议您尝试使用Gretty社区插件,该插件提供了嵌入式Servlet容器.
Building Java EE applications
多年来,Java企业系统已经发生了很大的变化,但是如果您仍要部署到JEE应用服务器,则可以使用Ear Plugin . 这增加了约定和构建EAR文件的任务. 插件的章节有更多详细信息.
Building Java Platforms
Java平台代表了一组依赖项声明和约束,这些声明和约束形成了要在消费项目上应用的内聚单元. 该平台没有来源,也没有自己的工件. 它在Maven世界中映射到BOM .
该支持来自Java Platform插件 ,该插件设置了不同的配置和发布组件.
✨
|
该插件是例外,因为它不应用Java插件. |