84. Build

84.1 生成构建信息

Maven 和 Gradle 插件都允许生成包含坐标,项目名称和版本的构建信息。还可以将插件配置为通过配置添加其他属性。当存在此类文件时,Spring Boot 会自动配置BuildProperties bean。

要使用 Maven 生成构建信息,请为build-info目标添加执行:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>1.5.9.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Tip

查看Spring Boot Maven 插件文档以获取更多详细信息。

并使用 Gradle 进行相同操作:

springBoot  {
    buildInfo()
}

可以使用 DSL 添加其他属性:

springBoot  {
    buildInfo {
        additionalProperties = [
            'foo': 'bar'
        ]
    }
}

84.2 生成 git 信息

Maven 和 Gradle 都允许生成git.properties文件,该文件包含有关项目构建时git源代码存储库状态的信息。

对于 Maven 用户,spring-boot-starter-parent POM 包含一个预先配置的插件,用于生成git.properties文件。只需将以下声明添加到您的 POM 中:

<build>
    <plugins>
        <plugin>
            <groupId>pl.project13.maven</groupId>
            <artifactId>git-commit-id-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Gradle 用户可以使用gradle-git-properties插件获得相同的结果

plugins {
    id "com.gorylenko.gradle-git-properties" version "1.4.17"
}

Tip

git.properties中的提交时间应与格式yyyy-MM-dd'T'HH:mm:ssZ相匹配。这是上面列出的两个插件的默认格式。使用此格式,可以将时间序列化为Date,并将其序列化为 JSON 时的格式由 Jackson 的日期序列化配置设置控制。

84.3 自定义依赖项版本

如果您使用的 Maven 构建直接或间接继承自spring-boot-dependencies(例如spring-boot-starter-parent),但是要覆盖特定的第三方依赖关系,则可以添加适当的<properties>元素。浏览spring-boot-dependencies POM 以获取完整的属性列表。例如,要选择其他slf4j版本,应添加以下内容:

<properties>
    <slf4j.version>1.7.5<slf4j.version>
</properties>

Note

仅当您的 Maven 项目(直接或间接)继承spring-boot-dependencies时,此方法才有效。如果您在自己的dependencyManagement部分中使用<scope>import</scope>添加了spring-boot-dependencies,则必须自己重新定义工件,而不是覆盖属性。

Warning

每个 Spring Boot 版本都是针对一组特定的第三方依赖项进行设计和测试的。覆盖版本可能会导致兼容性问题。

要覆盖 Gradle 中的依赖版本,您可以指定一个版本,如下所示:

ext['slf4j.version'] = '1.7.5'

有关更多信息,请参阅Gradle 依赖性 Management 插件文档

84.4 使用 Maven 创建可执行 JAR

spring-boot-maven-plugin可用于创建可执行的“胖” JAR。如果您使用的是spring-boot-starter-parent POM,则只需声明插件即可,然后将 jar 重新打包:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

如果您不使用父 POM,您仍然可以使用插件,但是,您还必须添加<executions>部分:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>1.5.9.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

有关完整用法的详细信息,请参见plugin documentation

84.5 使用 Spring Boot 应用程序作为依赖项

像 war 文件一样,Spring Boot 应用程序也不打算用作依赖项。如果您的应用程序包含要与其他项目共享的类,则建议的方法是将该代码移到单独的模块中。然后,您的应用程序和其他项目可以依赖单独的模块。

如果您不能按照上面的建议重新排列代码,则必须配置 Spring Boot 的 Maven 和 Gradle 插件以生成一个单独的工件,该工件适合用作依赖项。可执行归档文件不能用作BOOT-INF/classes中的可执行 jar 格式软件包应用程序类的依赖项。这意味着当将可执行 jar 用作依赖项时,找不到它们。

为了产生两个工件,一个可以用作依赖项,另一个可以执行,必须指定分类器。该分类器应用于可执行 Files 的名称,保留默认 Files 作为依赖项。

要在 Maven 中配置exec的分类器,可以使用以下配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <classifier>exec</classifier>
            </configuration>
        </plugin>
    </plugins>
</build>

使用 Gradle 时,可以使用以下配置:

bootRepackage  {
    classifier = 'exec'
}

84.6 运行可执行 jar 时提取特定的库

可执行 jar 中的大多数嵌套库无需解压即可运行,但是某些库可能会出现问题。例如,JRuby 包含其自己的嵌套 jar 支持,它假定jruby-complete.jar始终可以直接作为文件直接使用。

要处理任何有问题的库,您可以标记在可执行 jar 首次运行时应将特定的嵌套 jar 自动解压缩到“ temp 文件夹”。

例如,为了指示应该使用 Maven 插件将 JRuby 标记为解包,您可以添加以下配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <requiresUnpack>
                    <dependency>
                        <groupId>org.jruby</groupId>
                        <artifactId>jruby-complete</artifactId>
                    </dependency>
                </requiresUnpack>
            </configuration>
        </plugin>
    </plugins>
</build>

并使用 Gradle 进行相同操作:

springBoot  {
    requiresUnpack = ['org.jruby:jruby-complete']
}

84.7 创建带有排除项的不可执行的 JAR

通常,如果您将可执行文件和非可执行 jar 作为构建产品,则可执行版本将具有库 jar 中不需要的其他配置文件。例如。 application.yml配置文件可能会从不可执行的 JAR 中排除。

这是在 Maven 中执行此操作的方法:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <classifier>exec</classifier>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <id>exec</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <classifier>exec</classifier>
                    </configuration>
                </execution>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <!-- Need this to ensure application.yml is excluded -->
                        <forceCreation>true</forceCreation>
                        <excludes>
                            <exclude>application.yml</exclude>
                        </excludes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

在 Gradle 中,您可以创建一个具有标准任务 DSL 功能的新 JAR 存档,然后使用其withJarTask属性使bootRepackage任务依赖于该任务:

jar {
    baseName = 'spring-boot-sample-profile'
    version =  '0.0.0'
    excludes = ['**/application.yml']
}

task('execJar', type:Jar, dependsOn: 'jar') {
    baseName = 'spring-boot-sample-profile'
    version =  '0.0.0'
    classifier = 'exec'
    from sourceSets.main.output
}

bootRepackage  {
    withJarTask = tasks['execJar']
}

84.8 远程调试以 Maven 启动的 Spring Boot 应用程序

要将远程调试器附加到以 Maven 启动的 Spring Boot 应用程序,可以使用maven pluginjvmArguments属性。

查看this example了解更多详细信息。

84.9 远程调试以 Gradle 启动的 Spring Boot 应用程序

要将远程调试器附加到以 Gradle 启动的 Spring Boot 应用程序,可以使用bootRun task 的jvmArgs属性或--debug-jvm命令行选项。

build.gradle :

bootRun {
    jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
}

Command line:

$ gradle bootRun --debug-jvm

查看Gradle 应用程序插件了解更多详细信息。

84.10 不使用 spring-boot-antlib 从 Ant 构建可执行 Files

要使用 Ant 进行构建,您需要获取依赖项,进行编译,然后创建一个 jar 或 war 存档。要使其可执行,可以使用spring-boot-antlib模块,也可以按照以下说明进行操作:

  • 如果要构建 jar,请将应用程序的类和资源打包在嵌套的BOOT-INF/classes目录中。如果要发动 War,请照常将应用程序的类打包在嵌套的WEB-INF/classes目录中。

  • 在 jar 的嵌套BOOT-INF/lib目录中或在 war 的WEB-INF/lib中添加运行时依赖项。记住不要压缩压缩 Files 中的条目。

  • 在 jar 的嵌套BOOT-INF/lib目录中添加provided(嵌入式容器)依赖项,对于 War 则将WEB-INF/lib-provided添加到嵌套的WEB-INF/lib-provided目录中。记住不要压缩压缩 Files 中的条目。

  • 在 Files 的根目录中添加spring-boot-loader类(因此Main-Class可用)。

  • 使用适当的启动器,例如 jar 文件的JarLauncher,作为清单中的Main-Class属性,并指定它需要作为清单条目的其他属性,主要是Start-Class

Example:

<target name="build" depends="compile">
    <jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
        <mappedresources>
            <fileset dir="target/classes" />
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="src/main/resources" erroronmissingdir="false"/>
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="${lib.dir}/runtime" />
            <globmapper from="*" to="BOOT-INF/lib/*"/>
        </mappedresources>
        <zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
        <manifest>
            <attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
            <attribute name="Start-Class" value="${start-class}" />
        </manifest>
    </jar>
</target>

Ant Samplebuild.xml任务与manual任务一起运行,如果您使用

$ ant -lib <folder containing ivy-2.2.jar> clean manual

之后,您可以使用

$ java -jar target/*.jar

84.11 如何使用 Java 6

如果您想将 Spring Boot 与 Java 6 一起使用,则必须进行少量配置更改。确切的更改取决于您应用程序的功能。

84.11.1 嵌入式 Servlet 容器兼容性

如果使用的是 Boot 的嵌入式 Servlet 容器之一,则必须使用 Java 6 兼容的容器。 Tomcat 7 和 Jetty 8 都与 Java 6 兼容。有关详情,请参见第 73.16 节“使用 Tomcat 7.x 或 8.0”第 73.18 节“使用 Jetty8”

84.11.2 Jackson

Jackson 2.7 和更高版本需要 Java7.如果要在 Java 6 中使用 Jackson,则必须降级到 Jackson 2.6.

Spring Boot 使用从 Jackson 2.7 开始引入的 Jackson BOM,因此您不能仅覆盖jackson.version属性。为了使用 Jackson 2.6,您将必须在构建的dependencyManagement部分中定义各个模块,有关详细信息,请检查this example

84.11.3 JTA API 兼容性

尽管 Java Transaction API 本身不需要 Java 7,但官方 API jar 包含已构建为需要 Java 7 的类。如果您使用的是 JTA,则需要用已构建的 Java 替换官方的 JTA 1.2 API jar。才能在 Java 6 上工作。为此,请排除对javax.transaction:javax.transaction-api的所有传递依赖,并用对org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Final的依赖替换它们