第5章 Spring Boot 功能

Spring Boot 功能

      本節將會介紹Spring Boot的一些細節。 在這裏,您能夠了解您將要使用和自定義的主要功能。 若是尚未準備好,您可能須要閱讀第二部分「入門指南」和第三部分「使用 Spring Boot」部分,以使您有基礎的良好基礎。css

23. SpringApplication

SpringApplication類提供了一種方便的方法來引導將從main()方法啓動的Spring應用程序。 在許多狀況下,您只需委派靜態SpringApplication.run()方法:html

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

當您的應用程序啓動時,您應該看到相似於如下內容:java

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v1.5.2.RELEASE

2013-07-31 00:08:16.117 INFO 56603 --- [ main] o.s.b.s.app.SampleApplication : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2013-07-31 00:08:16.166 INFO 56603 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2014-03-04 13:09:54.912 INFO 41370 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080
2014-03-04 13:09:56.501 INFO 41370 --- [ main] o.s.b.s.app.SampleApplication : Started SampleApplication in 2.992 seconds (JVM running for 3.658)

默認狀況下,將顯示INFO 級別log消息,包括用戶啓動應用程序一些相關的啓動細節。mysql

23.1 啓動失敗

若是您的應用程序沒法啓動,則註冊的FailureAnalyzers會提供專門的錯誤消息和具體操做來解決問題。 例如,若是您在端口8080上啓動Web應用程序,而且該端口已在使用中,則應該會看到相似於如下內容的內容:jquery

***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

Spring Boot提供了衆多的FailureAnalyzer實現,您能夠很是容易地添加本身的實現git

若是沒有故障分析器(analyzers)可以處理異常,您仍然能夠顯示完整的自動配置報告,以更好地瞭解出現的問題。 爲此,您須要啓用debug屬性或啓用org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer的DEBUG日誌github

例如,若是使用java -jar運行應用程序,則能夠按以下方式啓用 debug:web

$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

23.2 自定義Banner

能夠經過在您的類路徑中添加一個 banner.txt 文件,或者將banner.location設置到banner文件的位置來更改啓動時打印的banner。 若是文件有一些不經常使用的編碼,你能夠設置banner.charset(默認爲UTF-8)。除了文本文件,您還能夠將banner.gif,banner.jpg或banner.png圖像文件添加到您的類路徑中,或者設置一個banner.image.location屬性。 圖像將被轉換成ASCII藝術表現,並打印在任何文字banner上方。redis

您能夠在banner.txt文件中使用如下佔位符:算法

表23.1. banner變量

變量名 描述
${application.version} 在MANIFEST.MF中聲明的應用程序的版本號。例如, Implementation-Version: 1.0 被打印爲 1.0.
${application.formatted-version} 在MANIFEST.MF中聲明的應用程序版本號的格式化顯示(用括號括起來,以v爲前綴)。 例如 (v1.0)。
${spring-boot.version} 您正在使用的Spring Boot版本。 例如1.5.2.RELEASE。
${spring-boot.formatted-version} 您正在使用格式化顯示的Spring Boot版本(用括號括起來,以v爲前綴)。 例如(v1.5.2.RELEASE)。
Ansi.NAME(or

{AnsiColor.NAME}, AnsiBackground.NAME,

{AnsiStyle.NAME}) 其中NAME是ANSI轉義碼的名稱。 有關詳細信息,請參閱 AnsiPropertySource
${application.title} 您的應用程序的標題在MANIFEST.MF中聲明。 例如Implementation-Title:MyApp打印爲MyApp。

若是要以編程方式生成banner,則可使用SpringApplication.setBanner()方法。 使用org.springframework.boot.Banner 如接口,並實現本身的printBanner() 方法。

您還可使用spring.main.banner-mode屬性來決定是否必須在System.out(控制檯)上打印banner,使用配置的logger(log)或不打印(off)。

23.3 定製SpringApplication

若是SpringApplication默認值不符合您的想法,您能夠建立本地實例並進行自定義。 例如,關閉banner:

public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}

傳遞給SpringApplication的構造函數參數是spring bean的配置源。 在大多數狀況下,這些將引用@Configuration類,但它們也能夠引用XML配置或應掃描的包。

也可使用application.properties文件配置SpringApplication。 有關詳細信息,請參見第24章「外部配置」

有關配置選項的完整列表,請參閱SpringApplication Javadoc

23.4 流式構建 API

若是您須要構建一個ApplicationContext層次結構(具備父/子關係的多個上下文),或者若是您只想使用「流式(fluent)」構建器API,則可使用SpringApplicationBuilder。

SpringApplicationBuilder容許您鏈式調用多個方法,幷包括容許您建立層次結構的父和子方法。

例如:

new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);

建立ApplicationContext層次結構時有一些限制,例如 Web組件必須包含在子上下文中,而且相同的環境將用於父和子上下文。 有關詳細信息,請參閱SpringApplicationBuilder Javadoc

23.5 Application events and listeners

除了常見的Spring Framework事件(如 ContextRefreshedEvent)以外,SpringApplication還會發送一些其餘應用程序事件。

在建立ApplicationContext以前,實際上觸發了一些事件,所以您不能在@Bean上註冊一個監聽器。 您能夠經過SpringApplication.addListeners(…) 或SpringApplicationBuilder.listeners(…)方法註冊它們。

若是您但願自動註冊這些偵聽器,不管建立應用程序的方式如何,均可以將META-INF / spring.factories文件添加到項目中,並使用org.springframework.context.ApplicationListener引用您的偵聽器。
org.springframework.context.ApplicationListener=com.example.project.MyListener

當您的應用程序運行時,事件按照如下順序發送:

  1. ApplicationStartingEvent在運行開始時發送,但在註冊偵聽器和註冊初始化器以後。
  2. 當已經知道要使用的上下文(context)環境,並在context建立以前,將發送ApplicationEnvironmentPreparedEvent。
  3. ApplicationPreparedEvent在啓動刷新(refresh)以前發送,但在加載了bean定義以後。
  4. ApplicationReadyEvent在刷新以後被髮送,而且處理了任何相關的回調以指示應用程序準備好服務請求。
  5. 若是啓動時發生異常,則發送ApplicationFailedEvent。

通常您不須要使用應用程序事件,但能夠方便地知道它們存在。 在內部,Spring Boot使用事件來處理各類任務。

23.6 Web 環境

SpringApplication將嘗試表明您建立正確類型的ApplicationContext。 默認狀況下,將使用AnnotationConfigApplicationContext或AnnotationConfigEmbeddedWebApplicationContext,具體取決於您是否正在開發Web應用程序。

用於肯定「Web環境」的算法是至關簡單的(基於幾個類的存在)。 若是須要覆蓋默認值,可使用setWebEnvironment(boolean webEnvironment)。

也能夠經過調用setApplicationContextClass() 對ApplicationContext徹底控制。

在JUnit測試中使用SpringApplication時,一般須要調用setWebEnvironment()

23.7 訪問應用程序參數

若是您須要訪問傳遞給SpringApplication.run()的應用程序參數,則能夠注入org.springframework.boot.ApplicationArguments bean。 ApplicationArguments接口提供對原始String []參數以及解析選項和非選項參數的訪問:

import org.springframework.boot.*
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*

@Component
public class MyBean {

@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}

}

Spring Boot還將向Spring Environment 註冊一個CommandLinePropertySource。 這容許您也使用@Value註解注入應用程序參數。

23.8 使用ApplicationRunner或CommandLineRunner

SpringApplication啓動時若是您須要運行一些特定的代碼,就能夠實現ApplicationRunner或CommandLineRunner接口。 兩個接口都以相同的方式工做,並提供一個單獨的運行方法,這將在SpringApplication.run(…)完成以前調用。

CommandLineRunner接口提供對應用程序參數的訪問(簡單的字符串數組),而ApplicationRunner使用上述的ApplicationArguments接口。

@Component
public class MyBean implements CommandLineRunner {

public void run(String... args) {
// Do something...
}

}

若是定義了若干CommandLineRunner或ApplicationRunner bean,這些bean必須按特定順序調用,您能夠實現org.springframework.core.Ordered接口,也可使用org.springframework.core.annotation.Order註解。

23.9 Application exit

每一個SpringApplication將註冊一個JVM關閉鉤子,以確保ApplicationContext在退出時正常關閉。 可使用全部標準的Spring生命週期回調(例如DisposableBean接口或@PreDestroy註釋)。

另外,若是但願在應用程序結束時返回特定的退出代碼,那麼bean能夠實現org.springframework.boot.ExitCodeGenerator接口。

23.10 管理功能

能夠經過指定spring.application.admin.enabled屬性來爲應用程序啓用與管理相關的功能。 這會在平臺MBeanServer上暴露SpringApplicationAdminMXBean。 您可使用此功能來遠程管理您的Spring Boot應用程序。 這對於任何服務包裝器(service wrapper)實現也是有用的。

若是您想知道應用程序在哪一個HTTP端口上運行,請使用local.server.port鍵獲取該屬性。

啓用此功能時請當心,由於MBean公開了關閉應用程序的方法。

24. 外部配置

Spring Boot容許您外部化您的配置,以便您能夠在不一樣的環境中使用相同的應用程序代碼。 您可使用properties文件,YAML文件,環境變量和命令行參數來外部化配置。 可使用@Value註釋將屬性值直接注入到您的bean中,該註釋可經過Spring環境(Environment)抽象訪問,或經過@ConfigurationProperties綁定到結構化對象

Spring Boot使用很是特別的PropertySource命令,旨在容許合理地覆蓋值。屬性按如下順序選擇:

  1. 在您的HOME目錄設置的Devtools全局屬性(~/.spring-boot-devtools.properties)。
  2. 單元測試中的 @TestPropertySource 註解。
  3. 單元測試中的 @SpringBootTest#properties 註解屬性
  4. 命令行參數。
  5. SPRING_APPLICATION_JSON 中的屬性值(內嵌JSON嵌入到環境變量或系統屬性中)。
  6. ServletConfig 初始化參數。
  7. ServletContext 初始化參數。
  8. 來自 java:comp/env 的JNDI屬性。
  9. Java系統屬性(System.getProperties())。
  10. 操做系統環境變量。
  11. RandomValuePropertySource,只有隨機的屬性 random.* 中。
  12. jar包外面的 Profile-specific application properties (application- {profile} .properties和YAML變體)
  13. jar包內的 Profile-specific application properties (application-{profile}.properties和YAML變體)
  14. jar包外的應用屬性文件(application.properties和YAML變體)。
  15. jar包內的應用屬性文件(application.properties和YAML變體)。
  16. 在@Configuration上的@PropertySource註解。
  17. 默認屬性(使用SpringApplication.setDefaultProperties設置)。

一個具體的例子,假設你開發一個使用name屬性的@Component:

import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {

@Value("${name}")
private String name;

// ...

}

在應用程序類路徑(例如,您的jar中)中,您能夠擁有一個application.properties,它爲 name 屬性提供了默認屬性值。 在新環境中運行時,能夠在您的jar外部提供一個application.properties來覆蓋 name 屬性; 對於一次性測試,您可使用特定的命令行開關啓動(例如,java -jar app.jar –name=」Spring」)。

SPRING_APPLICATION_JSON屬性能夠在命令行中提供一個環境變量。 例如在UN*X shell中:

$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar

在本例中,您將在Spring環境中使用foo.bar = spam。 您也能夠在系統變量中將JSON做爲spring.application.json提供:

$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar

或命令行參數:

$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'

或做爲JNDI變量 java:comp/env/spring.application.json 。

24.1 配置隨機值

RandomValuePropertySource可用於注入隨機值(例如,進入祕密或測試用例)。 它能夠產生整數,長整數,uuid或字符串,例如

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

random.int *語法是 OPEN value (,max) CLOSE ,其中OPEN,CLOSE是任何字符和值,max是整數。 若是提供max,則值爲最小值,max爲最大值(獨佔)。

24.2 訪問命令行屬性

默認狀況下,SpringApplication將任何命令行選項參數(以’– ‘開頭,例如–server.port=9000)轉換爲屬性,並將其添加到Spring環境中。 如上所述,命令行屬性始終優先於其餘屬性來源。

若是不但願將命令行屬性添加到環境中,可使用SpringApplication.setAddCommandLineProperties(false)禁用它們。

24.3 應用程序屬性文件

SpringApplication將從如下位置的application.properties文件中加載屬性,並將它們添加到Spring Environment中:

  1. 當前目錄的/config子目錄
  2. 當前目錄
  3. classpath中/config包
  4. classpath root路徑

該列表按優先級從高到低排序。

也能夠使用YAML(’.yml’)文件替代「.properties」。

若是您不喜歡application.properties做爲配置文件名,能夠經過指定一個spring.config.name Spring environment屬性來切換到另外一個。 您還可使用spring.config.location環境屬性(用逗號分隔的目錄位置列表或文件路徑)顯式引用位置。

$ java -jar myproject.jar --spring.config.name=myproject

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

spring.config.name和spring.config.location一開始就被用於肯定哪些文件必須被加載,所以必須將它們定義爲環境屬性(一般是OS env,system屬性或命令行參數)。

若是spring.config.location包含的若是是目錄而非文件,那麼它們應該以/結尾(並將在加載以前附加從spring.config.name生成的名稱,包括profile-specific的文件名)。 在spring.config.location中指定的文件按原樣使用,不支持特定於配置文件的變體,而且將被任何特定於配置文件的屬性覆蓋。

默認的搜索路徑 classpath:,classpath:/config,file:,file:config/ 始終會被搜索,無論spring.config.location的值如何。 該搜索路徑從優先級排序從低到高(file:config/最高)。 若是您指定本身的位置,則它們優先於全部默認位置,並使用相同的從最低到最高優先級排序。 這樣,您能夠在application.properties(或使用spring.config.name選擇的任何其餘基礎名稱)中爲應用程序設置默認值,並在運行時使用不一樣的文件覆蓋它,並保留默認值。

若是您使用環境(environment)變量而不是系統屬性,大多數操做系統不容許使用句點分隔(period-separated)的鍵名稱,但可使用下劃線(例如,SPRING_CONFIG_NAME,而不是spring.config.name)

若是您運行在容器中,則可使用JNDI屬性(在 java:comp/env 中)或servlet上下文初始化參數,而不是環境變量或系統屬性。

24.4 指定配置(Profile-specific)的屬性

除了application.properties文件外,還可使用命名約定application- {profile}.properties定義的指定配置文件。 環境具備一組默認配置文件,若是沒有設置活動配置文件(即,若是沒有顯式激活配置文件,則加載了來自application-default.properties的屬性)。

指定配置文件(Profile-specific)的屬性從與標準application.properties相同的位置加載,指定配置( profile-specific)文件始終覆蓋非指定文件,而無論指定配置文件是否在打包的jar內部或外部。

若是有幾個指定配置文件,則應用最後一個配置。 例如,由spring.profiles.active屬性指定的配置文件在經過SpringApplication API配置的配置以後添加,所以優先級高。

若是您在spring.config.location中指定了任何文件,則不會考慮這些特定配置(profile-specific)文件的變體。 若是您還想使用指定配置(profile-specific)文件的屬性,請使用spring.config.location中的目錄。

24.5 properties 文件中的佔位符

application.properties中的值在使用時經過已有的環境進行過濾,以便您能夠引用以前定義的值(例如,從系統屬性)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application

您也可使用此技術建立現有Spring Boot屬性的「簡寫「。 有關詳細信息,請參見第72.4節「使用」短命令行參數「how-to」

24.6 使用YAML替代 Properties

YAML是JSON的超集,所以這是分層配置數據一種很是方便的格式,。 每當您的類路徑中都有SnakeYAML庫時,SpringApplication類將自動支持YAML做爲 properties 的替代方法。

若是您使用「Starters」,SnakeYAML將經過spring-boot-starter自動提供。

24.6.1 加載 YAML

Spring Framework提供了兩個方便的類,可用於加載YAML文檔。 YamlPropertiesFactoryBean將YAML做爲Properties加載,YamlMapFactoryBean將YAML做爲Map加載。

例如,下面YAML文檔:

environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App

將轉化爲屬性:

environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App

YAML列表表示爲具備[index] dereferencers的屬性鍵,例如YAML:

my:
servers:
- dev.bar.com
- foo.bar.com

將轉化爲屬性:

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

要使用Spring DataBinder工具(@ConfigurationProperties作的)綁定到這樣的屬性,您須要有一個屬性類型爲java.util.List(或Set)的目標bean,而且您須要提供一個setter,或者 用可變值初始化它,例如 這將綁定到上面的屬性

@ConfigurationProperties(prefix="my")
public class Config {

private List<String> servers = new ArrayList<String>();

public List<String> getServers() {
return this.servers;
}
}

24.6.2 將YAML做爲Spring環境中的屬性文件

可使用YamlPropertySourceLoader類在Spring環境中將YAML做爲PropertySource暴露出來。 這容許您使用熟悉的@Value註解和佔位符語法來訪問YAML屬性。

24.6.3 多個YAML文件

您可使用spring.profiles鍵指定單個文件中的多個特定配置文件YAML文檔,以指示文檔什麼時候應用。 例如:

server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
server:
address: 192.168.1.120

在上面的示例中,若是開發配置文件處於活動狀態,則server.address屬性將爲127.0.0.1。 若是開發和生產配置文件未啓用,則該屬性的值將爲192.168.1.100。

若是應用程序上下文啓動時沒有顯式激活,默認配置文件將被激活。 因此在這個YAML中,咱們爲security.user.password設置一個僅在「默認」配置文件中可用的值:

server:
port: 8000
---
spring:
profiles: default
security:
user:
password: weak

使用「spring.profiles」元素指定的Spring profiles 以選擇使用 字符。 若是爲單個文檔指定了否認和非否認的配置文件,則至少有一個非否認配置文件必須匹配,沒有否認配置文件可能匹配。

24.6.4 YAML的缺點

YAML文件沒法經過@PropertySource註解加載。 所以,在須要以這種方式加載值的狀況下,須要使用properties文件。

24.6.5 合併YAML列表

如上所述,任何YAML內容最終都會轉換爲屬性。 當經過配置文件覆蓋「列表」屬性時,該過程可能比較直觀。

例如,假設名稱和描述屬性默認爲空的MyPojo對象。 讓咱們從FooProperties中公開MyPojo的列表:

@ConfigurationProperties("foo")
public class FooProperties {

private final List<MyPojo> list = new ArrayList<>();

public List<MyPojo> getList() {
return this.list;
}

}

類比如下配置:

foo:
list:
- name: my name
description: my description
---
spring:
profiles: dev
foo:
list:
- name: my another name

若是dev配置沒有激活,FooProperties.list將包含一個如上定義的MyPojo條目。 若是啓用了配置文件,列表仍將包含一個條目(名稱爲「my another name」,description=null)。 此配置不會將第二個MyPojo實例添加到列表中,而且不會將項目合併。

當在多個配置文件中指定集合時,使用具備最高優先級的集合(而且僅使用該配置文件):

foo:
list:
- name: my name
description: my description
- name: another name
description: another description
---
spring:
profiles: dev
foo:
list:
- name: my another name

在上面的示例中,考慮到dev配置文件處於激活狀態,FooProperties.list將包含一個MyPojo條目(名稱爲「my another name」和description=null)。

24.7 類型安全的配置屬性

使用@Value(「${property}」)註釋來注入配置屬性有時可能很麻煩,特別是若是您正在使用多個層次結構的屬性或數據時。 Spring Boot提供了一種處理屬性的替代方法,容許強類型Bean管理並驗證應用程序的配置。

package com.example;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("foo")
public class FooProperties {

private boolean enabled;

private InetAddress remoteAddress;

private final Security security = new Security();

public boolean isEnabled() { ... }

public void setEnabled(boolean enabled) { ... }

public InetAddress getRemoteAddress() { ... }

public void setRemoteAddress(InetAddress remoteAddress) { ... }

public Security getSecurity() { ... }

public static class Security {

private String username;

private String password;

private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

public String getUsername() { ... }

public void setUsername(String username) { ... }

public String getPassword() { ... }

public void setPassword(String password) { ... }

public List<String> getRoles() { ... }

public void setRoles(List<String> roles) { ... }

}
}

上述POJO定義瞭如下屬性:

  • foo.enabled,默認爲false
  • foo.remote-address,具備能夠從String強轉的類型
  • foo.security.username,具備內置的「安全性(security)」,其名稱由屬性名稱決定。 特別是返回類型並無被使用,多是SecurityProperties
  • foo.security.password
  • foo.security.roles,一個String集合

Getters和setter方法一般是必需要有的,由於綁定是經過標準的Java Beans屬性描述符,就像在Spring MVC中同樣。 在某些狀況下可能會省略setter方法:

  • Map 只要它們被初始化,須要一個getter,但不必定是一個setter,由於它們能夠被binder修改。
  • 集合和數組能夠經過索引(一般使用YAML)或使用單個逗號分隔值(Properties中)來訪問。 在後一種狀況下,setter方法是強制性的。 咱們建議老是爲這樣的類型添加一個設置器。 若是您初始化集合,請確保它不是不可變的(如上例所示)
  • 若是已初始化嵌套POJO屬性(如上例中的Security字段),則不須要setter方法。若是您但願binder使用其默認構造函數即時建立實例,則須要一個setter。

有些人使用Project Lombok自動添加getter和setter。 確保Lombok不會爲這種類型生成任何特定的構造函數,由於構造函將被容器自動用於實例化對象。

另請參閱@Value和@ConfigurationProperties之間的不一樣

您還須要列出在@EnableConfigurationProperties註解中註冊的屬性類:

@Configuration
@EnableConfigurationProperties(FooProperties.class)
public class MyConfiguration {
}

@ConfigurationProperties bean以這種方式註冊時,該bean將具備常規名稱:<prefix> - <fqn>,其中是@ConfigurationProperties註解中指定的環境密鑰前綴,是bean的全名(fully qualified name)。 若是註解不提供任何前綴,則僅使用該bean的全名。上面示例中的bean名稱將是foo-com.example.FooProperties。

即便上述配置將爲FooProperties建立一個常規bean,咱們建議@ConfigurationProperties僅處理環境,特別是不從上下文中注入其餘bean。 話雖如此,@EnableConfigurationProperties註釋也會自動應用於您的項目,以便使用@ConfigurationProperties註釋的任何現有的bean都將從環境配置。 您能夠經過確保FooProperties已是一個bean來快速上面的MyConfiguration

@Component
@ConfigurationProperties(prefix="foo")
public class FooProperties {

// ... see above

}

這種配置方式與SpringApplication外部的YAML配置至關:

# application.yml

foo:
remote-address: 192.168.1.1
security:
username: foo
roles:
- USER
- ADMIN

# additional configuration as required

要使用@ConfigurationProperties bean,您能夠像其餘任何bean同樣注入它們。

@Service
public class MyService {

private final FooProperties properties;

@Autowired
public MyService(FooProperties properties) {
this.properties = properties;
}

//...

@PostConstruct
public void openConnection() {
Server server = new Server(this.properties.getRemoteAddress());
// ...
}

}

使用@ConfigurationProperties還能夠生成IDE能夠爲本身的密鑰提供自動完成的元數據文件,有關詳細信息,請參見附錄B,配置元數據附錄

24.7.1第三方配置

除了使用@ConfigurationProperties來註解類,還能夠在public @Bean方法中使用它。 當您但願將屬性綁定到不受控制的第三方組件時,這可能特別有用。

@ConfigurationProperties(prefix = "bar")
@Bean
public BarComponent barComponent() {
...
}

使用 bar 前綴定義的任何屬性將以與上述FooProperties示例相似的方式映射到該BarComponent bean。

24.7.2 寬鬆的綁定

Spring Boot使用一些寬鬆的規則將環境屬性綁定到@ConfigurationProperties bean,所以不須要在Environment屬性名稱和bean屬性名稱之間進行徹底匹配。 經常使用的例子是這樣有用的:虛分離(例如上下文路徑綁定到contextPath)和大寫(例如PORT綁定到端口)環境屬性。

例如,給定如下@ConfigurationProperties類:

@ConfigurationProperties(prefix="person")
public class OwnerProperties {

private String firstName;

public String getFirstName() {
return this.firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

}

可使用如下屬性名稱:

表格 24.1. relaxed binding

Property Note
person.firstName 標準駱峯命名法。
person.first-name 虛線符號,推薦用於.properties和.yml文件。
person.first_name 下劃線符號,用於.properties和.yml文件的替代格式。
PERSON_FIRST_NAME 大寫格式 推薦使用系統環境變量時。

24.7.3屬性轉換

當Spring綁定到@ConfigurationProperties bean時,Spring將嘗試將外部應用程序屬性強制爲正確的類型。 若是須要自定義類型轉換,您能夠提供ConversionService bean(使用bean id conversionService)或自定義屬性編輯器(經過CustomEditorConfigurer bean)或自定義轉換器(使用註釋爲@ConfigurationPropertiesBinding的bean定義)。

因爲在應用程序生命週期期間很是早請求此Bean,請確保限制ConversionService正在使用的依賴關係。 一般,您須要的任何依賴關係可能沒法在建立時徹底初始化。 若是配置密鑰強制不須要,只需依賴使用@ConfigurationPropertiesBinding限定的自定義轉換器,就能夠重命名自定義ConversionService。

24.7.4 @ConfigurationProperties驗證

當Spring的@Validated註釋解時,Spring Boot將嘗試驗證@ConfigurationProperties類。 您能夠直接在配置類上使用JSR-303 javax.validation約束註釋。 只需確保您的類路徑中符合JSR-303實現,而後在您的字段中添加約束註釋:

@ConfigurationProperties(prefix="foo")
@Validated
public class FooProperties {

@NotNull
private InetAddress remoteAddress;

// ... getters and setters

}

爲了驗證嵌套屬性的值,您必須將關聯字段註釋爲@Valid以觸發其驗證。 例如,基於上述FooProperties示例:

@ConfigurationProperties(prefix="connection")
@Validated
public class FooProperties {

@NotNull
private InetAddress remoteAddress;

@Valid
private final Security security = new Security();

// ... getters and setters

public static class Security {

@NotEmpty
public String username;

// ... getters and setters

}

}

您還能夠經過建立名爲configurationPropertiesValidator的bean定義來添加自定義的Spring Validator。 @Bean方法應聲明爲static。 配置屬性驗證器在應用程序的生命週期早期建立,並聲明@Bean方法,由於static容許建立bean,而無需實例化@Configuration類。 這避免了早期實例化可能引發的任何問題。 這裏有一個屬性驗證的例子,因此你能夠看到如何設置。

spring-boot-actuator模塊包括一個暴露全部@ConfigurationProperties bean的端點。 只需將您的Web瀏覽器指向/configprops 或使用等效的JMX端點。 請參閱生產就緒功能 細節。

24.7.5 @ConfigurationProperties 對比 @Value

@Value是核心容器功能,它不提供與類型安全配置屬性相同的功能。 下表總結了@ConfigurationProperties和@Value支持的功能:

功能 @ConfigurationProperties @Value
Relaxed binding Yes No
Meta-data support Yes No
SpEL evaluation No Yes

若是您爲本身的組件定義了一組配置密鑰,咱們建議您將其分組到使用@ConfigurationProperties註釋的POJO中。 還請注意,因爲@Value不支持寬鬆的綁定,若是您須要使用環境變量提供值,那麼它不是一個很好的選擇。

最後,當您能夠在@Value中編寫一個Spel表達式時,這些表達式不會從應用程序屬性文件中處理。

25. 配置文件(Profiles)

Spring 配置文件提供了將應用程序配置隔離的方法,使其僅在某些環境中可用。 任何@Component或@Configuration均可以使用@Profile進行標記,以限制其在何時加載:

@Configuration
@Profile("production")
public class ProductionConfiguration {

// ...

}

通常,您可使用spring.profiles.active Environment屬性來指定哪些配置文件處於激活狀態。 您能夠以任何方式指定屬性,例如,您能夠將其包含在您的application.properties中:

spring.profiles.active=dev,hsqldb

或者使用命令行--spring.profiles.active=dev,hsqldb在命令行中指定。

25.1添加激活配置文件

spring.profiles.active屬性遵循與其餘屬性相同的優先級規則,PropertySource最高。這意味着您能夠在application.properties中指定活動配置文件,而後使用命令行開關替換它們。

有時,將特定於配置文件的屬性添加到激活的配置文件而不是替換它們是有用的。 spring.profiles.include屬性可用於無條件添加激活配置文件。 SpringApplication入口點還具備用於設置其餘配置文件的Java API(即,在由spring.profiles.active屬性激活的那些配置文件之上):請參閱setAdditionalProfiles()方法。

例如,當使用開關 -spring.profiles.active=prod 運行具備如下屬性的應用程序時,proddb和prodmq配置文件也將被激活:

---
my.property: fromyamlfile
---
spring.profiles: prod
spring.profiles.include:
- proddb
- prodmq

請記住,能夠在YAML文檔中定義spring.profiles屬性,以肯定此特定文檔什麼時候包含在配置中。 有關詳細信息,請參見第72.7節「根據環境更改配置」

25.2 以編程方式設置配置文件

您能夠經過在應用程序運行以前調用SpringApplication.setAdditionalProfiles(…)以編程方式設置激活配置文件。 也可使用Spring的ConfigurableEnvironment接口激活配置文件。

25.3 配置文件指定的配置文件

經過@ConfigurationProperties引用的application.properties(或application.yml)和文件的配置文件特定變體都被視爲加載文件。 有關詳細信息,請參見第24.4節指定配置(Profile-specific)的屬性」

26. 日誌

Spring Boot使用Commons Logging進行全部內部日誌記錄,但使基礎日誌實現開放。 默認配置提供了Java Util LoggingLog4J2Logback。 在每種狀況下,記錄器都預先配置爲使用控制檯輸出和可選文件輸出均可用。

默認狀況下,若是使用’Starters’,將會使用Logback。 還包括適當的Logback路由,以確保使用Java Util Logging,Commons Logging,Log4J或SLF4J的依賴庫都能正常工做。

有不少可用於Java的日誌記錄框架。 若是上面的列表看起來很混亂,別擔憂。 通常來講,您不須要更改日誌依賴關係,而且Spring Boot默認值將正常工做。

26.1 日誌格式

Spring Boot的默認日誌輸出以下所示:

2014-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

輸出如下項目:

  • 日期和時間 - 毫秒精度而且容易排序。
  • 日誌級別 - ERROR, WARN, INFO, DEBUG, TRACE.
  • 進程ID。
  • —分隔符來區分實際日誌消息的開始。
  • 線程名稱 - 括在方括號中(可能會截斷控制檯輸出)。
  • 記錄器名稱 - 這一般是源類名(一般縮寫)。
  • 日誌消息。

Logback沒有FATAL級別(對映ERROR)

26.2 控制檯輸出

默認的日誌配置會在控制檯顯示消息。 默認狀況下會記錄ERROR,WARN和INFO級別的消息。 您還能夠經過–debug啓動您的應用程序來啓用「debug」模式。

$ java -jar myapp.jar --debug

您還能夠在application.properties中指定debug=true。

當啓用debug模式時,配置核心記錄器(嵌入式容器,Hibernate和Spring Boot)的選擇能夠輸出更多信息。 啓用debug 模式不會將應用程序配置爲使用DEBUG級別記錄全部消息。

或者,您可使用–trace啓動應用程序(或在您的application.properties中爲trace=true)啓用「trace」模式。 這將爲核心記錄器(嵌入式容器,Hibernate模式生成和整個Spring組合)啓用trace日誌。

26.2.1 日誌顏色輸出

若是您的終端支持ANSI,顏色輸出能夠增長可讀性。 您能夠將spring.output.ansi.enabled設置爲支持的值來覆蓋自動檢測。

使用%clr關鍵字配置顏色編碼。 在最簡單的形式下,轉換器將根據日誌級別對輸出進行着色,例如:

%clr(%5p)

日誌級別映射到顏色以下:

  • blue
  • cyan
  • faint
  • green
  • magenta
  • red
  • yellow

26.3 文件輸出

默認狀況下,Spring Boot將僅將日誌輸出到控制檯,不會寫到文件。 若是要將控制檯上的日誌輸出到日誌文件,則須要設置logging.file或logging.path屬性(例如在application.properties中)。

下表顯示瞭如何一塊兒使用logging.*屬性:

表26.1 Logging屬性

logging.file logging.path Example Description
(none) (none)   僅控制檯輸出
Specific file (none) my.log 寫入指定的日誌文件。 名稱能夠是確切的位置或相對於當前目錄。
(none) Specific directory /var/log 將spring.log寫入指定的目錄。 名稱能夠是確切的位置或相對於當前目錄。

日誌文件將在10 MB時滾動輸出到文件,默認狀況下會記錄控制檯輸出,ERROR,WARN和INFO級別的消息。

日誌記錄系統在應用程序生命週期早期初始化,而且在經過@PropertySource註解加載的屬性文件中將不會找到log屬性

日誌屬性獨立於實際的日誌記錄基礎結構。 所以,特定配置key(如Logback的logback.configurationFile)不受Spring Boot管理。

26.4 日誌級別

全部支持的日誌記錄系統均可以在Spring Environment 中設置log級別(例如在application.properties中),使用‘logging.level.*=LEVEL’,其中’LEVEL’是TRACE,DEBUG,INFO,WARN,ERROR,FATAL, OFF之一。 可使用logging.level.root配置根記錄器。 示例application.properties:

logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

默認狀況下,Spring Boot會從新啓動Thymeleaf INFO消息,以便它們以DEBUG級別進行記錄。 這有助於下降標準日誌輸出中的噪音。 有關如何在本身的配置中應用重映射的詳細信息,請參閱LevelRemappingAppender

26.5 自定義日誌配置

能夠經過在類路徑中包含適當的庫來激活各類日誌系統,並經過在類路徑的根目錄中提供合適的配置文件,或在Spring Environment屬性logging.config指定的位置進一步配置。

您可使用org.springframework.boot.logging.LoggingSystem系統屬性強制Spring Boot使用特定的日誌記錄系統。該值應該是LoggingSystem實現的全名。 您還可使用none值徹底禁用Spring Boot的日誌記錄配置。

因爲在建立ApplicationContext以前初始化日誌,所以沒法在Spring @Configuration文件中控制@PropertySources的日誌記錄。 系統屬性和常規的Spring Boot外部配置文件工做正常。

根據您的日誌記錄系統,將會加載如下文件:

Logging System Customization
Logback logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging) logging.properties

若是可能,咱們建議您使用-spring變體進行日誌記錄配置(例如使用logback-spring.xml而不是logback.xml)。 若是使用標準配置位置,則Spring沒法徹底控制日誌初始化。

Java Util Logging存在已知的類加載問題,從「可執行jar」運行時會致使問題。 咱們建議您儘量避免。

幫助定製一些其餘屬性從Spring環境轉移到系統屬性:

Spring Environment System Property Comments
logging.exception-conversion-word LOG_EXCEPTION_CONVERSION_WORD 記錄異常時使用的轉換字。
logging.file LOG_FILE 若是定義了,則用於默認日誌配置。
logging.path LOG_PATH 若是定義了,則用於默認日誌配置。
logging.pattern.console CONSOLE_LOG_PATTERN 在控制檯上使用的日誌模式(stdout)。 (僅支持默認logback設置。)
logging.pattern.file FILE_LOG_PATTERN 在文件中使用的日誌模式(若是LOG_FILE已啓用)。 (僅支持默認logback設置。)
logging.pattern.level LOG_LEVEL_PATTERN 用於呈現日誌級別的格式(默認%5p)。 (僅支持默認logback設置。)
PID PID 當前進程ID(若是可能的話,當未被定義爲OS環境變量時被發現)。

支持的全部日誌記錄系統在分析其配置文件時能夠查看系統屬性。 有關示例,請參閱spring-boot.jar中的默認配置。

若是要在logging屬性中使用佔位符,則應使用Spring Boot的語法,而不是底層框架的語法。 值得注意的是,若是您使用Logback,您應該使用:做爲屬性名稱與其默認值之間的分隔符,而不是:-

您能夠經過覆蓋LOG_LEVEL_PATTERN(或Logback的log.pattern.level)來添加MDC和其餘ad-hoc內容到日誌行。 例如,若是使用logging.pattern.level = user:%X {user}%5p,則默認日誌格式將包含「user」的MDC條目(若是存在)。

2015-09-30 12:30:04.031 user:juergen INFO 22174 --- [  nio-8080-exec-0] demo.Controller
Handling authenticated request

26.6 Logback擴展

Spring Boot包括大量的Logback擴展,能夠幫助您進行高級配置。 您能夠在logback-spring.xml配置文件中使用這些擴展。

您不能在標準logback.xml配置文件中使用擴展名,由於其加載時間太早。 您須要使用logback-spring.xml或定義logging.config屬性。

擴展名不能與Logback的配置掃描一塊兒使用。 若是您嘗試這樣作,對配置文件進行更改將致使相似於如下記錄之一的錯誤:

ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]

26.6.1 指定配置文件配置

<springProfile>標籤容許您根據活動的Spring配置文件可選地包含或排除配置部分。 配置文件部分支持<configuration>元素在任何位置。 使用name屬性指定哪一個配置文件接受配置。 可使用逗號分隔列表指定多個配置文件。

<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev, staging">
<!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
<!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

26.6.2 環境屬性

標籤容許您從Spring環境中顯示屬性,以便在Logback中使用。 若是您在logback中訪問application.properties文件中的值,這將很是有用。 標籤的工做方式與Logback標準的標籤相似,但不是指定直接值,而是指定屬性的來源(來自Environment)。 若是須要將屬性存儲在本地範圍之外的位置,則可使用scope屬性。 若是在環境中未設置屬性的狀況下須要備用值,則可使用defaultValue屬性。

<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
<remoteHost>${fluentHost}</remoteHost>
...
</appender>

RelaxedPropertyResolver用於訪問Environment屬性。 若是以虛線表示法(my-property-name)指定源,則將嘗試全部寬鬆的變體(myPropertyName,MY_PROPERTY_NAME等)。

27. 開發Web應用程序

Spring Boot很是適合Web應用程序開發。 您可使用嵌入式Tomcat,Jetty或Undertow輕鬆建立自包含的HTTP服務器。 大多數Web應用程序將使用spring-boot-starter-web模塊快速啓動和運行。

若是您還沒有開發Spring Boot Web應用程序,則能夠按照「Hello World!」示例進行操做。 在「入門」部分中的示例。

27.1 「Spring Web MVC框架」

Spring Web MVC框架(一般簡稱爲「Spring MVC」)是一個豐富的「模型視圖控制器」Web框架。 Spring MVC容許您建立特殊的@Controller或@RestController bean來處理傳入的HTTP請求。 您的控制器中的方法將使用@RequestMapping註釋映射到HTTP。

如下是@RestController用於提供JSON數據的典型示例:

@RestController
@RequestMapping(value="/users")
public class MyRestController {

@RequestMapping(value="/{user}", method=RequestMethod.GET)
public User getUser(@PathVariable Long user) {
// ...
}

@RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
List<Customer> getUserCustomers(@PathVariable Long user) {
// ...
}

@RequestMapping(value="/{user}", method=RequestMethod.DELETE)
public User deleteUser(@PathVariable Long user) {
// ...
}

}

Spring MVC是Spring Framework的一部分,詳細信息可在參考文檔中找到。 Spring.io/guide中還有幾個指南可供Spring MVC使用。

27.1.1 Spring MVC自動配置

Spring Boot提供了適用於大多數應用程序的Spring MVC的自動配置。

自動配置在Spring的默認值之上添加如下功能:

  • 包含ContentNegotiatingViewResolver和BeanNameViewResolver bean。
  • 支持提供靜態資源,包括對WebJars的支持(見下文)。
  • Converter,GenericConverter,Formatter beans的自動註冊。
  • 支持HttpMessageConverters(見下文)。
  • 自動註冊MessageCodesResolver(見下文)。
  • 靜態index.html支持。
  • 自定義Favicon支持(見下文)。
  • 自動使用ConfigurableWebBindingInitializer bean(見下文)。

若是要保留Spring Boot MVC功能,而且您只須要添加其餘MVC配置(interceptors, formatters, view, controllers等),你能夠添加本身的WebConfigurerAdapter類型的@Configuration類,但不能使用@EnableWebMvc。 若是要提供自定義的RequestMappingHandlerMapping,RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver實例,您能夠聲明一個提供此類組件的WebMvcRegistrationsAdapter實例。

若是要徹底控制Spring MVC,可使用@EnableWebMvc添加您本身的@Configuration註釋。

27.1.2 HttpMessageConverters

Spring MVC使用HttpMessageConverter接口轉換HTTP請求和響應。 包括一些開箱即用的合理配置,例如對象能夠自動轉換爲JSON(使用Jackson庫)或XML(使用Jackson XML擴展,若是可用,不然使用JAXB)。 字符串默認使用UTF-8進行編碼。

若是須要添加或自定義轉換器,可使用Spring Boot HttpMessageConverter類:

import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration
public class MyConfiguration {

@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = ...
HttpMessageConverter<?> another = ...
return new HttpMessageConverters(additional, another);
}

}

上下文中存在的任何HttpMessageConverter bean將被添加到轉換器列表中。 您也能夠以這種方式覆蓋默認轉換器。

27.1.3 自定義JSON序列化器和反序列化器

若是您使用Jackson序列化和反序列化JSON數據,則可能須要編寫本身的JsonSerializer和JsonDeserializer類。 自定義序列化程序一般經過一個模塊註冊到Jackson,可是Spring Boot提供了一個備用的@JsonComponent註釋,能夠更容易地直接註冊Spring Bean。

您能夠直接在JsonSerializer或JsonDeserializer實現中使用@JsonComponent。 您也能夠將它用於包含序列化器/解串器的類做爲內部類。 例如:

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

public static class Serializer extends JsonSerializer<SomeObject> {
// ...
}

public static class Deserializer extends JsonDeserializer<SomeObject> {
// ...
}

}

ApplicationContext中的全部@JsonComponent bean將自動註冊到Jackson,而且因爲@JsonComponent是使用@Component進行元註解的,因此常規的組件掃描規則適用。

Spring Boot還提供了JsonObjectSerializerJsonObjectDeserializer基類,它們在序列化對象時爲標準的Jackson版本提供了有用的替代方法。 有關詳細信息,請參閱Javadoc。

27.1.4 MessageCodesResolver

Spring MVC有一個生成錯誤代碼的策略,用於從綁定錯誤中提取錯誤消息:MessageCodesResolver。 Spring Boot將爲您建立一個錯誤代碼,若是您設置spring.mvc.message-codes-resolver.format屬性PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE(請參閱DefaultMessageCodesResolver.Format中的枚舉)。

27.1.5 靜態內容

默認狀況下,Spring Boot將從類路徑或ServletContext的根目錄中的名爲/static(或/ public或/resources或/META-INF/resources)的目錄提供靜態內容。 它使用Spring MVC中的ResourceHttpRequestHandler,所以您能夠經過添加本身的WebMvcConfigurerAdapter並覆蓋addResourceHandlers方法來修改該行爲。

在獨立的Web應用程序中,來自容器的默認servlet也被啓用,而且做爲後備,若是Spring決定不處理它,則從ServletContext的根目錄提供內容。 大多數狀況下,這不會發生(除非您修改默認的MVC配置),由於Spring將始終可以經過DispatcherServlet處理請求。

默認狀況下,資源映射到/ ,但能夠經過spring.mvc.static-path-pattern調整。 例如,將全部資源重定位到 /resources/能夠配置以下:

spring.mvc.static-path-pattern=/resources/**

您還可使用spring.resources.static-locations(使用目錄位置列表替換默認值)來自定義靜態資源位置。 若是這樣作,默認歡迎頁面檢測將切換到您的自定義位置,所以,若是在啓動時任何位置都有一個index.html,它將是應用程序的主頁。

除了上述「標準」靜態資源位置以外,還提供了一個特殊狀況,用於Webjars內容。 任何具備/ webjars / **中路徑的資源都將從jar文件中提供,若是它們以Webjars格式打包。

若是您的應用程序將被打包爲jar,請不要使用 src/main/webapp 目錄。 雖然這個目錄是一個通用的標準,但它只適用於war包,若是生成一個jar,它將被大多數構建工具忽略。

Spring Boot還支持Spring MVC提供的高級資源處理功能,容許使用例如緩存靜態資源或使用Webjars的版本無關的URL。

要爲Webjars使用版本無關的URL,只需添加webjars-locator依賴關係便可。而後聲明您的Webjar,以jQuery爲例,如「/webjars/jquery/dist/jquery.min.js」,這將產生「/webjars/jquery/xyz/dist/jquery.min.js」,其中xyz是Webjar版本 。

若是您使用JBoss,則須要聲明webjars-locator-jboss-vfs依賴關係而不是webjars-locator; 不然全部Webjars都將解析爲404。

要使用緩存清除功能,如下配置將爲全部靜態資源配置緩存清除解決方案,從而有效地在URL中添加內容哈希值,例如:

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**

連接資源在運行時在模板中被重寫,這歸功於自動配置爲Thymeleaf和FreeMarker的ResourceUrlEncodingFilter。 使用JSP時,應手動聲明此過濾器。 其餘模板引擎如今不會自動支持,但可使用自定義模板宏/幫助程序和使用ResourceUrlProvider

當使用例如JavaScript模塊加載器動態加載資源時,重命名文件不是一個選項。這就是爲何其餘策略也獲得支持並能夠合併的緣由。 「固定(fixed)」策略將在URL中添加靜態版本字符串,而不更改文件名:

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/js/lib/
spring.resources.chain.strategy.fixed.version=v12

使用此配置,位於「/js/lib/」下的JavaScript模塊將使用固定版本策略「/v12/js/lib/mymodule.js」,而其餘資源仍將使用內容。

有關更多支持的選項,請參閱ResourceProperties

此功能已在專門的博客文章和Spring Framework參考文檔中進行了詳細描述。

27.1.6 自定義圖標

Spring Boot在配置的靜態內容位置和類路徑的根目錄(按順序)中查找favicon.ico。 若是文件存在,它將被自動用做應用程序的圖標。

27.1.7 ConfigurableWebBindingInitializer

Spring MVC使用WebBindingInitializer爲特定請求初始化WebDataBinder。 若是您用@Bean建立本身的ConfigurableWebBindingInitializer @Bean,Spring Boot將自動配置Spring MVC以使用它。

27.1.8 模板引擎

除了REST Web服務,您還可使用Spring MVC來提供動態HTML內容。 Spring MVC支持各類模板技術,包括Thymeleaf,FreeMarker和JSP。 許多其餘模板引擎也運行本身的Spring MVC集成。

Spring Boot包括對如下模板引擎的自動配置支持:

若是可能,應避免使用JSP,當使用嵌入式servlet容器時,JSP有幾個已知的限制

當您使用默認配置的模板引擎之一時,您的模板將從 src/main/resources/templates 自動獲取。

IntelliJ IDEA根據運行應用程序的方式對類路徑進行不一樣的排序。 經過main方法在IDE中運行應用程序將致使使用Maven或Gradle打包的jar運行應用程序時的不一樣順序。這可能會致使Spring Boot找不到類路徑上的模板。 若是您受此問題的影響,您能夠從新排序IDE中的類路徑,以放置模塊的類和資源。 或者,您能夠配置模板前綴以搜索類路徑上的每一個模板目錄:classpath*:/templates/

27.1.9 錯誤處理

默認狀況下,Spring Boot提供 /error 映射,以合理的方式處理全部錯誤,並在servlet容器中註冊爲「global」錯誤頁面。 對於機器客戶端,它將產生JSON響應,其中包含錯誤,HTTP狀態和異常消息的詳細信息。 對於瀏覽器客戶端,有一個’whitelabel’錯誤視圖,以HTML格式呈現相同的數據(定製它只需添加一個解析「error」的視圖)。 要徹底替換默認行爲,您能夠實現ErrorController並註冊該類型的bean定義,或者簡單地添加一個類型爲ErrorAttributes的bean來使用現有機制,但只是替換內容。

BasicErrorController能夠用做自定義ErrorController的基類。 若是要添加新內容類型的處理程序(默認狀況下是專門處理text/html併爲其餘內容提供備選),這一點尤爲有用。 要作到這一點,只需擴展BasicErrorController並添加一個帶有@RequestMapping的公共方法,並建立一個新類型的bean。

您還能夠定義一個@ControllerAdvice來自定義爲特定控制器 and/or 異常類型返回的JSON文檔。

@ControllerAdvice(basePackageClasses = FooController.class)
public class FooControllerAdvice extends ResponseEntityExceptionHandler {

@ExceptionHandler(YourException.class)
@ResponseBody
ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
}

private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}

}

在上面的示例中,若是由FooController在同一個包中定義的控件拋出了YourException,則將使用CustomerErrorType POJO的json表示法而不是ErrorAttributes表示形式。

自定義錯誤頁面

若是要顯示給定狀態代碼的自定義HTML錯誤頁面,請將文件添加到/error文件夾。 錯誤頁面能夠是靜態HTML(即添加在任何靜態資源文件夾下)或使用模板構建。 該文件的名稱應該是確切的狀態代碼或一個序列掩碼。

例如,要將404映射到靜態HTML文件,您的文件夾結構將以下所示:

src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>

要使用FreeMarker模板映射全部5xx錯誤,使用以下結構:

src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.ftl
+- <other templates>

對於更復雜的映射,您還能夠添加實現ErrorViewResolver接口的bean。

public class MyErrorViewResolver implements ErrorViewResolver {

@Override
public ModelAndView resolveErrorView(HttpServletRequest request,
HttpStatus status, Map<String, Object> model) {
// Use the request or status to optionally return a ModelAndView
return ...
}

}

您還可使用常規的Spring MVC功能,如@ExceptionHandler方法@ControllerAdvice。 而後,ErrorController將接收任何未處理的異常。

映射Spring MVC以外的錯誤頁面

對於不使用Spring MVC的應用程序,可使用ErrorPageRegistrar接口來直接註冊ErrorPages。這個抽象直接與底層的嵌入式servlet容器一塊兒工做,即便沒有Spring MVC DispatcherServlet也能夠工做。

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
return new MyErrorPageRegistrar();
}

// ...

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
}

}

N.B. 若是您註冊一個最終由Filter過濾的路徑的ErrorPage(例如,像一些非Spring Web框架,例如Jersey和Wicket同樣),則必須將Filter顯式註冊爲ERROR dispatcher,例如。

@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter());
...
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
return registration;
}

(默認的FilterRegistrationBean不包括ERROR dispatcher 類型)。

WebSphere Application Server上的錯誤處理

當部署到servlet容器時,Spring Boot會使用其錯誤頁面過濾器將具備錯誤狀態的請求轉發到相應的錯誤頁面。 若是響應還沒有提交,則該請求只能轉發到正確的錯誤頁面。 默認狀況下,WebSphere Application Server 8.0及更高版本在成功完成servlet的服務方法後提交響應。 您應該經過將com.ibm.ws.webcontainer.invokeFlushAfterService設置爲false來禁用此行爲

27.1.10 Spring HATEOAS

若是您正在開發一種利用超媒體的RESTful API,Spring Boot能夠爲Spring HATEOAS提供自動配置,適用於大多數應用程序。 自動配置取代了使用@EnableHypermediaSupport的需求,並註冊了一些Bean,以便輕鬆構建基於超媒體的應用程序,包括LinkDiscoverers(用於客戶端支持)和配置爲將響應正確地組織到所需表示中的ObjectMapper。 ObjectMapper將根據spring.jackson。*屬性或Jackson2ObjectMapperBuilder bean(若是存在)進行自定義。

您可使用@EnableHypermediaSupport控制Spring HATEOAS配置。 請注意,這將禁用上述ObjectMapper定製。

27.1.11 CORS 支持

跨原始資源共享(CORS)是大多數瀏覽器實現的W3C規範,容許您以靈活的方式指定什麼樣的跨域請求被受權,而不是使用一些不太安全和不太強大的方法,如IFRAME或JSONP。

從版本4.2起,Spring MVC支持CORS開箱即用。 在Spring Boot應用程序中的controller方法使用@CrossOrigin註解的CORS配置不須要任何特定的配置。 能夠經過使用自定義的addCorsMappings(CorsRegistry)方法註冊WebMvcConfigurer bean來定義全局CORS配置:

@Configuration
public class MyConfiguration {

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}

27.2 JAX-RS 和 Jersey

若是您喜歡JAX-RS編程模型的REST endpoints ,您可使用一個可用的實現而不是Spring MVC。 若是您剛剛在應用程序上下文中註冊了一個@Bean的Servlet或Filter,那麼Jersey 1.x和Apache CXF的功能很是出色。 Jersey2.x有一些本地Spring支持,因此咱們也提供自動配置支持它在Spring Boot與啓動器。

要開始使用Jersey 2.x,只需將spring-boot-starter-jersey做爲依賴項,而後您須要一個@Bean類型ResourceConfig,您能夠在其中註冊全部端點(endpoints):

@Component
public class JerseyConfig extends ResourceConfig {

public JerseyConfig() {
register(Endpoint.class);
}

}

Jersey對掃描可執行檔案的包是至關有限的。 例如,當運行可執行的war文件時,它沒法掃描在WEB-INF/classes中找到的包中的端點(endpoints)。 爲了不這種限制,不該使packages方法,而且應使用上述寄存器方法單獨註冊(register)端點。

您還能夠註冊任意數量的ResourceConfigCustomizer的實現bean,以實現更高級的自定義。

全部註冊的端點都應爲具備HTTP資源註解(@GET等)的@Components,例如。

@Component
@Path("/hello")
public class Endpoint {

@GET
public String message() {
return "Hello";
}

}

因爲Endpoint是一個Spring @Component,因此Spring的生命週期由Spring管理,您可使用@Autowired依賴關係並使用@Value注入外部配置。 默認狀況下,Jersey servlet將被註冊並映射到/ *。 您能夠經過將@ApplicationPath添加到ResourceConfig來更改映射。

默認狀況下,Jersey將經過@Bean以名爲jerseyServletRegistration的ServletRegistrationBean類型在Servlet進行設置。 默認狀況下,servlet將被初始化,可是您可使用spring.jersey.servlet.load-on-startup進行自定義。您能夠經過建立一個本身的同名文件來禁用或覆蓋該bean。 您也能夠經過設置spring.jersey.type = filter(在這種狀況下,@Bean來替換或替換爲jerseyFilterRegistration),使用Filter而不是Servlet。 servlet有一個@Order,您可使用spring.jersey.filter.order設置。 可使用spring.jersey.init.* 給出Servlet和過濾器註冊的init參數,以指定屬性的映射。

有一個Jersey示例,因此你能夠看到如何設置。 還有一個Jersey1.x示例。 請注意,在Jersey1.x示例中,spring-boot maven插件已經被配置爲打開一些Jersey jar,以便它們能夠被JAX-RS實現掃描(由於示例要求它們在Filter註冊中進行掃描) 。 若是您的任何JAX-RS資源做爲嵌套的jar打包,您可能須要執行相同操做。

27.3 嵌入式servlet容器支持

Spring Boot包括對嵌入式Tomcat,Jetty和Undertow服務器的支持。 大多數開發人員將簡單地使用適當的「Starter」來獲取徹底配置的實例。 默認狀況下,嵌入式服務器將監聽端口8080上的HTTP請求。

若是您選擇在CentOS上使用Tomcat,請注意,默認狀況下,臨時目錄用於存儲已編譯的JSP,文件上傳等。當您的應用程序正在運行致使故障時,該目錄可能會被tmpwatch刪除。 爲了不這種狀況,您可能須要自定義tmpwatch配置,以便tomcat.*目錄不被刪除,或配置server.tomcat.basedir,以便嵌入式Tomcat使用不一樣的位置

27.3.1 Servlets, Filters 和 listeners

當使用嵌入式servlet容器時,可使用Spring bean或經過掃描Servlet組件(例如HttpSessionListener)註冊Servlet規範中的Servlet,過濾器和全部監聽器。

將Servlets,過濾器和監聽器註冊爲Spring bean

任何Servlet,Filter或Servlet Listener 實例都會做爲Spring bean註冊到嵌入式容器中。 能夠很是方便地在配置過程當中引用您的application.properties中的值。

默認狀況下,若是容器中只包含一個Servlet,它將映射到/。 在多個Servlet bean的狀況下,bean名稱將做爲路徑前綴。 過濾器(Filters)將映射到/*,默認過濾全部請求。

若是基於慣例的映射不夠靈活,可使用ServletRegistrationBean,FilterRegistrationBean和ServletListenerRegistrationBean類來完成控制。

27.3.2 Servlet Context 初始化

嵌入式servlet容器不會直接執行Servlet 3.0+ javax.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口。 這樣設計的目的旨在下降在war中運行的第三方庫破壞Spring Boot應用程序的風險。

若是您須要在Spring Boot應用程序中執行servlet context 初始化,則應註冊一個實現org.springframework.boot.context.embedded.ServletContextInitializer接口的bean。 單個onStartup方法提供對ServletContext的訪問,而且若是須要,能夠輕鬆地用做現有WebApplicationInitializer的適配器。

掃描Servlet,過濾器和監聽器

使用嵌入式容器時,可使用@ServletComponentScan啓用@WebServlet,@WebFilter和@WebListener註解類的自動註冊。

@ServletComponentScan在獨立容器中不起做用,在該容器中將使用容器的內置發現機制。

27.3.3 EmbeddedWebApplicationContext

在Spring Boot引導下,將會使用一種新類型的ApplicationContext來支持嵌入式的servlet容器。 EmbeddedWebApplicationContext是一種特殊類型的WebApplicationContext,它經過搜索單個EmbeddedServletContainerFactory bean來引導自身。 一般,TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory將被自動配置。

您一般不須要知道這些實現類。 大多數應用程序將被自動配置,並將表明您建立適當的ApplicationContext和EmbeddedServletContainerFactory。

27.3.4 定製嵌入式servlet容器

可使用Spring Environment屬性配置常見的servlet容器設置。 一般您能夠在application.properties文件中定義屬性。

經常使用服務器設置包括:

  • 網絡設置:偵聽端口的HTTP請求(server.port),接口地址綁定到server.address等。
  • 會話設置:會話是否持久化(server.session.persistence),會話超時(server.session.timeout),會話數據的位置(server.session.store-dir)和session-cookie配置(server.session.cookie.*)。
  • 錯誤管理:錯誤頁面的位置(server.error.path)等
  • SSL
  • HTTP壓縮

Spring Boot儘量地嘗試公開常見設置,但並不老是可能的。 對於這些狀況,專用命名空間提供服務器特定的定製(請參閱server.tomcat和server.undertow)。 例如,可使用嵌入式servlet容器的特定功能來配置訪問日誌

有關完整列表,請參閱 ServerProperties 類。

用程序定製

若是須要以編程方式配置嵌入式servlet容器,您能夠註冊一個實現EmbeddedServletContainerCustomizer接口的Spring bean。 EmbeddedServletContainerCustomizer提供對ConfigurableEmbeddedServletContainer的訪問,其中包含許多自定義設置方法。

import org.springframework.boot.context.embedded.*;
import org.springframework.stereotype.Component;

@Component
public class CustomizationBean implements EmbeddedServletContainerCustomizer {

@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(9000);
}

}

直接自定義ConfigurableEmbeddedServletContainer

若是上述定製技術有太多限制,您能夠本身註冊TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory bean。

@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setPort(9000);
factory.setSessionTimeout(10, TimeUnit.MINUTES);
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
return factory;
}

setter方法提供了許多配置選項。 若是您須要作更多的自定義,還會提供幾種保護方法「鉤子」。 有關詳細信息,請參閱源代碼文檔。

27.3.5 JSP限制

當運行使用嵌入式servlet容器(並打包爲可執行文檔)的Spring Boot應用程序時,對JSP支持有一些限制。

  • 可使用Tomcat和war包,便可執行的war將會起做用,而且也能夠部署到標準容器(不限於但包括Tomcat)中。 因爲Tomcat中的硬編碼文件模式,可執行的jar將沒法正常工做。
  • 可使用Jetty和war包,便可執行的war將會起做用,而且也能夠部署到任何標準的容器,它應該能夠工做。
  • Undertow不支持JSP。
  • 建立自定義的error.jsp頁面將不會覆蓋默認視圖以進行錯誤處理,而應使用自定義錯誤頁面

28. Security

若是Spring Security位於類路徑上,則默認狀況下,Web應用程序將在全部HTTP端點上使用「basic」身份驗證。 要向Web應用程序添加方法級安全性,您還可使用所需的設置添加@EnableGlobalMethodSecurity。 有關更多信息,請參見「Spring Security Reference」。

默認的AuthenticationManager有一個用戶(用戶名’user’和隨機密碼,在應用程序啓動時以INFO級別打印)

Using default security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35

若是您調整日誌記錄配置,請確保將org.springframework.boot.autoconfigure.security類別設置爲記錄INFO消息,不然將不會打印默認密碼。

您能夠經過提供security.user.password來更改密碼。 這個和其餘有用的屬性經過 SecurityProperties(屬性前綴「security」)進行外部化。

默認的安全配置在SecurityAutoConfiguration和從那裏導入的類中實現(用於Web安全的SpringBootWebSecurityConfiguration和用於認證配置的AuthenticationManagerConfiguration,這在非Web應用程序中也是相關的)。 要徹底關閉默認的Web應用程序安全配置,您可使用@EnableWebSecurity添加一個bean(這不會禁用身份驗證管理器配置或Actuator的安全性)。 要定製它,您一般使用WebSecurityConfigurerAdapter類型的外部屬性和bean(例如添加基於表單的登陸)。 要關閉身份驗證管理器配置,您能夠添加AuthenticationManager類型的bean,或者經過將AuthenticationManagerBuilder自動鏈接到您的一個@Configuration類中的方法來配置全局AuthenticationManager。 Spring Boot示例中有幾個安全應用程序可讓您開始使用常見的用例

您在Web應用程序中得到的基本功能包括:

  • 具備內存存儲和單個用戶的AuthenticationManager Bean(請參閱用於用戶屬性的SecurityProperties.User)。
  • 對於常見的靜態資源位置,忽略(不安全)路徑(/css/**, /js/**, /images/**, /webjars/** and **/favicon.ico)。
  • HTTP全部其餘端點的baseic security 。
  • 安全事件發佈到Spring的ApplicationEventPublisher(成功、不成功的身份驗證、拒絕訪問)。
  • 默認狀況下,Spring Security提供的常見的底層功能(HSTS,XSS,CSRF,緩存)都是打開的。

全部上述可使用外部屬性(security.*)打開、關閉或修改。 要覆蓋訪問規則而不更改任何其餘自動配置的功能,請添加一個帶有@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)的WebSecurityConfigurerAdapter類型的Bean,並配置它以知足您的須要。

默認狀況下,WebSecurityConfigurerAdapter將匹配任何路徑。 若是您不想徹底覆蓋Spring Boot自動配置的訪問規則,您的適配器必須顯式配置您要覆蓋的路徑。

28.1 OAuth2

若是您的類路徑中有spring-security-oauth2,您能夠利用一些自動配置來輕鬆設置受權或資源服務器。 有關完整的詳細信息,請參閱「Spring Security OAuth 2開發人員指南」。

28.1.1 受權服務器

要建立受權服務器並授予訪問令牌,您須要使用@EnableAuthorizationServer並提供security.oauth2.client.client-id和security.oauth2.client.client-secret]屬性。 客戶端將爲您註冊在內存中。

$ curl client:secret@localhost:8080/oauth/token -d grant_type=password -d username=user -d password=pwd

/token 端點的基自己份驗證憑證是client-id和client-secret。 用戶憑據是普通的Spring Security用戶details (在Spring引導中默認爲「user」和隨機密碼)。

要關閉自動配置並自行配置受權服務器功能,只需添加一個類型爲AuthorizationServerConfigurer的@Bean。

28.1.2 資源服務器

要使用訪問令牌(token),您須要一個資源服務器(能夠與受權服務器相同)。 建立資源服務器很簡單,只需添加@EnableResourceServer並提供一些配置,以容許服務器解碼訪問令牌。 若是您的應用程序也是受權服務器,則它已經知道如何解碼令牌,無需作其餘事情。 若是你的應用程序是一個獨立的服務,那麼你須要給它一些更多的配置,如下選項之一:

若是您同時指定user-info-uri和token-info-uri,那麼您能夠設置一個標誌,表示優先於另外一個(prefer-token-inf=true是默認值)。

或者(不是user-info-uri或token-info-uri的狀況)若是令牌是JWT,您能夠配置security.oauth2.resource.jwt.key-value來本地解碼(key是驗證密鑰verification key)。 驗證密鑰值是對稱祕密或PEM編碼的RSA公鑰。 若是您沒有密鑰,而且它是公開的,您能夠提供一個可使用security.oauth2.resource.jwt.key-uri下載的URI(具備「value」字段的JSON對象)。 例如在PWS上:

$ curl https://uaa.run.pivotal.io/token_key
{"alg":"SHA256withRSA","value":"-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----\n"}

若是您使用security.oauth2.resource.jwt.key-uri,則應用程序啓動時須要運行受權服務器。 若是找不到密鑰,它將記錄一個警告,並告訴您如何解決該問題。

若是您使用security.oauth2.resource.jwt.key-uri,則應用程序啓動時須要運行受權服務器。 若是找不到密鑰,它將會在日誌記錄一個警告,並告訴您如何解決該問題。

OAuth2資源由order security.oauth2.resource.filter-order的過濾器鏈保護,默認狀況下保護執行器(actuator)端點的過濾器(因此執行器(actuator)端點將保留在HTTP Basic上,除非更改順序)。

28.2 User Info中的令牌類型

Google和某些其餘第三方身份認證提供商對在header中發送到用戶信息端點的令牌類型名稱更爲嚴格。 默認值爲「Bearer」,適合大多數提供程序並匹配規範,但若是須要更改,能夠設置security.oauth2.resource.token-type。

28.3 自定義用戶信息RestTemplate

若是您有user-info-uri,則資源服務器功能在內部使用OAuth2RestTemplate來獲取用戶身份驗證信息。 這是以UserInfoRestTemplateFactory類型的@Bean提供的。 大多數提供程序的默認值應該是能知足正常使用,但有時您可能須要添加其餘攔截器,或者更改請求驗證器(例如:令牌如何附加到傳出請求)。 進行自定義,只需建立一個類型爲UserInfoRestTemplateCustomizer的bean - 它具備一個方法,在bean建立以後但在初始化以前將被調用。 這裏定製的rest模板只能在內部進行驗證。 或者,您能夠定義本身的UserInfoRestTemplateFactory @Bean來徹底控制。

要在YAML中設置RSA密鑰值,請使用「pipe」繼續標記將其分割成多行(「|」),並記住縮進鍵值(它是標準的 YAML 語言功能)。 例:

security:
oauth2:
resource:
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC...
-----END PUBLIC KEY-----

28.3.1 Client

要使您的 web-app 進入OAuth2客戶端,您能夠簡單地添加@ EnableOAuth2Client,Spring Boot將建立一個OAuth2ClientContext和OAuth2ProtectedResourceDetails,這些是建立OAuth2RestOperations所必需的。 Spring Boot不會自動建立這樣的bean,可是您能夠輕鬆建立本身的bean:

@Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext,
OAuth2ProtectedResourceDetails details) {
return new OAuth2RestTemplate(details, oauth2ClientContext);
}

您可能須要添加限定符並查看您的配置,由於您的應用程序可能會定義多個RestTemplate。

此配置使用security.oauth2.client.*做爲憑據(可能與受權服務器中使用的相同),但另外還須要知道受權服務器中的受權和令牌URI。 例如:

application.yml.

security:
oauth2:
client:
clientId: bd1c0a783ccdd1c9b9e4
clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
accessTokenUri: https://github.com/login/oauth/access_token
userAuthorizationUri: https://github.com/login/oauth/authorize
clientAuthenticationScheme: form

當您嘗試使用OAuth2RestTemplate時,具備此配置的應用程序將重定向到Github進行受權。 若是您已經登陸Github,您甚至不會注意到它已經被認證。 若是您的應用程序在端口8080上運行(在Github或其餘提供商註冊本身的客戶端應用程序以得到更大的靈活性),這些特定的憑據纔會起做用。

要限制客戶端在獲取訪問令牌時要求的範圍,您能夠設置security.oauth2.client.scope(逗號分隔或YAML中的數組)。 默認狀況下,scope是空的,由受權服務器決定其默認值,一般取決於客戶端註冊中的設置。

還有一個security.oauth2.client.client-authentication-scheme的設置,默認爲「header」(可是若是像Github那樣,您可能須要將其設置爲「form」,例如,您的OAuth2提供程序不喜歡header 認證)。 事實上,security.oauth2.client.*屬性綁定到AuthorizationCodeResourceDetails的一個實例,所以能夠指定其全部的屬性。

在非Web應用程序中,您仍然能夠建立一個OAuth2RestOperations,它仍然鏈接到security.oauth2.client.*配置中。 在這種狀況下,它是一個「客戶端憑據令牌授予」,您若是使用它就請求它(而且不須要使用@EnableOAuth2Client或@EnableOAuth2Sso)。爲了防止定義基礎設施,只需從配置中刪除security.oauth2.client.client-id(或使其成爲空字符串)。

28.3.2 單點登陸

OAuth2客戶端可用於從提供商獲取用戶詳細信息(若是此類功能可用),而後將其轉換爲Spring Security的身份驗證令牌。 以上資源服務器經過user-info-uri屬性支持此功能這是基於OAuth2的單點登陸(SSO)協議的基礎,Spring Boot能夠經過提供@ EnableOAuth2Sso註解來輕鬆加入。 上面的Github客戶端能夠經過添加該註釋並聲明在何處查找端點(除了上面列出的security.oauth2.client.*配置)外,還能夠保護全部資源並使用Github/user/endpoint進行身份驗證:

application.yml.

security:
oauth2:
...
resource:
userInfoUri: https://api.github.com/user
preferTokenInfo: false

因爲默認狀況下全部路徑都是安全的,因此沒有能夠向未經身份驗證的用戶顯示「家」頁面,並邀請他們登陸(經過訪問/登陸路徑或由security.oauth2.sso.login-path指定的路徑) 。

因爲默認狀況下全部路徑都是要求安全的,因此沒有能夠向未經身份驗證的用戶顯示「home」頁面,並邀請他們登陸(經過訪問/login 路徑或由security.oauth2.sso.login-path指定的路徑) 。

要自定義保護的訪問規則或路徑,所以您能夠添加「home」頁面,例如,@EnableOAuth2Sso能夠添加到WebSecurityConfigurerAdapter,而且註解將使其被修飾和加強,以使所需的/login路徑能夠工做。 例如,這裏咱們簡單地容許未經身份驗證的訪問「/「下的主頁面,並保留其餘全部內容的默認值:

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
public void init(WebSecurity web) {
web.ignore("/");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();
}

}

28.4 Actuator Security

若是Actuator也在使用中,您會發現:

  • 即便應用程序端點不安全,管理端點也是安全的。
  • Security 事件將轉換爲AuditEvent實例,併發布到AuditEventRepository。
  • 默認用戶將具備ACTUATOR角色以及USER角色。

Actuator的安全功能可使用外部屬性(management.security.*)進行修改。要覆蓋應用程序訪問規則,請添加一個類型爲WebSecurityConfigurerAdapter的@Bean,若是您不想覆蓋執行程序訪問規則,則使用@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)或@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)覆蓋執行器訪問規則。

29. 使用SQL數據庫

Spring Framework 爲使用SQL數據庫提供了普遍的支持。 從使用JdbcTemplate直接JDBC訪問到完成「對象關係映射」技術,如Hibernate。Spring Data提供了額外的功能,直接從接口建立Repository實現,並使用約定從方法名稱生成查詢。

29.1 配置DataSource

Java的javax.sql.DataSource接口提供了使用數據庫鏈接的標準方法。傳統上,DataSource使用URL和一些憑據來創建數據庫鏈接。

還能夠查看更多高級示例的「操做方法」部分,一般能夠徹底控制DataSource的配置。

29.1.1 嵌入式數據庫支持

使用內存中嵌入式數據庫開發應用程序一般很方便。 顯然,內存數據庫不提供持久化存儲; 您的應用程序啓動時,您將須要初始化數據庫,並在應用程序結束時丟棄數據。

「How-to」部分包含如何初始化數據庫

Spring Boot能夠自動配置嵌入式 H2HSQLDerby 數據庫。 您不須要提供任何鏈接URL,只需將要使用的嵌入式數據庫的依賴關係包含進去便可。

若是您在測試中使用此功能,您可能會注意到,整個測試套件都會重複使用相同的數據庫,而無論您使用的應用程序上下文的數量。 若是要確保每一個上下文都有一個單獨的嵌入式數據庫,您應該將spring.datasource.generate-unique-name設置爲true。

例如,典型的POM依賴關係是:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>

對於要自動配置的嵌入式數據庫,您須要依賴spring-jdbc。 在這個例子中,它是經過spring-boot-starter-data-jpa傳遞的。

若是因爲某種緣由配置嵌入式數據庫的鏈接URL,則應注意確保數據庫的自動關閉被禁用。 若是你使用H2,你應該使用DB_CLOSE_ON_EXIT=FALSE這樣作。 若是您使用HSQLDB,則應確保不使用shutdown=true。 禁用數據庫的自動關閉容許Spring Boot控制數據庫什麼時候關閉,從而確保在再也不須要訪問數據庫時發生這種狀況。

29.1.2 鏈接到生產環境數據庫

生產數據庫鏈接也可使用鏈接池數據源自動配置。 這是選擇具體實現的算法:

  • 咱們更喜歡Tomcat鏈接池DataSource的性能和併發性,因此若是可用,咱們老是選擇它。
  • 不然,若是HikariCP可用,咱們將使用它。
  • 若是Tomcat池數據源和HikariCP都不可用,而且若是Commons DBCP可用,咱們將使用它,可是咱們不建議在生產中使用它,而且不支持它。
  • 最後,若是Commons DBCP2可用,咱們將使用它。

若是您使用spring-boot-starter-jdbc或spring-boot-starter-data-jpa 的startters,您將自動得到對tomcat-jdbc的依賴。

您能夠徹底繞過該算法,並經過spring.datasource.type屬性指定要使用的鏈接池。 若是您在Tomcat容器中運行應用程序,則默認狀況下提供tomcat-jdbc,這一點尤其重要。

能夠隨時手動配置其餘鏈接池。若是您定義本身的DataSource bean,則不會發生自動配置。

DataSource配置由spring.datasource中的外部配置屬性控制。 例如,您能夠在application.properties中聲明如下部分:

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

您應至少使用spring.datasource.url屬性指定url,不然Spring Boot將嘗試自動配置嵌入式數據庫。

您一般不須要指定驅動程序類名稱,由於Spring Boot能夠從url爲大多數數據庫推斷出驅動程序名稱。

對於要建立的池數據源,咱們須要可以驗證有效的Driver類是否可用,因此咱們在作任何事情以前檢查它。 即 若是您設置spring.datasource.driver-class-name=com.mysql.jdbc.Driver,那麼該類必須可加載。

有關更多支持的選項,請參閱 DataSourceProperties。 這些是標準選項,不管實際執行狀況如何。 還可使用各自的前綴(spring.datasource.tomcat.*,spring.datasource.hikari.*和spring.datasource.dbcp2.*)微調實現特定的設置。 有關更多詳細信息,請參閱您正在使用的鏈接池實現的文檔。

例如,若是您正在使用Tomcat鏈接池,您能夠自定義許多其餘設置:

# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.tomcat.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=50

# Validate the connection before borrowing it from the pool.
spring.datasource.tomcat.test-on-borrow=true

29.1.3 鏈接到JNDI DataSource

若是要將Spring Boot應用程序部署到應用程序服務器,則可能須要使用應用程序服務器內置功能來配置和管理DataSource,並使用JNDI進行訪問。

spring.datasource.jndi-name屬性能夠用做spring.datasource.url,spring.datasource.username和spring.datasource.password屬性的替代方法,以從特定的JNDI位置訪問DataSource。 例如,application.properties中的如下部分顯示瞭如何訪問JBoss AS定義的DataSource:

spring.datasource.jndi-name=java:jboss/datasources/customers

29.2 使用JdbcTemplate

Spring的JdbcTemplate和NamedParameterJdbcTemplate類是自動配置的,您能夠將它們直接鏈接到您本身的bean中:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

private final JdbcTemplate jdbcTemplate;

@Autowired
public MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

// ...

}

29.3 JPA 和 ‘Spring Data’

Java Persistence API是一種標準技術,可以讓您將對象映射到關係數據庫。 spring-boot-starter-data-jpa POM提供了一種快速入門的方法。 它提供如下關鍵依賴:

  • Hibernate - 最受歡迎的JPA實現之一。
  • Spring Data JPA - 能夠輕鬆實現基於JPA的存儲庫。
  • Spring ORMs - 來自Spring Framework的核心ORM支持。

咱們不會在這裏介紹太多的JPA或Spring Data的細節。 您能夠從spring.io中查看「使用JPA訪問數據」指南,並閱讀Spring Data JPAHibernate參考文檔。

默認狀況下,Spring Boot使用Hibernate 5.0.x. 可是,若是您願意,也可使用4.3.x或5.2.x。 請參考 Hibernate 4Hibernate 5.2 示例,看看如何作到這一點。

29.3.1 實體類

傳統上,JPA’Entity’類在persistence.xml文件中指定。 使用Spring Boot此文件不是必需的,而是使用「實體掃描」。 默認狀況下,將搜索主配置類下面的全部包(用@EnableAutoConfiguration或@SpringBootApplication註解的類)。

任何用@Entity,@Embeddable或@MappedSuperclass註解的類將被考慮。 典型的實體類將以下所示:

package com.example.myapp.domain;

import java.io.Serializable;
import javax.persistence.*;

@Entity
public class City implements Serializable {

@Id
@GeneratedValue
private Long id;

@Column(nullable = false)
private String name;

@Column(nullable = false)
private String state;

// ... additional members, often include @OneToMany mappings

protected City() {
// no-args constructor required by JPA spec
// this one is protected since it shouldn't be used directly
}

public City(String name, String state) {
this.name = name;
this.country = country;
}

public String getName() {
return this.name;
}

public String getState() {
return this.state;
}

// ... etc

}

您可使用@EntityScan註解自定義實體掃描位置。 請參見第77.4節「從Spring配置中分離@Entity定義」操做方法。

29.3.2 Spring Data JPA Repositories

Spring Data JPA庫是能夠定義用於訪問數據的接口。 JPA查詢是從您的方法名稱自動建立的。 例如,CityRepository接口能夠聲明findAllByState(String state)方法來查找給定狀態下的全部城市。

對於更復雜的查詢,您可使用Spring數據查詢註解來註解您的方法。

Spring數據存儲庫一般從Repository或CrudRepository接口擴展。 若是您正在使用自動配置,將從包含主配置類(經過@EnableAutoConfiguration或@SpringBootApplication註解的包)的包中搜索存儲庫(repositories)。

這是一個典型的Spring數據庫:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

Page<City> findAll(Pageable pageable);

City findByNameAndCountryAllIgnoringCase(String name, String country);

}

咱們只是觸及了Spring Data JPA的表面。 有關完整的詳細信息,請查閱其參考文檔

29.3.3 建立和刪除JPA數據庫

默認狀況下,僅當您使用嵌入式數據庫(H2,HSQL或Derby)時纔會自動建立JPA數據庫。 您可使用spring.jpa。*屬性顯式配置JPA設置。 例如,要建立和刪除表,您能夠將如下內容添加到application.properties中。

spring.jpa.hibernate.ddl-auto=create-drop

Hibernate本身的內部屬性名稱(若是你記得更好)是hibernate.hbm2ddl.auto。您可使用spring.jpa.properties *(將其添加到實體管理器時這個前綴會被刪除)與其餘Hibernate屬性一塊兒設置。 例:

spring.jpa.properties.hibernate.globally_quoted_identifiers=true

hibernate.globally_quoted_identifiers 傳遞給Hibernate實體管理器。

默認狀況下,DDL執行(或驗證)將延遲到ApplicationContext啓動。 還有一個spring.jpa.generate-ddl標誌,可是若是Hibernate 自動配置是激活的,那麼它將不會被使用,由於ddl-auto配置更好。

29.3.4 在View中打開EntityManager

若是您正在運行Web應用程序,Spring Boot將默認註冊OpenEntityManagerInViewInterceptor來應用「查看」中的「打開EntityManager」模式,即容許在Web視圖中進行延遲加載。 若是你不想要這個行爲,你應該在你的application.properties中將spring.jpa.open-in-view設置爲false。

29.4 使用H2的Web控制檯

H2數據庫提供了一個基於瀏覽器的控制檯,Spring Boot能夠爲您自動配置。 知足如下條件時,控制檯將自動配置:

若是您不使用Spring Boot的開發人員工具,但仍但願使用H2的控制檯,那麼能夠經過配置一個值爲true的spring.h2.console.enabled屬性來實現。 H2控制檯僅用於開發期間,所以應注意確保spring.h2.console.enabled在生產中未設置爲true。

29.4.1 更改H2控制檯的路徑

默認狀況下,控制檯路徑將在 /h2-console上。 您可使用spring.h2.console.path屬性來自定義控制檯的路徑。

29.4.2 保護H2控制檯

當Spring Security位於類路徑上且啓用了基自己份驗證時,H2控制檯將自動使用基自己份驗證進行保護。 如下屬性可用於自定義安全配置:

  • security.user.role
  • security.basic.authorize-mode
  • security.basic.enabled

29.5 使用jOOQ

Java面向對象查詢(jOOQ)是Data Geekery的產品,它從數據庫生成Java代碼,並經過流暢的API構建類型安全的SQL查詢。 商業版和開源版均可以與Spring Boot一塊兒使用。

29.5.1 代碼生成

爲了使用jOOQ類型安全的查詢,您須要從數據庫模式生成Java類。 您能夠按照jOOQ用戶手冊中的說明進行操做。 若是您正在使用jooq-codegen-maven插件(而且還使用spring-boot-starter-parent「父POM」),您能夠安全地省略插件的標籤。 您還可使用Spring Boot定義的版本變量(例如h2.version)來聲明插件的數據庫依賴關係。 如下是一個例子:

<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
...
</executions>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
<configuration>
<jdbc>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/yourdatabase</url>
</jdbc>
<generator>
...
</generator>
</configuration>
</plugin>

29.5.2 使用 DSLContext

jOOQ提供的流暢的API是經過org.jooq.DSLContext接口啓動的。 Spring Boot將自動配置DSLContext做爲Spring Bean並將其鏈接到應用程序DataSource。 要使用DSLContext,您只需@Autowire它:

@Component
public class JooqExample implements CommandLineRunner {

private final DSLContext create;

@Autowired
public JooqExample(DSLContext dslContext) {
this.create = dslContext;
}

}

jOOQ手冊傾向於使用名爲create的變量來保存DSLContext,咱們在此示例中也是這樣。

而後,您可使用DSLContext構建查詢:

public List<GregorianCalendar> authorsBornAfter1980() {
return this.create.selectFrom(AUTHOR)
.where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
.fetch(AUTHOR.DATE_OF_BIRTH);
}

29.5.3 定製jOOQ

您能夠經過在application.properties中設置spring.jooq.sql-dialect來自定義jOOQ使用的SQL方言。 例如,要指定Postgres,您能夠添加:

spring.jooq.sql-dialect=Postgres

經過定義本身的@Bean定義能夠實現更高級的定製,這些定義將在建立jOOQ配置時使用。您能夠爲如下jOOQ類型定義bean:

  • ConnectionProvider
  • TransactionProvider
  • RecordMapperProvider
  • RecordListenerProvider
  • ExecuteListenerProvider
  • VisitListenerProvider

若是要徹底控制jOOQ配置,您還能夠建立本身的org.jooq.Configuration @Bean。

30. 使用NoSQL技術

Spring Data提供了額外的項目,可幫助您訪問各類NoSQL技術,包括MongoDBNeo4JElasticsearchSolrRedisGemfireCassandraCouchbaseLDAP。 Spring Boot爲Redis,MongoDB,Neo4j,Elasticsearch,Solr Cassandra,Couchbase和LDAP提供了自動配置; 您也可使用其餘項目,但您須要自行配置它們。 請參閱projects.spring.io/spring-data中相應的參考文檔。

30.1 Redis

Redis是一個緩存,消息代理並有功能豐富的鍵值存儲數據庫。Spring Boot提供了Jedis客戶端庫的基本自動配置和Spring Data Redis提供的抽象。 有一個spring-boot-starter-data-redis「Starter」用於以方便的方式收集依賴關係。

30.1.1 鏈接到Redis

您能夠像任何其餘Spring Bean同樣注入自動配置的RedisConnectionFactory,StringRedisTemplate或vanilla RedisTemplate實例。 默認狀況下,實例將嘗試使用localhost:6379鏈接到Redis服務器:

@Component
public class MyBean {

private StringRedisTemplate template;

@Autowired
public MyBean(StringRedisTemplate template) {
this.template = template;
}

// ...

}

若是您添加了您本身的任何自動配置類型的@Bean,它將替換默認值(除了在RedisTemplate的狀況下,排除是基於bean名稱「redisTemplate」而不是其類型)。 若是commons-pool2在類路徑上,則默認狀況下將得到一個pooled鏈接工廠。

30.2 MongoDB

MongoDB是一個開源的NoSQL文檔數據庫,它使用相似JSON的架構,而不是傳統的基於表的關係數據。 Spring Boot爲MongoDB提供了幾種便利,包括spring-boot-starter-data-mongodb’Starter’。

相關文章
相關標籤/搜索