第三章 使用Spring Boot

全集

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

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

3.1 構(gòu)建系統(tǒng)

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

3.3.1 依賴管理

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

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

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

每個Spring Boot穩(wěn)定版本都和一個Spring Framework基礎(chǔ)版本相關(guān)聯(lián),我們強烈建議您不要聲明它的版本。

3.1.2 Maven

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

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

注意,由于application.properties和application.yml文件接受Spring樣式的占位符(${...}),因此Maven過濾已更改為使用@...@占位符(您可以通過設(shè)置一個名為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>

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

使用該設(shè)置,您還可以通過覆蓋自己項目中的屬性來覆蓋各個依賴項。 例如,要升級到另一個Spring Data發(fā)布系列,您可以將以下內(nèi)容添加到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文件。您可能需要使用自己的公司標(biāo)準(zhǔn)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>

上面的示例配置沒有允許您通過使用屬性來覆蓋各個依賴項。為了獲得相同的結(jié)果,需要在spring-boot-dependencies條目之前的項目的dependencyManagement中添加一個元素。例如,要升級到另一個Spring Data發(fā)布系列,您可以添加下面的元素到你的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包含了一個將項目打包成可執(zhí)行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中定義的設(shè)置

3.1.3 Gradle

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

3.1.4 Ant

可以使用Apache Ant + Ivy構(gòu)建Spring Boot項目。 spring-boot-antlib“ AntLib”模塊也可用于幫助Ant創(chuàng)建可執(zhí)行的jar。

要聲明依賴關(guān)系,典型的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構(gòu)建可執(zhí)行檔案。

3.1.5 Starters

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

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

名稱包含什么

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

Spring Boot在org.springframework.boot組下提供了以下應(yīng)用程序Starter:

Table 1. Spring Boot應(yīng)用程序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等云平臺中服務(wù)的連接。不推薦使用Java CFEnv Pom
spring-boot-starter-data-cassandra 使用Cassandra分布式數(shù)據(jù)庫和Spring Data Cassandra Reactive的Starter Pom
spring-boot-starter-data-couchbase 使用Couchbase面向文檔的數(shù)據(jù)庫和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結(jié)合使用的Starter Pom
spring-boot-starter-data-ldap 使用Spring Data LDAP的Starter Pom
spring-boot-starter-data-mongodb 使用MongoDB面向文檔的數(shù)據(jù)庫和Spring Data MongoDB的Starter Pom
spring-boot-starter-data-mongodb-reactive 使用MongoDB面向文檔的數(shù)據(jù)庫和Spring Data MongoDB Reactive的Starter Pom
spring-boot-starter-data-neo4j 使用Neo4j圖形數(shù)據(jù)庫和Spring Data Neo4j的Starter Pom
spring-boot-starter-data-redis 使用Redis鍵值數(shù)據(jù)存儲與Spring Data Redis和Lettuce客戶端的Starter Pom
spring-boot-starter-data-redis-reactive 將Redis鍵值數(shù)據(jù)存儲與Spring Data Redis Reacting和Lettuce客戶端一起使用的Starter Pom
spring-boot-starter-data-rest 使用Spring Data REST通過REST公開Spring數(shù)據(jù)存儲庫的Starter Pom
spring-boot-starter-data-solr 將Apache Solr搜索平臺與Spring Data Solr結(jié)合使用的Starter Pom
spring-boot-starter-freemarker 使用FreeMarker視圖構(gòu)建MVC Web應(yīng)用程序的Starter Pom
spring-boot-starter-groovy-templates 使用Groovy模板視圖構(gòu)建MVC Web應(yīng)用程序的Starter Pom
spring-boot-starter-hateoas 使用Spring MVC和Spring HATEOAS構(gòu)建基于超媒體的RESTful Web應(yīng)用程序的Starter Pom
spring-boot-starter-integration 使用Spring Integration的Starter Pom
spring-boot-starter-jdbc 結(jié)合使用JDBC和HikariCP連接池的Starter Pom
spring-boot-starter-jersey 使用JAX-RS和Jersey構(gòu)建RESTful Web應(yīng)用程序的Starter,的替代品spring-boot-starter-web Pom
spring-boot-starter-jooq 使用jOOQ訪問SQL數(shù)據(jù)庫的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事務(wù)的Starter Pom
spring-boot-starter-jta-bitronix 使用Bitronix的JTA事務(wù)的Starter Pom
spring-boot-starter-mail 使用Java Mail和Spring Framework的電子郵件發(fā)送支持的Starter Pom
spring-boot-starter-mustache 使用Mustache視圖構(gòu)建Web應(yīng)用程序的Starter Pom
spring-boot-starter-oauth2-client 使用Spring Security的OAuth2 / OpenID Connect客戶端功能的Starter Pom
spring-boot-starter-oauth2-resource-server 使用Spring Security的OAuth2資源服務(wù)器功能的Starter Pom
spring-boot-starter-quartz 使用Quartz Scheduler的Starter Pom
spring-boot-starter-rsocket 用于構(gòu)建RSocket客戶端和服務(wù)器的Starter Pom
spring-boot-starter-security 使用Spring Security的Starter Pom
spring-boot-starter-test 用于使用包括JUnit,Hamcrest和Mockito在內(nèi)的庫測試Spring Boot應(yīng)用程序的Starter Pom
spring-boot-starter-thymeleaf 使用Thymeleaf視圖構(gòu)建MVC Web應(yīng)用程序的Starter Pom
spring-boot-starter-validation 通過Hibernate Validator使用Java Bean驗證的Starter Pom
spring-boot-starter-web 使用Spring MVC構(gòu)建Web(包括RESTful)應(yīng)用程序的Starter。使用Tomcat作為默認(rèn)的嵌入式容器 Pom
spring-boot-starter-web-services 使用Spring Web Services的Starter Pom
spring-boot-starter-webflux 使用Spring Framework的Reactive Web支持構(gòu)建WebFlux應(yīng)用程序的Starter Pom
spring-boot-starter-websocket 使用Spring Framework的WebSocket支持構(gòu)建WebSocket應(yīng)用程序的Starter Pom

除了應(yīng)用程序啟動程序,以下啟動程序可用于添加生產(chǎn)就緒功能:

Table 2. Spring Boot生產(chǎn)Starter

Name Description Pom
spring-boot-starter-actuator 使用Spring Boot的Actuator的Starter,它提供了生產(chǎn)就緒功能,可幫助您監(jiān)視和管理應(yīng)用程序 Pom

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

Table 3. Spring Boot技術(shù)入門

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,默認(rèn)日志Starter Pom
spring-boot-starter-reactor-netty 使用Reactor Netty作為嵌入式反應(yīng)式HTTP服務(wù)器的Starter Pom
spring-boot-starter-tomcat 用于將Tomcat用作嵌入式Servlet容器Starter,spring-boot-starter-web默認(rèn)使用的servlet容器Starter Pom
spring-boot-starter-undertow 使用Undertow作為嵌入式servlet容器的Starter,spring-boot-starter-tomcat的替代品 Pom

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

3.2 結(jié)構(gòu)化代碼

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

3.2.1 使用默認(rèn)包

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

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

3.2.2 放置應(yīng)用程序主類

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

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

下面列出了一個經(jīng)典的布局

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。

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

3.3.1 導(dǎo)入額外的配置類

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

3.3.2 導(dǎo)入XML配置

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

3.4 自動配置

Spring Boot的自動配置會嘗試根據(jù)你導(dǎo)入的依賴來自動配置你的應(yīng)用。例如,如果HSQLDB在你的類路徑中,但你并沒有手動配置任何數(shù)據(jù)庫連接Bean,那么Spring Boot會自動配置一個內(nèi)存型數(shù)據(jù)庫。

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

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

3.4.1 逐漸取代自動配置

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

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

3.4.2 關(guān)閉特定的配置類

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

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屬性控制要排除的自動配置類的列表。

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

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

3.5 SpringBean和依賴注入

你可以自由的選擇使用標(biāo)準(zhǔn)Spring Framework技術(shù)來定義你的Bean和依賴注入。為簡單起見,我們發(fā)現(xiàn)使用@ComponentScan(掃描你的Bean)和@Autowired(用來構(gòu)造器注入)效果很好。

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

以下示例顯示了一個@Service Bean,它使用構(gòu)造函數(shù)注入來獲取所需的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具有一個構(gòu)造函數(shù),則可以省略@Autowired,如以下示例所示:

@Service
public class DatabaseAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

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

    // ...

}

請注意,使用構(gòu)造函數(shù)注入使riskAssessor字段被標(biāo)記為final,表明它隨后無法更改。

3.6 使用@SpringBootApplication注解

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

  • @EnableAutoConfiguration 開啟Spring Boot的自動配置機制
  • @ComponentScan:在應(yīng)用程序所在的軟件包上啟用@Component掃描(請參閱最佳實踐
  • @Configuration 允許注入額外的Bean到上下文中或?qū)腩~外的配置類。
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的屬性。

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

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注釋的類并且顯式導(dǎo)入用戶定義的Bean外,Application就像其他任何Spring Boot應(yīng)用程序一樣(請參閱@Import)。

3.7 運行你的應(yīng)用

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

3.7.1 在IDE中運行你的應(yīng)用

你可以像一個簡單的Java應(yīng)用一樣在IDE中運行Spring Boo,但是你首先需要導(dǎo)入你的項目,導(dǎo)入過程根據(jù)你的IDE和構(gòu)建系統(tǒng)有所區(qū)別。大多數(shù)IDE可以直接導(dǎo)入Maven工程,例如,Eclipse用戶可以從File菜單中選擇Import->Existing Maven Projects導(dǎo)入。

如果你不能將應(yīng)用直接導(dǎo)入你的IDE,你可能需要用構(gòu)建插件來生成IDE元數(shù)據(jù)。Maven包含了Eclipse和IDEA的插件,Gradle也同樣為一些IDE提供了插件。

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

3.7.2 運行打包后的程序

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

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

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

 $ 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插件包含了一個運行的目標(biāo),可以來快速的編譯運行你的應(yīng)用。應(yīng)用可以像在IDE中一樣以一種暴露的方式運行。下面的示例展示了一個用經(jīng)典的Maven命令來運行應(yīng)用:

 $ mvn spring-boot:run

您可能還想使用MAVEN_OPTS操作系統(tǒng)環(huán)境變量,如以下示例所示:

 $ export MAVEN_OPTS=-Xmx1024m

3.7.4 使用Gradle插件

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

 $ gradle bootRun

您可能還想使用JAVA_OPTS操作系統(tǒng)環(huán)境變量,如以下示例所示:

 $ export JAVA_OPTS=-Xmx1024m

3.7.5 熱交換

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

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

3.8 DevTools

Spring Boot包括一組額外的工具,這些工具可以使應(yīng)用程序開發(fā)體驗更加愉快。spring-boot-devtools模塊可以添加到任何的工程中來提供額外的開發(fā)時特性。要包括devtools支持,請將模塊依賴項添加到您的構(gòu)建中,如以下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")
}

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

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

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

3.8.1 默認(rèn)屬性

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

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

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

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

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

有關(guān)devtools應(yīng)用的屬性的完整列表,請參見DevToolsPropertyDefaultsPostProcessor

3.8.2 啟動重啟

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

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

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

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

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

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

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

                                                     重啟VS重加載

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

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

記錄條件評估中的更改

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

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

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

排除資源

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

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

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

監(jiān)測額外路徑

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

關(guān)閉重啟

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

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

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

使用觸發(fā)文件

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

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

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

例如,如果您的項目具有以下結(jié)構(gòu):

src
+- main
   +- resources
      +- .reloadtrigger

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

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

現(xiàn)在重啟只會在src/main/resources/.reloadtrigger文件更新是發(fā)生

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

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

定制Restart類加載器

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

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

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

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

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

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

已知局限性

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

如果您不想在應(yīng)用程序運行時啟動LiveReload服務(wù),則可以將spring.devtools.livereload.enabled屬性設(shè)置為false。

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

3.8.4 全局設(shè)置

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

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

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

~/.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上的應(yīng)用程序共享devtools全局配置。

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

3.8.5 遠程應(yīng)用

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

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

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

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

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

運行遠程客戶端應(yīng)用

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

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

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

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

  .   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: 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)

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

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

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

遠程更新

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

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

配置文件系統(tǒng)觀察器

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

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

如果您經(jīng)常觀察到此類問題,請嘗試將spring.devtools.restart.poll-interval和spring.devtools.restart.quiet-period參數(shù)增加到適合您的開發(fā)環(huán)境的值:

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

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

3.9 打包您的生產(chǎn)應(yīng)用

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

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

3.10 接下來閱讀什么

現(xiàn)在,您應(yīng)該了解如何使用Spring Boot以及應(yīng)遵循的一些最佳實踐。 現(xiàn)在,您可以繼續(xù)深入了解特定的Spring Boot功能,或者可以跳過并閱讀有關(guān)Spring Boot的“生產(chǎn)就緒”方面的信息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容