第三章 使用Spring Boot

全集

本節將詳細介紹如何使用Spring Boot, 它包含了諸如構建系統,自動配置以及怎么運行你的程序這些主題。我們還將介紹一些Spring Boot的最佳實踐。盡管Spring Boot沒什么特別的(它只是您可以使用的另一個庫),但是有一些建議可以使您的開發過程更輕松一些。

如果你是從Spring Boot開始的,那么在深入了解之前,您應該閱讀入門指南

3.1 構建系統

我們強烈推薦您選擇一個支持依賴管理的構建系統,可以讓你使用發布到Maven中央倉庫的組件。我們建議您使用Maven或Gradle??梢允筍pring Boot與其它構建系統(例如Ant)一起使用,但是它們并沒有得到很好的支持。

3.3.1 依賴管理

每個Spring Boot版本都提供了他所支持的依賴關系列表,實踐中,您不用在您的構建配置上提供任何依賴的版本,因為Spring Boot已經幫你管理了。當你升級Spring Boot時,它的依賴也一并升級了。

當你需要時,你仍然可以聲明版本來覆蓋Spring Boot推薦的版本。

精選列表包含可與Spring Boot一起使用的所有spring模塊以及完善的第三方庫列表。 該列表是可與Maven和Gradle一起使用的標準依賴清單(spring-boot-dependencies)。

每個Spring Boot穩定版本都和一個Spring Framework基礎版本相關聯,我們強烈建議您不要聲明它的版本。

3.1.2 Maven

Maven用戶可以繼承spring-boot-starter-parent來獲取一些合理的默認值,該Parent項目提供了下列功能:

  • Java 1.8作為默認編譯級別
  • UTF-8編碼
  • 一個繼承自spring-boot-dependencies pom文件的依賴管理塊,它管理了通用依賴的版本。這個依賴管理讓你省略在pom文件使用的那些依賴的<version>標簽
  • 以repackage來實現重新打包目標的執行
  • 智能的文件過濾
  • 合理的插件配置(exec插件,Git提交Id和Shade)
  • 對application.properties和application.yml進行智能的資源過濾,包括特定于配置文件的文件(例如,application-dev.properties和application-dev.yml)

注意,由于application.properties和application.yml文件接受Spring樣式的占位符(${...}),因此Maven過濾已更改為使用@...@占位符(您可以通過設置一個名為resource.delemiter的Maven屬性來覆蓋它)

繼承啟動器

通過繼承spring-boot-starter-parent來配置你的項目,查看下面列出的parent:

<!-- Inherit defaults from Spring Boot -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
</parent>

你應該只在這個依賴中聲明Spring Boot的版本。如果你導入其它的啟動器,你可以安全的省略版本號

使用該設置,您還可以通過覆蓋自己項目中的屬性來覆蓋各個依賴項。 例如,要升級到另一個Spring Data發布系列,您可以將以下內容添加到pom.xml中:

<properties>
    <spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>

查看 spring-boot-dependencies pom文件列出的屬性

不使用父POM來使用Spring Boot

并不是每個人都喜歡繼承spring-boot-starter-parent的POM文件。您可能需要使用自己的公司標準parent,或者可能希望顯示聲明所有Maven配置。

如果你不想使用spring-boot-starter-parent,你仍然可以通過使用一個 scope=import 的依賴來得到依賴管理的益處,如下所示:

<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.2.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

上面的示例配置沒有允許您通過使用屬性來覆蓋各個依賴項。為了獲得相同的結果,需要在spring-boot-dependencies條目之前的項目的dependencyManagement中添加一個元素。例如,要升級到另一個Spring Data發布系列,您可以添加下面的元素到你的pom.xml文件中:

<dependencyManagement>
    <dependencies>
        <!-- Override Spring Data release train provided by Spring Boot -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-releasetrain</artifactId>
            <version>Fowler-SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.2.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

在生疏示例總,我們指定了一個BOM,但是任何依賴項類型都可以以相同方式覆蓋

使用Spring Boot Maven Plugin

Spring Boot包含了一個將項目打包成可執行jar的Maven插件,若果要使用它就將這個插件像下面的示例一樣添加到你的<plugins>中:

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

如果你使用Spring Boot starter的父Pom,您只需要添加這個插件,并不需要任何配置除非你想改變在父Pom中定義的設置

3.1.3 Gradle

要將Spring Boot和Gradle一起使用,請參考Spring Boot的Gradle插件文檔:

3.1.4 Ant

可以使用Apache Ant + Ivy構建Spring Boot項目。 spring-boot-antlib“ AntLib”模塊也可用于幫助Ant創建可執行的jar。

要聲明依賴關系,典型的ivy.xml文件看起來類似于以下示例:

<ivy-module version="2.0">
    <info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
    <configurations>
        <conf name="compile" description="everything needed to compile this module" />
        <conf name="runtime" extends="compile" description="everything needed to run this module" />
    </configurations>
    <dependencies>
        <dependency org="org.springframework.boot" name="spring-boot-starter"
            rev="${spring-boot.version}" conf="compile" />
    </dependencies>
</ivy-module>

典型的build.xml類似于以下示例:

<project
    xmlns:ivy="antlib:org.apache.ivy.ant"
    xmlns:spring-boot="antlib:org.springframework.boot.ant"
    name="myapp" default="build">

    <property name="spring-boot.version" value="2.2.6.RELEASE" />

    <target name="resolve" description="--> retrieve dependencies with ivy">
        <ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" />
    </target>

    <target name="classpaths" depends="resolve">
        <path id="compile.classpath">
            <fileset dir="lib/compile" includes="*.jar" />
        </path>
    </target>

    <target name="init" depends="classpaths">
        <mkdir dir="build/classes" />
    </target>

    <target name="compile" depends="init" description="compile">
        <javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" />
    </target>

    <target name="build" depends="compile">
        <spring-boot:exejar destfile="build/myapp.jar" classes="build/classes">
            <spring-boot:lib>
                <fileset dir="lib/runtime" />
            </spring-boot:lib>
        </spring-boot:exejar>
    </target>
</project>

如果您不想使用spring-boot-antlib模塊,請參閱不使用spring-boot-antlib“如何”而從Ant構建可執行檔案。

3.1.5 Starters

Starters是一組方便的依賴項描述符,您可以在應用程序中包括它們。 您可以一站式購買所需的所有Spring和相關技術,而不必搜尋示例代碼和依賴描述符的復制粘貼負載。 例如,如果要開始使用Spring和JPA進行數據庫訪問,請在項目中包括spring-boot-starter-data-jpa依賴項。

Starters包含許多啟動項目并快速運行所需的依賴項,并且具有一組受支持的受管傳遞性依賴項

名稱包含什么

所有官方Starters都遵循類似的命名方式。 spring-boot-starter-*,其中*是特定類型的應用程序。 這種命名結構旨在在您需要尋找入門者時提供幫助。 許多IDE中的Maven集成使您可以按名稱搜索依賴項。 例如,在安裝了適當的Eclipse或STS插件的情況下,您可以在POM編輯器中按ctrl-space并鍵入“ spring-boot-starter”以獲取完整列表。

Spring Boot在org.springframework.boot組下提供了以下應用程序Starter:

Table 1. Spring Boot應用程序Starter

Name Description Pom
spring-boot-starter 核心Starter,包含自動配置支持,日志和YAML Pom
spring-boot-starter-activemq 使用Apache ActiveMQ的JMS消息的Starter Pom
spring-boot-starter-amqp 使用Spring AMQP和Rabbit MQ的Starter Pom
spring-boot-starter-aop 使用Spring AOP和AspectJ進行面向方面編程的Starter Pom
spring-boot-starter-artemis 使用Apache Artemis的JMS消息傳遞Starter Pom
spring-boot-starter-batch 使用Spring Batch的Starter Pom
spring-boot-starter-cache 使用Spring Framework的緩存支持的Starter Pom
spring-boot-starter-cloud-connectors 使用Spring Cloud Connectors的Starter,可簡化與Cloud Foundry和Heroku等云平臺中服務的連接。不推薦使用Java CFEnv Pom
spring-boot-starter-data-cassandra 使用Cassandra分布式數據庫和Spring Data Cassandra Reactive的Starter Pom
spring-boot-starter-data-couchbase 使用Couchbase面向文檔的數據庫和Spring Data Couchbase的入門 Pom
spring-boot-starter-data-elasticsearch 使用Elasticsearch搜索和分析引擎以及Spring Data Elasticsearch的Starter Pom
spring-boot-starter-data-jdbc 使用Spring Data JDBC的Starter Pom
spring-boot-starter-data-jpa 將Spring Data JPA與Hibernate結合使用的Starter Pom
spring-boot-starter-data-ldap 使用Spring Data LDAP的Starter Pom
spring-boot-starter-data-mongodb 使用MongoDB面向文檔的數據庫和Spring Data MongoDB的Starter Pom
spring-boot-starter-data-mongodb-reactive 使用MongoDB面向文檔的數據庫和Spring Data MongoDB Reactive的Starter Pom
spring-boot-starter-data-neo4j 使用Neo4j圖形數據庫和Spring Data Neo4j的Starter Pom
spring-boot-starter-data-redis 使用Redis鍵值數據存儲與Spring Data Redis和Lettuce客戶端的Starter Pom
spring-boot-starter-data-redis-reactive 將Redis鍵值數據存儲與Spring Data Redis Reacting和Lettuce客戶端一起使用的Starter Pom
spring-boot-starter-data-rest 使用Spring Data REST通過REST公開Spring數據存儲庫的Starter Pom
spring-boot-starter-data-solr 將Apache Solr搜索平臺與Spring Data Solr結合使用的Starter Pom
spring-boot-starter-freemarker 使用FreeMarker視圖構建MVC Web應用程序的Starter Pom
spring-boot-starter-groovy-templates 使用Groovy模板視圖構建MVC Web應用程序的Starter Pom
spring-boot-starter-hateoas 使用Spring MVC和Spring HATEOAS構建基于超媒體的RESTful Web應用程序的Starter Pom
spring-boot-starter-integration 使用Spring Integration的Starter Pom
spring-boot-starter-jdbc 結合使用JDBC和HikariCP連接池的Starter Pom
spring-boot-starter-jersey 使用JAX-RS和Jersey構建RESTful Web應用程序的Starter,的替代品spring-boot-starter-web Pom
spring-boot-starter-jooq 使用jOOQ訪問SQL數據庫的Starter,spring-boot-starter-data-jpa或spring-boot-starter-jdbc的替代品 Pom
spring-boot-starter-json 讀寫JSON的Starter Pom
spring-boot-starter-jta-atomikos 使用Atomikos的JTA事務的Starter Pom
spring-boot-starter-jta-bitronix 使用Bitronix的JTA事務的Starter Pom
spring-boot-starter-mail 使用Java Mail和Spring Framework的電子郵件發送支持的Starter Pom
spring-boot-starter-mustache 使用Mustache視圖構建Web應用程序的Starter Pom
spring-boot-starter-oauth2-client 使用Spring Security的OAuth2 / OpenID Connect客戶端功能的Starter Pom
spring-boot-starter-oauth2-resource-server 使用Spring Security的OAuth2資源服務器功能的Starter Pom
spring-boot-starter-quartz 使用Quartz Scheduler的Starter Pom
spring-boot-starter-rsocket 用于構建RSocket客戶端和服務器的Starter Pom
spring-boot-starter-security 使用Spring Security的Starter Pom
spring-boot-starter-test 用于使用包括JUnit,Hamcrest和Mockito在內的庫測試Spring Boot應用程序的Starter Pom
spring-boot-starter-thymeleaf 使用Thymeleaf視圖構建MVC Web應用程序的Starter Pom
spring-boot-starter-validation 通過Hibernate Validator使用Java Bean驗證的Starter Pom
spring-boot-starter-web 使用Spring MVC構建Web(包括RESTful)應用程序的Starter。使用Tomcat作為默認的嵌入式容器 Pom
spring-boot-starter-web-services 使用Spring Web Services的Starter Pom
spring-boot-starter-webflux 使用Spring Framework的Reactive Web支持構建WebFlux應用程序的Starter Pom
spring-boot-starter-websocket 使用Spring Framework的WebSocket支持構建WebSocket應用程序的Starter Pom

除了應用程序啟動程序,以下啟動程序可用于添加生產就緒功能:

Table 2. Spring Boot生產Starter

Name Description Pom
spring-boot-starter-actuator 使用Spring Boot的Actuator的Starter,它提供了生產就緒功能,可幫助您監視和管理應用程序 Pom

最后,Spring Boot還包括以下啟動程序,如果您想排除或交換特定的技術方面,可以使用這些啟動程序:

Table 3. Spring Boot技術入門

Name Description Pom
spring-boot-starter-jetty 使用Jetty作為嵌入式servlet容器的Starter,spring-boot-starter-tomcat的替代品 Pom
spring-boot-starter-log4j2 使用Log4j2進行日志記錄的Starter,spring-boot-starter-logging的替代品 Pom
spring-boot-starter-logging 使用Logback進行日志記錄的Starter,默認日志Starter Pom
spring-boot-starter-reactor-netty 使用Reactor Netty作為嵌入式反應式HTTP服務器的Starter Pom
spring-boot-starter-tomcat 用于將Tomcat用作嵌入式Servlet容器Starter,spring-boot-starter-web默認使用的servlet容器Starter Pom
spring-boot-starter-undertow 使用Undertow作為嵌入式servlet容器的Starter,spring-boot-starter-tomcat的替代品 Pom

有關社區貢獻的其他入門者的列表,請參閱GitHub中spring-boot-starters模塊中的README文件

3.2 結構化代碼

Spring Boot不需要任何特定的代碼布局即可工作。 但是,有一些最佳做法可以幫助您

3.2.1 使用默認包

當類不包含程序包聲明時,將其視為在“默認程序包”中。 通常不建議使用“默認程序包”,應避免使用。 對于使用@ ComponentScan,@ ConfigurationPropertiesScan,@ EntityScan或@SpringBootApplication注解的Spring Boot應用程序,這可能會導致特定的問題,因為每個jar中的每個類都會被讀取。

我們建議您遵循Java建議的程序包命名約定,并使用反向域名(例如com.example.project)。

3.2.2 放置應用程序主類

我們通常推薦您將應用程序主類放置在其它類下根包中。@SpringBootApplicaton注解經常放在你的主類中,它隱式的定義了某些條目的基礎搜索路徑。例如,你正在開發一個JPA應用,@SpringBootApplication注解的類的包被用來搜索@Entity,使用根包也可以將組件掃描應用于你的項目。

如果你不想使用@SpringBootApplication注解,@EnableAutoConfiguration和@ComponentScan也定義了那些功能,所以你可以使用它們作為替代。

下面列出了一個經典的布局

com
 +- example
     +- myapplication
         +- Application.java
         |
         +- customer
         |   +- Customer.java
         |   +- CustomerController.java
         |   +- CustomerService.java
         |   +- CustomerRepository.java
         |
         +- order
             +- Order.java
             +- OrderController.java
             +- OrderService.java
             +- OrderRepository.java

Applicaton.java文件會聲明main方法,以及基本的@SpringBootApplication注解,如下所示:

package com.example.myappmlication;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

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

}

3.3 配置類

Spring Boot支持基于Java的配置,盡管可以將SpringApplicaton和XML源一起使用,我們通常建議您的主要代碼為單個@Confuguration類。通常,定義Main方法的類是首選的@Configuration。

網上有很多使用XML配置的Spring示例,如果可能,盡量使用基于Java的配置。搜索@Enable*注解會是一個很好的開始。

3.3.1 導入額外的配置類

你不需要在每個類上加@Configuration注解,@Import注解可以用來加載其他的配置類。你也可以使用@ComponentScan注解來掃描所有的Spring組件,包括@Configuration注解的類。

3.3.2 導入XML配置

如果你一定要是使用基于XML的配置,我們建議您依然從@Configuration類開始,然后使用@ImportResource注解來加載XML配置文件。

3.4 自動配置

Spring Boot的自動配置會嘗試根據你導入的依賴來自動配置你的應用。例如,如果HSQLDB在你的類路徑中,但你并沒有手動配置任何數據庫連接Bean,那么Spring Boot會自動配置一個內存型數據庫。

您需要通過向@Configuration類之一添加@EnableAutoConfiguration或@SpringBootApplication注釋來選擇加入自動配置。

你只需要加入@EnableAutoConfiguration或@SpringBootApplication之一,我們通常推薦你添加其中一個到你的一個配置類中。

3.4.1 逐漸取代自動配置

自動配置是非侵入性的,在任何時候,你可以自定義你的配置來代替自動配置的特定部分。例如,當你添加你的數據庫連接Bean,那么默認的內嵌數據庫會被取代。

如果你想知道正在應用的自動配置是什么,為什么這么配置,那就以debug模式啟動你的應用,這樣做可以啟用調試日志,以選擇核心記錄器,并將條件報告記錄到控制臺。

3.4.2 關閉特定的配置類

如果你發現一個正在被使用的配置類不是你想要的,你可以使用@SpringBootApplication注解的exclude屬性來關閉它,正如下所示:

import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class MyApplication {
}

如果這個類不在類路徑中,你可用使用該注解的excludeName屬性和使用類的全路徑限定名來作為替代。如果你比起@SpringBootApplication更傾向于使用@EnableAutoConfiguration注解,exclude和excludeName也是可以使用的。最后,您還可以使用spring.autoconfigure.exclude屬性控制要排除的自動配置類的列表。

您可以在注解級別和使用屬性來定義排除項。

即使自動配置類是公共的,該類的唯一方面也被認為是公共API,該類的名稱可以用于禁用自動配置。 這些類的實際內容(例如嵌套配置類或Bean方法)僅供內部使用,我們不建議直接使用它們。

3.5 SpringBean和依賴注入

你可以自由的選擇使用標準Spring Framework技術來定義你的Bean和依賴注入。為簡單起見,我們發現使用@ComponentScan(掃描你的Bean)和@Autowired(用來構造器注入)效果很好。

如果你按照上面的建議來組織你的代碼(把你的應用啟動類放在根包),你可以添加@ComponentScan而不使用任何參數,你的所有Spring組件(@Component,@Repository,@Service,@Controller等等)將會被自動注冊為Bean。

以下示例顯示了一個@Service Bean,它使用構造函數注入來獲取所需的RiskAssessor Bean:

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DatabaseAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    @Autowired
    public DatabaseAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }

    // ...

}

如果bean具有一個構造函數,則可以省略@Autowired,如以下示例所示:

@Service
public class DatabaseAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    public DatabaseAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }

    // ...

}

請注意,使用構造函數注入使riskAssessor字段被標記為final,表明它隨后無法更改。

3.6 使用@SpringBootApplication注解

許多Spring Boot開發人員喜歡他們的應用使用自動配置,組件掃描并可以添加額外的配置到應用啟動類上,單個的@SpringBootApplication注解可以開啟下面三個功能:

  • @EnableAutoConfiguration 開啟Spring Boot的自動配置機制
  • @ComponentScan:在應用程序所在的軟件包上啟用@Component掃描(請參閱最佳實踐
  • @Configuration 允許注入額外的Bean到上下文中或導入額外的配置類。
package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

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

}

@SpringBootApplication還提供別名以自定義@EnableAutoConfiguration和@ComponentScan的屬性。

這些功能都不是強制性的,您可以選擇用它啟用的任何功能替換此單個注釋。 例如,您可能不想在應用程序中使用組件掃描或配置屬性掃描:

package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;


@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {

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

}

在此示例中,除了不會自動檢測到@Component注釋的類和@ConfigurationProperties注釋的類并且顯式導入用戶定義的Bean外,Application就像其他任何Spring Boot應用程序一樣(請參閱@Import)。

3.7 運行你的應用

將應用打包成為Jar包并使用內嵌HTTP服務器的最大好處是你可以在任何時候運行你的應用。調試Spring Boot應用也變得非常容易,你不需要任何特殊的IDE插件或擴展。

3.7.1 在IDE中運行你的應用

你可以像一個簡單的Java應用一樣在IDE中運行Spring Boo,但是你首先需要導入你的項目,導入過程根據你的IDE和構建系統有所區別。大多數IDE可以直接導入Maven工程,例如,Eclipse用戶可以從File菜單中選擇Import->Existing Maven Projects導入。

如果你不能將應用直接導入你的IDE,你可能需要用構建插件來生成IDE元數據。Maven包含了Eclipse和IDEA的插件,Gradle也同樣為一些IDE提供了插件。

如果突然將一個Web應用運行兩次,會看到一個“Port is already in use”的錯誤。STS用戶可以使用ReLaunch按鈕而不是Run來確保存在的實例被關閉。

3.7.2 運行打包后的程序

如果你使用Spring Boot的Maven或Gradle插件來生成可執行jar,你可以像下面的示例一樣,使用java -jar來運行你的應用

  $ java -jar target/myapplication-0.0.1-SNAPSHOT.jar

可以在運行一個打包的應用的同時開啟遠程調試,這樣做可以將一個debugger和你的應用連接起來,像下面的示例一樣:

 $ java -jar -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
       -jar target/myapplication-0.0.1-SNAPSHOT.jar

3.7.3 使用Maven插件

Spring Boot的Maven插件包含了一個運行的目標,可以來快速的編譯運行你的應用。應用可以像在IDE中一樣以一種暴露的方式運行。下面的示例展示了一個用經典的Maven命令來運行應用:

 $ mvn spring-boot:run

您可能還想使用MAVEN_OPTS操作系統環境變量,如以下示例所示:

 $ export MAVEN_OPTS=-Xmx1024m

3.7.4 使用Gradle插件

Spring Boot Gradle插件還包含一個bootRun任務,該任務可用于以暴露的方式運行您的應用程序。 每當您應用org.springframework.boot和java插件時,都會添加bootRun任務,并在以下示例中顯示:

 $ gradle bootRun

您可能還想使用JAVA_OPTS操作系統環境變量,如以下示例所示:

 $ export JAVA_OPTS=-Xmx1024m

3.7.5 熱交換

因為Spring Boot應用是指普通的Java應用,JVM熱交換應該可以立即使用。JVM熱交換在一定程度上受到它可以替換的字節碼的限制,對于更完善的解決方案,可以使用JRebel。

spring-boot-devtools也包含了應用快速啟動的支持,有關詳細信息,請參見本章稍后的“devtools”部分和熱交換“操作方法”。

3.8 DevTools

Spring Boot包括一組額外的工具,這些工具可以使應用程序開發體驗更加愉快。spring-boot-devtools模塊可以添加到任何的工程中來提供額外的開發時特性。要包括devtools支持,請將模塊依賴項添加到您的構建中,如以下Maven和Gradle清單所示:

Maven

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

Gradle

configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
}
dependencies {
    developmentOnly("org.springframework.boot:spring-boot-devtools")
}

開發人員工具會在運行完全打包應用的時候被自動關閉。如果您的應用程序是從java -jar啟動的,或者是從特殊的類加載器啟動的,則將其視為“生產應用程序”。 如果這不適用于您(即,如果您從容器中運行應用程序),請考慮排除devtools或設置-Dspring.devtools.restart.enabled = false系統屬性。

在Maven中將依賴項標記為可選,或在Gradle中使用自定義developmentOnly配置(如上所示)是一種最佳做法,可防止將devtools過渡地應用到使用項目的其他模塊。

重新打包的存檔默認情況下不包含devtools。 如果要使用某個遠程devtools功能,則需要禁用excludeDevtools構建屬性以包括它。 Maven和Gradle插件均支持該屬性。

3.8.1 默認屬性

Spring Boot支持的一些庫使用緩存來提高性能。例如,模板引擎 template engines緩存已編譯的模板,以避免重復解析模板文件。 而且,Spring MVC可以在提供靜態資源時向響應添加HTTP緩存標頭。

盡管緩存在生產中非常有益,但在開發過程中可能適得其反,從而使您無法看到自己剛剛在應用程序中所做的更改。 因此,默認情況下,spring-boot-devtools禁用緩存選項。

緩存選項通常由application.properties文件中的設置配置。 例如,Thymeleaf提供spring.thymeleaf.cache屬性。 spring-boot-devtools模塊不需要自動設置這些屬性,而是自動應用合理的開發時配置。

因為在開發Spring MVC和Spring WebFlux應用程序時需要有關Web請求的更多信息,所以devtools將為Web日志記錄組啟用DEBUG日志記錄。 這將為您提供有關傳入請求,處理程序正在處理的信息,響應結果等信息。如果您希望記錄所有請求詳細信息(包括潛在的敏感信息),則可以打開spring.http.log-request- details配置屬性。

如果你不想使用默認屬性,可以在application.properties文件中設置spring.devtool.add-properties為false

有關devtools應用的屬性的完整列表,請參見DevToolsPropertyDefaultsPostProcessor

3.8.2 啟動重啟

使用spring-boot-devtools的應用會在類路徑下的文件改變時自動重啟,在IDE中工作時,這可能是一個有用的功能,因為它為代碼更改提供了非??焖俚姆答佈h。 默認情況下,將監視類路徑上指向文件夾的任何條目的更改。 請注意,某些資源(例如靜態資產和視圖模板)不需要重新啟動應用程序。

觸發重啟
當DevTools監視類路徑資源時,觸發重啟的唯一方法是更新類路徑。 導致類路徑更新的方式取決于您使用的IDE。 在Eclipse中,保存修改后的文件將導致類路徑被更新并觸發重新啟動。 在IntelliJ IDEA中,構建項目(Build +→+ Build Project)具有相同的效果。

只要啟用了fork,您還可以使用受支持的構建插件(Maven和Gradle)來啟動應用程序,因為DevTools需要隔離的應用程序類加載器才能正常運行。 默認情況下,Gradle和Maven插件會fork應用程序進程。

與LiveReload一起使用時,自動重啟非常有效。 有關詳細信息,請參見LiveReload部分。 如果使用JRebel,則禁用自動重新啟動,而支持動態類重新加載。 其他devtools功能(例如LiveReload和屬性替代)仍可以使用。

DevTools依靠應用程序上下文的關閉掛鉤在重新啟動期間將其關閉。 如果您禁用了關閉掛鉤(SpringApplication.setRegisterShutdownHook(false)),它將無法正常工作。

在確定類路徑上的條目是否應在更改后觸發重新啟動時,DevTools會自動忽略名為spring-boot,spring-boot-devtools,spring-boot-autoconfigure,spring-boot-actuator和spring-boot-starter的項目。

DevTools需要自定義ApplicationContext使用的ResourceLoader。 如果您的應用程序已經提供了,它將被包裝。 不支持在ApplicationContext上直接重寫getResource方法。

                                                     重啟VS重加載

重啟技術是通過Spring Boot使用兩個類加載器來實現,不變的類(例如那些第三方Jar包中的)被加載到一個基本類加載器,你正在開發的類使用一個restart類加載器,當應用重啟時,restart類加載器被丟掉并新建一個實例,這種方式意味著比傳統的冷啟動更快,因為基本類加載器一直可用并已填充

如果發現重新啟動對于您的應用程序而言不夠快,或者遇到類加載問題,則可以考慮從ZeroTurnaround重新加載技術,例如JRebel。 這些方法通過在加載類時重寫類來使它們更適合于重新加載。

記錄條件評估中的更改

默認每次應用重啟時,記錄條件評估增量的報告。該報告顯示了您進行更改(例如添加或刪除Bean以及設置配置屬性)時對應用程序自動配置的更改。

要禁用報告的日志記錄,請設置以下屬性:

spring.devtools.restart.log-condition-evaluation-delta=false

排除資源

某些資源在更改時不一定需要觸發重新啟動。 例如,Thymeleaf模板可以就地編輯。 默認情況下,更改/ META-INF/mave,/META-INF/resources,/resources,/static,/public或/templates中的資源不會觸發重新啟動,但會觸發實時重新加載。 如果要自定義這些排除項,則可以使用spring.devtools.restart.exclude屬性。 例如,要僅排除/ static和/ public,可以設置以下屬性:

spring.devtools.restart.exclude=static/**,public/**

如果你想保持默認的配置并增加一些額外的排除項,請使用spring.devtools.restart.addtional-exclude屬性作為替代

監測額外路徑

當您對不在類路徑上的文件進行更改時,您可能希望重新啟動或重新加載應用程序。 為此,請使用spring.devtools.restart.additional-paths屬性配置其他路徑以監視更改。 您可以使用前面所述的spring.devtools.restart.exclude屬性來控制其他路徑下的更改是觸發完全重啟還是動態重新加載。

關閉重啟

如果你不想使用重啟功能,你可以設置spring.devtool.restart.enabled屬性來關閉它。在大多數情況下,您可以在application.properties中設置此屬性(這樣做仍會初始化restart類加載器,但它不會監視文件更改)。

如果您需要完全禁用重啟支持(例如,因為它不適用于特定的庫),則需要在調用SpringApplication.run(...)之前將spring.devtools.restart.enabled系統屬性設置為false,例如 如以下示例所示:

public static void main(String[] args) {
    System.setProperty("spring.devtools.restart.enabled", "false");
    SpringApplication.run(MyApp.class, args);
}

使用觸發文件

如果使用持續編譯更改文件的IDE,則可能更喜歡僅在特定時間觸發重新啟動。 為此,您可以使用“觸發文件”,這是一個特殊文件,當您要實際觸發重新啟動檢查時必須對其進行修改。

對文件的任何更新都會觸發檢查,但是只有在Devtools檢測到有事情要做的情況下,重啟才會真正發生。

要使用觸發文件,請將spring.devtools.restart.trigger-file屬性設置為觸發文件的名稱(不包括任何路徑)。 觸發器文件必須出現在類路徑上的某個位置。

例如,如果您的項目具有以下結構:

src
+- main
   +- resources
      +- .reloadtrigger

那么你的trigger-file屬性會是這樣的:

spring.devtools.restart.trigger-file=.reloadtrigger

現在重啟只會在src/main/resources/.reloadtrigger文件更新是發生

您可能希望將spring.devtools.restart.trigger-file設置為全局設置,以便所有項目的行為均相同。

某些IDE具有使您不必手動更新觸發器文件的功能。Spring Tools for Eclipse
IntelliJ IDEA (Ultimate Edition)都具有這種支持。 使用Spring Tools,您可以從控制臺視圖使用“重新加載”按鈕(只要您的觸發文件名為.reloadtrigger)。 對于IntelliJ,您可以按照其文檔中的說明進行操作。

定制Restart類加載器

如前面的“重新啟動與重新加載”部分所述,重新啟動功能是通過使用兩個類加載器實現的。 對于大多數應用程序,此方法效果很好。 但是,有時可能會導致類加載問題。

默認情況下,IDE中任何打開的項目都使用“重新啟動”類加載器加載,而任何常規.jar文件都使用“基本”類加載器加載。 如果您在多模塊項目上工作,并且并非每個模塊都導入到IDE中,則可能需要自定義內容。 為此,您可以創建一個META-INF / spring-devtools.properties文件。

spring-devtools.properties文件可以包含帶有restart.exclude和restart.include前綴的屬性。 include元素是應上拉到“重新啟動”類加載器中的項目,而exclude元素是應下推到“基本”類加載器中的項目。 該屬性的值是一個應用于類路徑的正則表達式模式,如以下示例所示:

restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\.]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\.]+\.jar

所有屬性鍵都必須是唯一的。 只要屬性以restart.include開頭, 或restart.exclude開頭,都會被考慮在內

類路徑中的所有META-INF / spring-devtools.properties將被加載。 您可以將文件打包到項目內部或項目使用的庫中。

已知局限性

重新啟動功能不適用于使用標準ObjectInputStream反序列化的對象。 如果您需要反序列化數據,則可能需要將Spring的ConfigurableObjectInputStream與Thread.currentThread().getContextClassLoader()結合使用。

如果您不想在應用程序運行時啟動LiveReload服務,則可以將spring.devtools.livereload.enabled屬性設置為false。

一次只能運行一個LiveReload服務。 在啟動應用程序之前,請確保沒有其他LiveReload服務正在運行。 如果從IDE啟動多個應用程序,則只有第一個具有LiveReload支持。

3.8.4 全局設置

您可以通過將以下任何文件添加到$HOME/.config / spring-boot文件夾來配置全局devtools設置:

  1. spring-boot-devtools.properties
  2. spring-boot-devtools.yaml
  3. spring-boot-devtools.yml

添加到這些文件的任何屬性都將應用于使用devtools的計算機上的所有Spring Boot應用程序。 例如,要將重新啟動配置為始終使用觸發文件,應添加以下屬性:

~/.config/spring-boot/spring-boot-devtools.properties

spring.devtools.restart.trigger-file=.reloadtrigger

如果在$HOME/.config/spring-boot中找不到devtools配置文件,則在$HOME文件夾的根目錄中搜索是否存在.spring-boot-devtools.properties文件。 這使您可以與不支持$HOME/.config/spring-boot位置的較舊版本的Spring Boot上的應用程序共享devtools全局配置。

在上述文件中激活的配置文件不會影響特定配置文件的加載。

3.8.5 遠程應用

Spring Boot開發人員工具不僅限于本地開發。 遠程運行應用程序時,您還可以使用多種功能。 選擇啟用遠程支持,可能會帶來安全風險。 僅當在受信任的網絡上運行或使用SSL保護時,才應啟用它。 如果這兩個選項都不可用,則不應使用DevTools的遠程支持。 您永遠不要在生產部署上啟用支持。

要啟用它,您需要確保重新打包的檔案中包含devtools,如以下清單所示:

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

然后,您需要設置spring.devtools.remote.secret屬性。 像任何重要的密碼或機密一樣,該值應唯一且強壯,以免被猜測或強行使用。

遠程devtools支持分為兩個部分:接受連接的服務器端端點和在IDE中運行的客戶端應用程序。 設置spring.devtools.remote.secret屬性后,將自動啟用服務器組件。 客戶端組件必須手動啟動。

運行遠程客戶端應用

遠程客戶端應用程序旨在在您的IDE中運行, 您需要使用與您連接到的遠程項目相同的類路徑來運行org.springframework.boot.devtools.RemoteSpringApplication。 該應用程序的唯一必需參數是它連接到的遠程URL。

例如,如果您使用的是Eclipse或STS,并且有一個名為my-app的項目已部署到Cloud Foundry,則可以執行以下操作:

  • 從Run菜單中選擇Run Configuration
  • 創建一個新的Java應用啟動配置
  • 選擇my-app項目
  • 使用org.springframework.boot.devtools.RemodeSpringApplication作為啟動類
  • https://myapp.cfapps.io(或你的URL)添加到程序參數中

正在運行的遠程客戶端可能類似于以下清單:

  .   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote :: 2.2.6.RELEASE

2015-06-10 18:25:06.632  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-project/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code)
2015-06-10 18:25:06.671  INFO 14938 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043  WARN 14938 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074  INFO 14938 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2015-06-10 18:25:07.130  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)

因為遠程客戶端使用與真實應用程序相同的類路徑,所以它可以直接讀取應用程序屬性。 這就是讀取spring.devtools.remote.secret屬性并將其傳遞給服務器進行身份驗證的方式。

始終建議使用https://作為連接協議,以便對通信進行加密并且不能截獲密碼。

如果需要使用代理來訪問遠程應用程序,請配置spring.devtools.remote.proxy.host和spring.devtools.remote.proxy.port屬性

遠程更新

遠程客戶端以與本地重新啟動相同的方式監視應用程序類路徑中的更改。 任何更新的資源都會推送到遠程應用程序,并且(如果需要)會觸發重新啟動。 如果您迭代使用本地沒有的云服務的功能,這將很有幫助。 通常,遠程更新和重新啟動比完整的重建和部署周期要快得多。

僅在遠程客戶端正在運行時監視文件。 如果在啟動遠程客戶端之前更改文件,則不會將其推送到遠程服務器。

配置文件系統觀察器

FileSystemWatcher的工作方式是按一定時間間隔輪詢類更改,然后等待預定義的靜默期以確保沒有更多更改。 然后將更改上傳到遠程應用程序。 在較慢的開發環境中,可能會發生靜默期不夠的情況,并且類中的更改可能會分為幾批。 第一批類更改上傳后,服務器將重新啟動。 由于服務器正在重新啟動,因此下一批不能發送到應用程序。

這通常通過RemoteSpringApplication日志中的警告來證明,即有關上載某些類失敗的消息,然后進行重試。 但是,這也可能導致應用程序代碼不一致,并且在上傳第一批更改后無法重新啟動。

如果您經常觀察到此類問題,請嘗試將spring.devtools.restart.poll-interval和spring.devtools.restart.quiet-period參數增加到適合您的開發環境的值:

spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s

現在每2秒輪詢一次受監視的classpath文件夾是否有更改,并保持1秒鐘的靜默時間以確保沒有其他類更改。

3.9 打包您的生產應用

可執行jar可以用于生產部署。 由于它們是獨立的,因此它們也非常適合基于云的部署。

對于其他“生產準備就緒”功能,例如運行狀況,審核和度量REST或JMX端點,請考慮添加spring-boot-actuator。 有關詳細信息,請參見Spring Boot Actuator:生產就緒功能。

3.10 接下來閱讀什么

現在,您應該了解如何使用Spring Boot以及應遵循的一些最佳實踐。 現在,您可以繼續深入了解特定的Spring Boot功能,或者可以跳過并閱讀有關Spring Boot的“生產就緒”方面的信息。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容