spring-boot(三) HowTo

Spring Boot How To

1. 簡介

本章節將回答一些常見的"我該怎麼作"類型的問題,這些問題在咱們使用spring Boot時常常遇到。這毫不是一個詳盡的列表,但它覆蓋了不少方面。javascript

若是遇到一個特殊的咱們沒有覆蓋的問題,你可能想去查看stackoverflow.comcss

2. Spring Boot應用

2.1. 解決自動配置問題

Spring Boot自動配置老是嘗試盡最大努力去作正確的事,但有時候會失敗而且很難說出失敗緣由。html

在每一個Spring Boot ApplicationContext中都存在一個至關有用的ConditionEvaluationReport。若是開啓DEBUG日誌輸出,你將會看到它。若是你使用spring-boot-actuator,則會有一個autoconfig的端點,它將以JSON形式渲染該報告。可使用它調試應用程序,並能查看Spring Boot運行時都添加了哪些特性(及哪些沒添加)。前端

經過查看源碼和javadoc能夠獲取更多問題的答案。如下是一些經驗:java

查找名爲*AutoConfiguration的類並閱讀源碼,特別是@Conditional*註解,這能夠幫你找出它們啓用哪些特性及什麼時候啓用。 將--debug添加到命令行或添加系統屬性-Ddebug能夠在控制檯查看日誌,該日誌會記錄你的應用中全部自動配置的決策。在一個運行的Actuator app中,經過查看autoconfig端點(/autoconfig或等效的JMX)能夠獲取相同信息。

查找是@ConfigurationProperties的類(好比ServerProperties)並看下有哪些可用的外部配置選項。@ConfigurationProperties類有一個用於充當外部配置前綴的name屬性,所以ServerProperties的值爲prefix="server",它的配置屬性有server.port,server.address等。在運行的Actuator應用中能夠查看configprops端點。

查看使用RelaxedEnvironment明確地將配置從Environment暴露出去。它常常會使用一個前綴。

查看@Value註解,它直接綁定到Environment。相比RelaxedEnvironment,這種方式稍微缺少靈活性,但它也容許鬆散的綁定,特別是OS環境變量(因此CAPITALS_AND_UNDERSCORES是period.separated的同義詞)。

查看@ConditionalOnExpression註解,它根據SpEL表達式的結果來開啓或關閉特性,一般使用解析自Environment的佔位符進行計算。

2.2. 啓動前自定義Environment或ApplicationContext

每一個SpringApplication都有ApplicationListeners和ApplicationContextInitializers,用於自定義上下文(context)或環境(environment)。Spring Boot從META-INF/spring.factories下加載不少這樣的內部使用的自定義。有不少方法能夠註冊其餘的自定義:mysql

以編程方式爲每一個應用註冊自定義,經過在SpringApplication運行前調用它的addListeners和addInitializers方法來實現。
以聲明方式爲每一個應用註冊自定義,經過設置context.initializer.classes或context.listener.classes來實現。
以聲明方式爲全部應用註冊自定義,經過添加一個META-INF/spring.factories並打包成一個jar文件(該應用將它做爲一個庫)來實現。

SpringApplication會給監聽器(即便是在上下文被建立以前就存在的)發送一些特定的ApplicationEvents,而後也會註冊監聽ApplicationContext發佈的事件的監聽器。查看Spring Boot特性章節中的Section 22.4, 「Application events and listeners」 能夠獲取一個完整列表。web

2.3. 建立一個非web(non-web)應用

不是全部的Spring應用都必須是web應用(或web服務)。若是你想在main方法中執行一些代碼,但須要啓動一個Spring應用去設置須要的底層設施,那使用Spring Boot的SpringApplication特性能夠很容易實現。SpringApplication會根據它是否須要一個web應用來改變它的ApplicationContext類。首先你須要作的是去掉servlet API依賴,若是不能這樣作(好比,基於相同的代碼運行兩個應用),那你能夠明確地調用SpringApplication.setWebEnvironment(false)或設置applicationContextClass屬性(經過Java API或使用外部配置)。你想運行的,做爲業務邏輯的應用代碼能夠實現爲一個CommandLineRunner,並將上下文降級爲一個@Bean定義。正則表達式

3. 屬性&配置

3.1. 外部化SpringApplication配置

SpringApplication已經被屬性化(主要是setters),因此你能夠在建立應用時使用它的Java API修改它的行爲。或者你可使用properties文件中的spring.main.*來外部化(在應用代碼外配置)這些配置。好比,在application.properties中可能會有如下內容:spring

spring.main.web_environment=false
spring.main.show_banner=false

而後Spring Boot在啓動時將不會顯示banner,而且該應用也不是一個web應用。sql

3.2. 改變應用程序外部配置文件的位置

默認狀況下,來自不一樣源的屬性以一個定義好的順序添加到Spring的Environment中(查看'Sprin Boot特性'章節的Chapter 23, Externalized Configuration獲取精確的順序)。

爲應用程序源添加@PropertySource註解是一種很好的添加和修改源順序的方法。傳遞給SpringApplication靜態便利設施(convenience)方法的類和使用setSources()添加的類都會被檢查,以查看它們是否有@PropertySources,若是有,這些屬性會被儘量早的添加到Environment裏,以確保ApplicationContext生命週期的全部階段都能使用。以這種方式添加的屬性優先於任何使用默認位置添加的屬性,但低於系統屬性,環境變量或命令行參數。

你也能夠提供系統屬性(或環境變量)來改變該行爲:

spring.config.name(SPRING_CONFIG_NAME)是根文件名,默認爲application。
spring.config.location(SPRING_CONFIG_LOCATION)是要加載的文件(例如,一個classpath資源或一個URL)。Spring Boot爲該文檔設置一個單獨的Environment屬性,它能夠被系統屬性,環境變量或命令行參數覆蓋。

無論你在environment設置什麼,Spring Boot都將加載上面討論過的application.properties。若是使用YAML,那具備'.yml'擴展的文件默認也會被添加到該列表。

3.3. 使用'short'命令行參數

有些人喜歡使用(例如)--port=9000代替--server.port=9000來設置命令行配置屬性。你能夠經過在application.properties中使用佔位符來啓用該功能,好比:

server.port=${port:8080}

注:若是你繼承自spring-boot-starter-parent POM,爲了防止和Spring-style的佔位符產生衝突,maven-resources-plugins默認的過濾令牌(filter token)已經從${*}變爲@(即@maven.token@代替了${maven.token})。若是已經直接啓用maven對application.properties的過濾,你可能也想使用其餘的分隔符替換默認的過濾令牌。

注:在這種特殊的狀況下,端口綁定可以在一個PaaS環境下工做,好比Heroku和Cloud Foundry,由於在這兩個平臺中PORT環境變量是自動設置的,而且Spring可以綁定Environment屬性的大寫同義詞。

3.4. 使用YAML配置外部屬性

YAML是JSON的一個超集,能夠很是方便的將外部配置以層次結構形式存儲起來。好比:

spring:
    application:
        name: cruncher
    datasource:
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost/test
server:
    port: 9000

建立一個application.yml文件,將它放到classpath的根目錄下,並添加snakeyaml依賴(Maven座標爲org.yaml:snakeyaml,若是你使用spring-boot-starter那就已經被包含了)。一個YAML文件會被解析爲一個java Map<String,Object>(和一個JSON對象相似),Spring Boot會平伸該map,這樣它就只有1級深度,而且有period-separated的keys,跟人們在Java中常用的Properties文件很是相似。 上面的YAML示例對應於下面的application.properties文件:

spring.application.name=cruncher
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000

3.5. 設置生效的Spring profiles

Spring Environment有一個API能夠設置生效的profiles,但一般你會設置一個系統profile(spring.profiles.active)或一個OS環境變量(SPRINGPROFILESACTIVE)。好比,使用一個-D參數啓動應用程序(記着把它放到main類或jar文件以前):

 java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar

在Spring Boot中,你也能夠在application.properties裏設置生效的profile,例如:

spring.profiles.active=production

經過這種方式設置的值會被系統屬性或環境變量替換,但不會被SpringApplicationBuilder.profiles()方法替換。所以,後面的Java API可用來在不改變默認設置的狀況下增長profiles。

3.6. 根據環境改變配置

一個YAML文件其實是一系列以---線分割的文檔,每一個文檔都被單獨解析爲一個平坦的(flattened)map。

若是一個YAML文檔包含一個spring.profiles關鍵字,那profiles的值(以逗號分割的profiles列表)將被傳入Spring的Environment.acceptsProfiles()方法,而且若是這些profiles的任何一個被激活,對應的文檔被包含到最終的合併中(不然不會)。

示例:

server:
    port: 9000
---

spring:
    profiles: development
server:
    port: 9001

---

spring:
    profiles: production
server:
    port: 0

在這個示例中,默認的端口是9000,但若是Spring profile 'development'生效則該端口是9001,若是'production'生效則它是0。

YAML文檔以它們遇到的順序合併(因此後面的值會覆蓋前面的值)。

想要使用profiles文件完成一樣的操做,你可使用application-${profile}.properties指定特殊的,profile相關的值。

3.7. 發現外部屬性的內置選項

Spring Boot在運行時未來自application.properties(或.yml)的外部屬性綁定進一個應用中。在一個地方不可能存在詳盡的全部支持屬性的列表(技術上也是不可能的),由於你的classpath下的其餘jar文件也可以貢獻。

每一個運行中且有Actuator特性的應用都會有一個configprops端點,它可以展現全部邊界和可經過@ConfigurationProperties綁定的屬性。

附錄中包含一個application.properties示例,它列舉了Spring Boot支持的大多數經常使用屬性。獲取權威列表可搜索@ConfigurationProperties和@Value的源碼,還有不常用的RelaxedEnvironment。

4. 內嵌的servlet容器

4.1. 爲應用添加Servlet,Filter或ServletContextListener

Servlet規範支持的Servlet,Filter,ServletContextListener和其餘監聽器能夠做爲@Bean定義添加到你的應用中。須要格外當心的是,它們不會引發太多的其餘beans的熱初始化,由於在應用生命週期的早期它們已經被安裝到容器裏了(好比,讓它們依賴你的DataSource或JPA配置就不是一個好主意)。你能夠經過延遲初始化它們到第一次使用而不是初始化時來突破該限制。

在Filters和Servlets的狀況下,你也能夠經過添加一個FilterRegistrationBean或ServletRegistrationBean代替或以及底層的組件來添加映射(mappings)和初始化參數。

4.2. 改變HTTP端口

在一個單獨的應用中,主HTTP端口默認爲8080,但可使用server.port設置(好比,在application.properties中或做爲一個系統屬性)。因爲Environment值的寬鬆綁定,你也可使用SERVER_PORT(好比,做爲一個OS環境變)。

爲了徹底關閉HTTP端點,但仍建立一個WebApplicationContext,你能夠設置server.port=-1(測試時可能有用)。

想獲取更多詳情可查看'Spring Boot特性'章節的Section 26.3.3, 「Customizing embedded servlet containers」,或ServerProperties源碼。

4.3. 使用隨機未分配的HTTP端口

想掃描一個未使用的端口(爲了防止衝突使用OS本地端口)可使用server.port=0。

4.4. 發現運行時的HTTP端口

你能夠經過日誌輸出或它的EmbeddedServletContainer的EmbeddedWebApplicationContext獲取服務器正在運行的端口。獲取和確認服務器已經初始化的最好方式是添加一個ApplicationListener類型的@Bean,而後當事件發佈時將容器pull出來。

使用@WebIntegrationTests的一個有用實踐是設置server.port=0,而後使用@Value注入實際的('local')端口。例如:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)
@WebIntegrationTest("server.port:0")
public class CityRepositoryIntegrationTests {

    @Autowired
    EmbeddedWebApplicationContext server;

    @Value("${local.server.port}")
    int port;

    // ...

}

4.5. 配置SSL

SSL可以以聲明方式進行配置,通常經過在application.properties或application.yml設置各類各樣的server.ssl.*屬性。例如:

server.port = 8443
server.ssl.key-store = classpath:keystore.jks
server.ssl.key-store-password = secret
server.ssl.key-password = another-secret

獲取全部支持的配置詳情可查看Ssl。

注:Tomcat要求key存儲(若是你正在使用一個可信存儲)可以直接在文件系統上訪問,即它不能從一個jar文件內讀取。Jetty和Undertow沒有該限制。

使用相似於以上示例的配置意味着該應用將不在支持端口爲8080的普通HTTP鏈接。Spring Boot不支持經過application.properties同時配置HTTP鏈接器和HTTPS鏈接器。若是你兩個都想要,那就須要以編程的方式配置它們中的一個。推薦使用application.properties配置HTTPS,由於HTTP鏈接器是兩個中最容易以編程方式進行配置的。獲取示例可查看spring-boot-sample-tomcat-multi-connectors示例項目。

4.6. 配置Tomcat

一般你能夠遵循Section 63.7, 「Discover built-in options for external properties」關於@ConfigurationProperties(這裏主要的是ServerProperties)的建議,但也看下EmbeddedServletContainerCustomizer和各類你能夠添加的Tomcat-specific的*Customizers。

Tomcat APIs至關豐富,一旦獲取到TomcatEmbeddedServletContainerFactory,你就可以以多種方式修改它。或核心選擇是添加你本身的TomcatEmbeddedServletContainerFactory。

4.7. 啓用Tomcat的多鏈接器(Multiple Connectors)

你能夠將一個org.apache.catalina.connector.Connector添加到TomcatEmbeddedServletContainerFactory,這就可以容許多鏈接器,好比HTTP和HTTPS鏈接器:

@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
    tomcat.addAdditionalTomcatConnectors(createSslConnector());
    return tomcat;
}

private Connector createSslConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
    try {
        File keystore = new ClassPathResource("keystore").getFile();
        File truststore = new ClassPathResource("keystore").getFile();
        connector.setScheme("https");
        connector.setSecure(true);
        connector.setPort(8443);
        protocol.setSSLEnabled(true);
        protocol.setKeystoreFile(keystore.getAbsolutePath());
        protocol.setKeystorePass("changeit");
        protocol.setTruststoreFile(truststore.getAbsolutePath());
        protocol.setTruststorePass("changeit");
        protocol.setKeyAlias("apitester");
        return connector;
    }
    catch (IOException ex) {
        throw new IllegalStateException("can't access keystore: [" + "keystore"
                + "] or truststore: [" + "keystore" + "]", ex);
    }
}

4.8. 在前端代理服務器後使用Tomcat

Spring Boot將自動配置Tomcat的RemoteIpValve,若是你啓用它的話。這容許你透明地使用標準的x-forwarded-for和x-forwarded-proto頭,不少前端代理服務器都會添加這些頭信息(headers)。經過將這些屬性中的一個或所有設置爲非空的內容來開啓該功能(它們是大多數代理約定的值,若是你只設置其中的一個,則另外一個也會被自動設置)。

server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto

若是你的代理使用不一樣的頭部(headers),你能夠經過向application.properties添加一些條目來自定義該值的配置,好比:

server.tomcat.remote_ip_header=x-your-remote-ip-header
server.tomcat.protocol_header=x-your-protocol-header

該值也能夠配置爲一個默認的,可以匹配信任的內部代理的正則表達式。默認狀況下,受信任的IP包括 10/8, 192.168/16, 169.254/16 和 127/8。能夠經過向application.properties添加一個條目來自定義該值的配置,好比:

server.tomcat.internal_proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}

注:只有在你使用一個properties文件做爲配置的時候才須要雙反斜槓。若是你使用YAML,單個反斜槓就足夠了,192.168.\d{1,3}.\d{1,3}和上面的等價。

另外,經過在一個TomcatEmbeddedServletContainerFactory bean中配置和添加RemoteIpValve,你就能夠徹底控制它的設置了。

4.9. 使用Jetty替代Tomcat

Spring Boot starters(特別是spring-boot-starter-web)默認都是使用Tomcat做爲內嵌容器的。你須要排除那些Tomcat的依賴幷包含Jetty的依賴。爲了讓這種處理儘量簡單,Spring Boot將Tomcat和Jetty的依賴捆綁在一塊兒,而後提供單獨的starters。

Maven示例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

Gradle示例:

configurations {
    compile.exclude module: "spring-boot-starter-tomcat"
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.3.0.BUILD-SNAPSHOT")
    compile("org.springframework.boot:spring-boot-starter-jetty:1.3.0.BUILD-SNAPSHOT")
    // ...
}

4.10. 配置Jetty

一般你能夠遵循Section 63.7, 「Discover built-in options for external properties」關於@ConfigurationProperties(此處主要是ServerProperties)的建議,但也要看下EmbeddedServletContainerCustomizer。Jetty API至關豐富,一旦獲取到JettyEmbeddedServletContainerFactory,你就可使用不少方式修改它。或更完全地就是添加你本身的JettyEmbeddedServletContainerFactory。

4.11. 使用Undertow替代Tomcat

使用Undertow替代Tomcat和使用Jetty替代Tomcat很是相似。你須要排除Tomat依賴,幷包含Undertow starter。

Maven示例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

Gradle示例:

configurations {
    compile.exclude module: "spring-boot-starter-tomcat"
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web:1.3.0.BUILD-SNAPSHOT")
    compile 'org.springframework.boot:spring-boot-starter-undertow:1.3.0.BUILD-SNAPSHOT")
    // ...
}

4.13. 啓用Undertow的多監聽器(Multiple Listeners)

往UndertowEmbeddedServletContainerFactory添加一個UndertowBuilderCustomizer,而後添加一個監聽者到Builder:

@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
    UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
    factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {

        @Override
        public void customize(Builder builder) {
            builder.addHttpListener(8080, "0.0.0.0");
        }

    });
    return factory;
}

4.14. 使用Tomcat7

Tomcat7可用於Spring Boot,但默認使用的是Tomcat8。若是不能使用Tomcat8(例如,你使用的是Java1.6),你須要改變classpath去引用Tomcat7。

4.14.1. 經過Maven使用Tomcat7

若是正在使用starter pom和parent,你只須要改變Tomcat的version屬性,好比,對於一個簡單的webapp或service:

<properties>
    <tomcat.version>7.0.59</tomcat.version>
</properties>
<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    ...
</dependencies>

4.14.2. 經過Gradle使用Tomcat7

你能夠經過設置tomcat.version屬性改變Tomcat的版本:

ext['tomcat.version'] = '7.0.59' dependencies { compile 'org.springframework.boot:spring-boot-starter-web' }

4.15. 使用Jetty8

Jetty8可用於Spring Boot,但默認使用的是Jetty9。若是不能使用Jetty9(例如,由於你使用的是Java1.6),你只需改變classpath去引用Jetty8。你也須要排除Jetty的WebSocket相關的依賴。

4.15.1. 經過Maven使用Jetty8

若是正在使用starter pom和parent,你只需添加Jetty starter,去掉WebSocket依賴,並改變version屬性,好比,對於一個簡單的webapp或service:

<properties>
    <jetty.version>8.1.15.v20140411</jetty.version>
    <jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.eclipse.jetty.websocket</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

4.16. 使用@ServerEndpoint建立WebSocket端點

若是想在一個使用內嵌容器的Spring Boot應用中使用@ServerEndpoint,你須要聲明一個單獨的ServerEndpointExporter @Bean:

@Bean
public ServerEndpointExporter serverEndpointExporter() {
    return new ServerEndpointExporter();
}

該bean將用底層的WebSocket容器註冊任何的被@ServerEndpoint註解的beans。當部署到一個單獨的servlet容器時,該角色將被一個servlet容器初始化方法履行,ServerEndpointExporter bean也就不是必需的了。

4.17. 啓用HTTP響應壓縮

Spring Boot提供兩種啓用HTTP壓縮的機制;一種是Tomcat特有的,另外一種是使用一個filter,能夠配合Jetty,Tomcat和Undertow。

4.17.1. 啓用Tomcat的HTTP響應壓縮

Tomcat對HTTP響應壓縮提供內建支持。默認是禁用的,但能夠經過application.properties輕鬆的啓用:

server.tomcat.compression: on

當設置爲on時,Tomcat將壓縮響應的長度至少爲2048字節。你能夠配置一個整型值來設置該限制而不僅是on,好比:

server.tomcat.compression: 4096

默認狀況下,Tomcat只壓縮某些MIME類型的響應(text/html,text/xml和text/plain)。你可使用server.tomcat.compressableMimeTypes屬性進行自定義,好比:

server.tomcat.compressableMimeTypes=application/json,application/xml

4.17.2. 使用GzipFilter開啓HTTP響應壓縮

若是你正在使用Jetty或Undertow,或想要更精確的控制HTTP響應壓縮,Spring Boot爲Jetty的GzipFilter提供自動配置。雖然該過濾器是Jetty的一部分,但它也兼容Tomcat和Undertow。想要啓用該過濾器,只需簡單的爲你的應用添加org.eclipse.jetty:jetty-servlets依賴。

GzipFilter可使用spring.http.gzip.*屬性進行配置。具體參考GzipFilterProperties。

5. Spring MVC

5.1. 編寫一個JSON REST服務

在Spring Boot應用中,任何Spring @RestController默認應該渲染爲JSON響應,只要classpath下存在Jackson2。例如:

@RestController
public class MyController {

    @RequestMapping("/thing")
    public MyThing thing() {
            return new MyThing();
    }

}

只要MyThing可以經過Jackson2序列化(好比,一個標準的POJO或Groovy對象),localhost:8080/thing默認響應一個JSON表示。有時在一個瀏覽器中你可能看到XML響應由於瀏覽器傾向於發送XML 響應頭。

5.2. 編寫一個XML REST服務

若是classpath下存在Jackson XML擴展(jackson-dataformat-xml),它會被用來渲染XML響應,示例和JSON的很是類似。想要使用它,只需爲你的項目添加如下的依賴:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

你可能也想添加對Woodstox的依賴。它比JDK提供的默認Stax實現快不少,而且支持良好的格式化輸出,提升了namespace處理能力:

<dependency>
    <groupId>org.codehaus.woodstox</groupId>
    <artifactId>woodstox-core-asl</artifactId>
</dependency>

若是Jackson的XML擴展不可用,Spring Boot將使用JAXB(JDK默認提供),不過你須要爲MyThing添加額外的註解@XmlRootElement:

@XmlRootElement
public class MyThing {
    private String name;
    // .. getters and setters
}

想要服務器渲染XML而不是JSON,你可能須要發送一個Accept: text/xml頭部(或使用瀏覽器)。

5.3. 自定義Jackson ObjectMapper

在一個HTTP交互中,Spring MVC(客戶端和服務端)使用HttpMessageConverters協商內容轉換。若是classpath下存在Jackson,你就已經獲取到Jackson2ObjectMapperBuilder提供的默認轉換器。

建立的ObjectMapper(或用於Jackson XML轉換的XmlMapper)實例默認有如下自定義屬性:

MapperFeature.DEFAULT_VIEW_INCLUSION禁用
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES禁用

Spring Boot也有一些簡化自定義該行爲的特性。

你可使用當前的environment配置ObjectMapper和XmlMapper實例。Jackson提供一個擴展套件,能夠用來簡單的關閉或開啓一些特性,你能夠用它們配置Jackson處理的不一樣方面。這些特性在Jackson中使用5個枚舉進行描述的,並被映射到environment的屬性上:

Jackson枚舉 Environment屬性 com.fasterxml.jackson.databind.DeserializationFeaturespring.jackson.generator.=true false com.fasterxml.jackson.databind.MapperFeature spring.jackson.parser.=true falsecom.fasterxml.jackson.databind.SerializationFeature output=true能夠開啓漂亮打印。注意,因爲鬆綁定的使用,indentoutput沒必要匹配對應的枚舉常量INDENT_OUTPUT。

若是想完全替換默認的ObjectMapper,你須要定義一個該類型的@Bean並將它標記爲@Primary。

定義一個Jackson2ObjectMapperBuilder類型的@Bean將容許你自定義默認的ObjectMapper和XmlMapper(分別用於MappingJackson2HttpMessageConverter和MappingJackson2XmlHttpMessageConverter)。

另外一種自定義Jackson的方法是向你的上下文添加com.fasterxml.jackson.databind.Module類型的beans。它們會被註冊入每一個ObjectMapper類型的bean,當爲你的應用添加新特性時,這就提供了一種全局機制來貢獻自定義模塊。

最後,若是你提供任何MappingJackson2HttpMessageConverter類型的@Beans,那它們將替換MVC配置中的默認值。同時,也提供一個HttpMessageConverters類型的bean,它有一些有用的方法能夠獲取默認的和用戶加強的message轉換器。

5.4. 自定義@ResponseBody渲染

Spring使用HttpMessageConverters渲染@ResponseBody(或來自@RestController的響應)。你能夠經過在Spring Boot上下文中添加該類型的beans來貢獻其餘的轉換器。若是你添加的bean類型默認已經包含了(像用於JSON轉換的MappingJackson2HttpMessageConverter),那它將替換默認的。Spring Boot提供一個方便的HttpMessageConverters類型的bean,它有一些有用的方法能夠訪問默認的和用戶加強的message轉換器(有用,好比你想要手動將它們注入到一個自定義的RestTemplate)。

在一般的MVC用例中,任何你提供的WebMvcConfigurerAdapter beans經過覆蓋configureMessageConverters方法也能貢獻轉換器,但不一樣於一般的MVC,你能夠只提供你須要的轉換器(由於Spring Boot使用相同的機制來貢獻它默認的轉換器)。最終,若是你經過提供本身的@EnableWebMvc註解覆蓋Spring Boot默認的MVC配置,那你就能夠徹底控制,並使用來自WebMvcConfigurationSupport的getMessageConverters手動作任何事。

5.5. 處理Multipart文件上傳

Spring Boot採用Servlet 3 javax.servlet.http.Part API來支持文件上傳。默認狀況下,Spring Boot配置Spring MVC在單個請求中每一個文件最大1Mb,最多10Mb的文件數據。你能夠覆蓋那些值,也能夠設置臨時文件存儲的位置(好比,存儲到/tmp文件夾下)及傳遞數據刷新到磁盤的閥值(經過使用MultipartProperties類暴露的屬性)。若是你須要設置文件不受限制,例如,能夠設置multipart.maxFileSize屬性值爲-1。

當你想要接收部分(multipart)編碼文件數據做爲Spring MVC控制器(controller)處理方法中被@RequestParam註解的MultipartFile類型的參數時,multipart支持就很是有用了。

5.6. 關閉Spring MVC DispatcherServlet

Spring Boot想要服務來自應用程序root /下的全部內容。若是你想將本身的servlet映射到該目錄下也是能夠的,但固然你可能失去一些Boot MVC特性。爲了添加你本身的servlet,並將它映射到root資源,你只需聲明一個Servlet類型的@Bean,並給它特定的bean名稱dispatcherServlet(若是隻想關閉但不替換它,你可使用該名稱建立不一樣類型的bean)。

5.7. 關閉默認的MVC配置

徹底控制MVC配置的最簡單方式是提供你本身的被@EnableWebMvc註解的@Configuration。這樣全部的MVC配置都逃不出你的掌心。

5.8. 自定義ViewResolvers

ViewResolver是Spring MVC的核心組件,它負責轉換@Controller中的視圖名稱到實際的View實現。注意ViewResolvers主要用在UI應用中,而不是REST風格的服務(View不是用來渲染@ResponseBody的)。Spring有不少你能夠選擇的ViewResolver實現,而且Spring本身對如何選擇相應實現也沒發表意見。另外一方面,Spring Boot會根據classpath上的依賴和應用上下文爲你安裝一或兩個ViewResolver實現。DispatcherServlet使用全部在應用上下文中找到的解析器(resolvers),並依次嘗試每個直到它獲取到結果,因此若是你正在添加本身的解析器,那就要當心順序和你的解析器添加的位置。

WebMvcAutoConfiguration將會爲你的上下文添加如下ViewResolvers:

bean id爲defaultViewResolver的InternalResourceViewResolver。這個會定位可使用DefaultServlet渲染的物理資源(好比,靜態資源和JSP頁面)。它在視圖(view name)上應用了一個前綴和後綴(默認都爲空,但你能夠經過spring.view.prefix和spring.view.suffix外部配置設置),而後查找在servlet上下文中具備該路徑的物理資源。能夠經過提供相同類型的bean覆蓋它。

id爲beanNameViewResolver的BeanNameViewResolver。這是視圖解析器鏈的一個很是有用的成員,它能夠在View被解析時收集任何具備相同名稱的beans。 id爲viewResolver的ContentNegotiatingViewResolver只會在實際View類型的beans出現時添加。這是一個'主'解析器,它的職責會代理給其餘解析器,它會嘗試找到客戶端發送的一個匹配'Accept'的HTTP頭部。這有一篇有用的,關於你須要更多瞭解的ContentNegotiatingViewResolver的博客,也要具體查看下源碼。經過定義一個名叫'viewResolver'的bean,你能夠關閉自動配置的ContentNegotiatingViewResolver。

若是使用Thymeleaf,你將有一個id爲thymeleafViewResolver的ThymeleafViewResolver。它會經過加前綴和後綴的視圖名來查找資源(外部配置爲spring.thymeleaf.prefix和spring.thymeleaf.suffix,對應的默認爲'classpath:/templates/'和'.html')。你能夠經過提供相同名稱的bean來覆蓋它。

若是使用FreeMarker,你將有一個id爲freeMarkerViewResolver的FreeMarkerViewResolver。它會使用加前綴和後綴(外部配置爲spring.freemarker.prefix和spring.freemarker.suffix,對應的默認值爲空和'.ftl')的視圖名從加載路徑(外部配置爲spring.freemarker.templateLoaderPath,默認爲'classpath:/templates/')下查找資源。你能夠經過提供一個相同名稱的bean來覆蓋它。

若是使用Groovy模板(實際上只要你把groovy-templates添加到classpath下),你將有一個id爲groovyTemplateViewResolver的Groovy TemplateViewResolver。它會使用加前綴和後綴(外部屬性爲spring.groovy.template.prefix和spring.groovy.template.suffix,對應的默認值爲'classpath:/templates/'和'.tpl')的視圖名從加載路徑下查找資源。你能夠經過提供一個相同名稱的bean來覆蓋它。

若是使用Velocity,你將有一個id爲velocityViewResolver的VelocityViewResolver。它會使用加前綴和後綴(外部屬性爲spring.velocity.prefix和spring.velocity.suffix,對應的默認值爲空和'.vm')的視圖名從加載路徑(外部屬性爲spring.velocity.resourceLoaderPath,默認爲'classpath:/templates/')下查找資源。你能夠經過提供一個相同名稱的bean來覆蓋它。 具體參考: WebMvcAutoConfiguration,ThymeleafAutoConfiguration,FreeMarkerAutoConfiguration,GroovyTemplateAutoConfiguration, VelocityAutoConfiguration。

6. 日誌

Spring Boot除了commons-logging API外沒有其餘強制性的日誌依賴,你有不少可選的日誌實現。想要使用Logback,你須要包含它,及一些對classpath下commons-logging的綁定。最簡單的方式是經過依賴spring-boot-starter-logging的starter pom。對於一個web應用程序,你只需添加spring-boot-starter-web依賴,由於它依賴於logging starter。例如,使用Maven:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 

Spring Boot有一個LoggingSystem抽象,用於嘗試經過classpath上下文配置日誌系統。若是Logback可用,則首選它。若是你惟一須要作的就是設置不一樣日誌的級別,那能夠經過在application.properties中使用logging.level前綴實現,好比:

logging.level.org.springframework.web: DEBUG
logging.level.org.hibernate: ERROR

你也可使用logging.file設置日誌文件的位置(除控制檯以外,默認會輸出到控制檯)。

想要對日誌系統進行更細粒度的配置,你須要使用正在說的LoggingSystem支持的原生配置格式。默認狀況下,Spring Boot從系統的默認位置加載原生配置(好比對於Logback爲classpath:logback.xml),但你可使用logging.config屬性設置配置文件的位置。

6.1. 配置Logback

若是你將一個logback.xml放到classpath根目錄下,那它將會被從這加載。Spring Boot提供一個默認的基本配置,若是你只是設置日誌級別,那你能夠包含它,好比:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <logger name="org.springframework.web" level="DEBUG"/>
</configuration>

若是查看spring-boot jar包中的默認logback.xml,你將會看到LoggingSystem爲你建立的不少有用的系統屬性,好比:

${PID},當前進程id
${LOG_FILE},若是在Boot外部配置中設置了logging.file
${LOG_PATH},若是設置了logging.path(表示日誌文件產生的目錄)

Spring Boot也提供使用自定義的Logback轉換器在控制檯上輸出一些漂亮的彩色ANSI日誌信息(不是日誌文件)。具體參考默認的base.xml配置。

若是Groovy在classpath下,你也可使用logback.groovy配置Logback。

6.2. 配置Log4j

Spring Boot也支持Log4j或Log4j 2做爲日誌配置,但只有在它們中的某個在classpath下存在的狀況。若是你正在使用starter poms進行依賴裝配,這意味着你須要排除Logback,而後包含你選擇的Log4j版本。若是你不使用starter poms,那除了你選擇的Log4j版本外還要提供commons-logging(至少)。

最簡單的方式可能就是經過starter poms,儘管它須要排除一些依賴,好比,在Maven中:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
</dependency>

想要使用Log4j 2,只須要依賴spring-boot-starter-log4j2而不是spring-boot-starter-log4j。

注:使用Log4j各版本的starters都會收集好依賴以知足common logging的要求(好比,Tomcat中使用java.util.logging,但使用Log4j或 Log4j 2做爲輸出)。具體查看Actuator Log4j或Log4j 2的示例,瞭解如何將它用於實戰。

6.2.1. 使用YAML或JSON配置Log4j2

除了它的默認XML配置格式,Log4j 2也支持YAML和JSON配置文件。想要使用其餘配置文件格式來配置Log4j 2,你須要添加合適的依賴到classpath。爲了使用YAML,你須要添加com.fasterxml.jackson.dataformat:jackson-dataformat-yaml依賴,Log4j 2將查找名稱爲log4j2.yaml或log4j2.yml的配置文件。爲了使用JSON,你須要添加com.fasterxml.jackson.core:jackson-databind依賴,Log4j 2將查找名稱爲log4j2.json或log4j2.jsn的配置文件

7. 數據訪問

7.1. 配置一個數據源

想要覆蓋默認的設置只須要定義一個你本身的DataSource類型的@Bean。Spring Boot提供一個工具構建類DataSourceBuilder,可用來建立一個標準的DataSource(若是它處於classpath下),或者僅建立你本身的DataSource,而後將它和在Section 23.7.1, 「Third-party configuration」解釋的一系列Environment屬性綁定。 好比:

@Bean
@ConfigurationProperties(prefix="datasource.mine")
public DataSource dataSource() {
    return new FancyDataSource();
}

datasource.mine.jdbcUrl=jdbc:h2:mem:mydb
datasource.mine.user=sa
datasource.mine.poolSize=30

具體參考'Spring Boot特性'章節中的Section 28.1, 「Configure a DataSource」和DataSourceAutoConfiguration類源碼。

7.2. 配置兩個數據源

建立多個數據源和建立第一個工做都是同樣的。若是使用針對JDBC或JPA的默認自動配置,你可能想要將其中一個設置爲@Primary(而後它就能被任何@Autowired注入獲取)。

@Bean
@Primary
@ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
@ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
    return DataSourceBuilder.create().build();
}

7.3. 使用Spring Data倉庫

Spring Data能夠爲你的@Repository接口建立各類風格的實現。Spring Boot會爲你處理全部事情,只要那些@Repositories接口跟你的@EnableAutoConfiguration類處於相同的包(或子包)。

對於不少應用來講,你須要作的就是將正確的Spring Data依賴添加到classpath下(對於JPA有一個spring-boot-starter-data-jpa,對於MongoDB有一個spring-boot-starter-data-mongodb),建立一些repository接口來處理@Entity對象。具體參考JPA sample或Mongodb sample。

Spring Boot會基於它找到的@EnableAutoConfiguration來嘗試猜想你的@Repository定義的位置。想要獲取更多控制,可使用@EnableJpaRepositories註解(來自Spring Data JPA)。

7.4. 從Spring配置分離@Entity定義

Spring Boot會基於它找到的@EnableAutoConfiguration來嘗試猜想你的@Entity定義的位置。想要獲取更多控制,你可使用@EntityScan註解,好比:

@Configuration
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
public class Application {

    //...

}

7.5. 配置JPA屬性

Spring Data JPA已經提供了一些獨立的配置選項(好比,針對SQL日誌),而且Spring Boot會暴露它們,針對hibernate的外部配置屬性也更多些。最多見的選項以下:

spring.jpa.hibernate.ddl-auto: create-drop
spring.jpa.hibernate.naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.database: H2
spring.jpa.show-sql: true

(因爲寬鬆的數據綁定策略,連字符或下劃線做爲屬性keys做用應該是等效的)ddl-auto配置是個特殊狀況,它有不一樣的默認設置,這取決於你是否使用一個內嵌數據庫(create-drop)。當本地EntityManagerFactory被建立時,全部spring.jpa.properties.*屬性都被做爲正常的JPA屬性(去掉前綴)傳遞進去了。

具體參考HibernateJpaAutoConfiguration和JpaBaseConfiguration。

7.6. 使用自定義的EntityManagerFactory

爲了徹底控制EntityManagerFactory的配置,你須要添加一個名爲entityManagerFactory的@Bean。Spring Boot自動配置會根據是否存在該類型的bean來關閉它的實體管理器(entity manager)。

7.7. 使用兩個EntityManagers

即便默認的EntityManagerFactory工做的很好,你也須要定義一個新的EntityManagerFactory,由於一旦出現第二個該類型的bean,默認的將會被關閉。爲了輕鬆的實現該操做,你可使用Spring Boot提供的EntityManagerBuilder,或者若是你喜歡的話能夠直接使用來自Spring ORM的LocalContainerEntityManagerFactoryBean。

示例:

// add two data sources configured as above

@Bean
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
        EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(customerDataSource())
            .packages(Customer.class)
            .persistenceUnit("customers")
            .build();
}

@Bean
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
        EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(orderDataSource())
            .packages(Order.class)
            .persistenceUnit("orders")
            .build();
}

上面的配置靠本身基本能夠運行。想要完成做品你也須要爲兩個EntityManagers配置TransactionManagers。其中的一個會被Spring Boot默認的JpaTransactionManager獲取,若是你將它標記爲@Primary。另外一個須要顯式注入到一個新實例。或你可使用一個JTA事物管理器生成它兩個。

7.8. 使用普通的persistence.xml

Spring不要求使用XML配置JPA提供者(provider),而且Spring Boot假定你想要充分利用該特性。若是你傾向於使用persistence.xml,那你須要定義你本身的id爲'entityManagerFactory'的LocalEntityManagerFactoryBean類型的@Bean,並在那設置持久化單元的名稱。

默認設置可查看JpaBaseConfiguration

7.9. 使用Spring Data JPA和Mongo倉庫

Spring Data JPA和Spring Data Mongo都能自動爲你建立Repository實現。若是它們同時出如今classpath下,你可能須要添加額外的配置來告訴Spring Boot你想要哪一個(或兩個)爲你建立倉庫。最明確地方式是使用標準的Spring Data @EnableRepositories,而後告訴它你的Repository接口的位置(此處便可以是Jpa,也能夠是Mongo,或者二者都是)。

這裏也有spring.data.*.repositories.enabled標誌,可用來在外部配置中開啓或關閉倉庫的自動配置。這在你想關閉Mongo倉庫,但仍舊使用自動配置的MongoTemplate時很是有用。

相同的障礙和特性也存在於其餘自動配置的Spring Data倉庫類型(Elasticsearch, Solr)。只須要改變對應註解的名稱和標誌。

7.10. 將Spring Data倉庫暴露爲REST端點

Spring Data REST可以將Repository的實現暴露爲REST端點,只要該應用啓用Spring MVC。

Spring Boot暴露一系列來自spring.data.rest命名空間的有用屬性來定製化RepositoryRestConfiguration。若是須要提供其餘定製,你能夠建立一個繼承自SpringBootRepositoryRestMvcConfiguration的@Configuration類。該類功能和RepositoryRestMvcConfiguration相同,但容許你繼續使用spring.data.rest.*屬性。

8. 數據庫初始化

一個數據庫可使用不一樣的方式進行初始化,這取決於你的技術棧。或者你能夠手動完成該任務,只要數據庫是單獨的過程。

8.1. 使用JPA初始化數據庫

JPA有個生成DDL的特性,這些能夠設置爲在數據庫啓動時運行。這能夠經過兩個外部屬性進行控制:

spring.jpa.generate-ddl(boolean)控制該特性的關閉和開啓,跟實現者不要緊
spring.jpa.hibernate.ddl-auto(enum)是一個Hibernate特性,用於更細力度的控制該行爲。更多詳情參考如下內容。

8.2. 使用Hibernate初始化數據庫

你能夠顯式設置spring.jpa.hibernate.ddl-auto,標準的Hibernate屬性值有none,validate,update,create,create-drop。Spring Boot根據你的數據庫是否爲內嵌數據庫來選擇相應的默認值,若是是內嵌型的則默認值爲create-drop,不然爲none。經過查看Connection類型能夠檢查是否爲內嵌型數據庫,hsqldb,h2和derby是內嵌的,其餘都不是。當從內存數據庫遷移到一個真正的數據庫時,你須要小心,在新的平臺中不能對數據庫表和數據是否存在進行臆斷。你也須要顯式設置ddl-auto,或使用其餘機制初始化數據庫。

此外,啓動時處於classpath根目錄下的import.sql文件會被執行。這在demos或測試時頗有用,但在生產環境中你可能不指望這樣。這是Hibernate的特性,和Spring沒有一點關係。

8.3. 使用Spring JDBC初始化數據庫

Spring JDBC有一個DataSource初始化特性。Spring Boot默認啓用了該特性,並從標準的位置schema.sql和data.sql(位於classpath根目錄)加載SQL。此外,Spring Boot將加載schema-${platform}.sql和data-${platform}.sql文件(若是存在),在這裏platform是spring.datasource.platform的值,好比,你能夠將它設置爲數據庫的供應商名稱(hsqldb, h2, Oracle, MySQL, postgresql等)。Spring Boot默認啓用Spring JDBC初始化快速失敗特性,因此若是腳本致使異常產生,那應用程序將啓動失敗。腳本的位置能夠經過設置spring.datasource.schema和spring.datasource.data來改變,若是設置spring.datasource.initialize=false則哪一個位置都不會被處理。

你能夠設置spring.datasource.continueOnError=true禁用快速失敗特性。一旦應用程序成熟並被部署了不少次,那該設置就頗有用,由於腳本能夠充當"可憐人的遷移"-例如,插入失敗時意味着數據已經存在,也就不必阻止應用繼續運行。

若是你想要在一個JPA應用中使用schema.sql,那若是Hibernate試圖建立相同的表,ddl-auto=create-drop將致使錯誤產生。爲了不那些錯誤,能夠將ddl-auto設置爲「」(推薦)或「none」。無論是否使用ddl-auto=create-drop,你總可使用data.sql初始化新數據。

8.4. 初始化Spring Batch數據庫

若是你正在使用Spring Batch,那麼它會爲大多數的流行數據庫平臺預裝SQL初始化腳本。Spring Boot會檢測你的數據庫類型,並默認執行那些腳本,在這種狀況下將關閉快速失敗特性(錯誤被記錄但不會阻止應用啓動)。這是由於那些腳本是可信任的,一般不會包含bugs,因此錯誤會被忽略掉,而且對錯誤的忽略可讓腳本具備冪等性。你可使用spring.batch.initializer.enabled=false顯式關閉初始化功能。

8.5. 使用一個高級別的數據遷移工具

Spring Boot跟高級別的數據遷移工具Flyway(基於SQL)和Liquibase(XML)工做的很好。一般咱們傾向於Flyway,由於它一眼看去好像很容易,另外它一般不須要平臺獨立:通常一個或至多須要兩個平臺。

8.5.1. 啓動時執行Flyway數據庫遷移

想要在啓動時自動運行Flyway數據庫遷移,須要將org.flywaydb:flyway-core添加到你的classpath下。

遷移是一些V_.sql格式的腳本(是一個下劃線分割的版本號,好比'1'或'21')。默認狀況下,它們存放在一個classpath:db/migration的文件夾中,但你可使用flyway.locations(一個列表)來改變它。詳情可參考flyway-core中的Flyway類,查看一些可用的配置,好比schemas。Spring Boot在FlywayProperties中提供了一個小的屬性集,可用於禁止遷移,或關閉位置檢測。

默認狀況下,Flyway將自動注入(@Primary)DataSource到你的上下文,並用它進行數據遷移。若是你想使用一個不一樣的DataSource,你能夠建立一個,並將它標記爲@FlywayDataSource的@Bean-若是你這樣作了,且想要兩個數據源,記得建立另外一個並將它標記爲@Primary。或者你能夠經過在外部配置文件中設置flyway.[url,user,password]來使用Flyway的原生DataSource。

這是一個Flyway示例,你能夠做爲參考。

8.5.2. 啓動時執行Liquibase數據庫遷移

想要在啓動時自動運行Liquibase數據庫遷移,你須要將org.liquibase:liquibase-core添加到classpath下。

主改變日誌(master change log)默認從db/changelog/db.changelog-master.yaml讀取,但你可使用liquibase.change-log進行設置。詳情查看LiquibaseProperties以獲取可用設置,好比上下文,默認的schema等。

這裏有個Liquibase示例可做爲參考。

9. 批處理應用

9.1. 在啓動時執行Spring Batch做業

你能夠在上下文的某個地方添加@EnableBatchProcessing來啓用Spring Batch的自動配置功能。

默認狀況下,在啓動時它會執行應用的全部做業(Jobs),具體查看JobLauncherCommandLineRunner。你能夠經過指定spring.batch.job.names(多個做業名以逗號分割)來縮小到一個特定的做業或多個做業。

若是應用上下文包含一個JobRegistry,那麼處於spring.batch.job.names中的做業將會從registry中查找,而不是從上下文中自動裝配。這是複雜系統中常見的一個模式,在這些系統中多個做業被定義在子上下文和註冊中心。

具體參考BatchAutoConfiguration和@EnableBatchProcessing。

10. 執行器(Actuator)

10.1. 改變HTTP端口或執行器端點的地址

在一個單獨的應用中,執行器的HTTP端口默認和主HTTP端口相同。想要讓應用監聽不一樣的端口,你能夠設置外部屬性management.port。爲了監聽一個徹底不一樣的網絡地址(好比,你有一個用於管理的內部網絡和一個用於用戶應用程序的外部網絡),你能夠將management.address設置爲一個可用的IP地址,而後將服務器綁定到該地址。

查看ManagementServerProperties源碼和'Production-ready特性'章節中的Section 41.3, 「Customizing the management server port」來獲取更多詳情。

10.2. 自定義'白標'(whitelabel,能夠了解下相關理念)錯誤頁面

Spring Boot安裝了一個'whitelabel'錯誤頁面,若是你遇到一個服務器錯誤(機器客戶端消費的是JSON,其餘媒體類型則會看到一個具備正確錯誤碼的合乎情理的響應),那就能在客戶端瀏覽器中看到該頁面。你能夠設置error.whitelabel.enabled=false來關閉該功能,但一般你想要添加本身的錯誤頁面來取代whitelabel。確切地說,如何實現取決於你使用的模板技術。例如,你正在使用Thymeleaf,你將添加一個error.html模板。若是你正在使用FreeMarker,那你將添加一個error.ftl模板。一般,你須要的只是一個名稱爲error的View,和/或一個處理/error路徑的@Controller。除非你替換了一些默認配置,不然你將在你的ApplicationContext中找到一個BeanNameViewResolver,因此一個id爲error的@Bean多是完成該操做的一個簡單方式。詳情參考ErrorMvcAutoConfiguration。

查看Error Handling章節,瞭解下如何將處理器(handlers)註冊到servlet容器中。

11. 安全

11.1. 關閉Spring Boot安全配置

無論你在應用的什麼地方定義了一個使用@EnableWebSecurity註解的@Configuration,它將會關閉Spring Boot中的默認webapp安全設置。想要調整默認值,你能夠嘗試設置security.*屬性(具體查看SecurityProperties和常見應用屬性的SECURITY章節)。

11.2. 改變AuthenticationManager並添加用戶帳號

若是你提供了一個AuthenticationManager類型的@Bean,那麼默認的就不會被建立了,因此你能夠得到Spring Security可用的所有特性(好比,不一樣的認證選項)。

Spring Security也提供了一個方便的AuthenticationManagerBuilder,可用於構建具備常見選項的AuthenticationManager。在一個webapp中,推薦將它注入到WebSecurityConfigurerAdapter的一個void方法中,好比:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                .withUser("barry").password("password").roles("USER"); // ... etc.
    }

    // ... other stuff for application security
}

若是把它放到一個內部類或一個單獨的類中,你將獲得最好的結果(也就是不跟不少其餘@Beans混合在一塊兒將容許你改變實例化的順序)。secure web sample是一個有用的參考模板。

若是你遇到了實例化問題(好比,使用JDBC或JPA進行用戶詳細信息的存儲),那將AuthenticationManagerBuilder回調提取到一個GlobalAuthenticationConfigurerAdapter(放到init()方法內以防其餘地方也須要authentication manager)多是個不錯的選擇,好比:

@Configuration
public class AuthenticationManagerConfiguration extends

    GlobalAuthenticationConfigurerAdapter {
    @Override
    public void init(AuthenticationManagerBuilder auth) {
        auth.inMemoryAuthentication() // ... etc.
    }

}

11.3. 當前端使用代理服務器時,啓用HTTPS

對於任何應用來講,確保全部的主端點(URL)都只在HTTPS下可用是個重要的苦差事。若是你使用Tomcat做爲servlet容器,那Spring Boot若是發現一些環境設置的話,它將自動添加Tomcat本身的RemoteIpValve,你也能夠依賴於HttpServletRequest來報告是否請求是安全的(即便代理服務器的downstream處理真實的SSL終端)。這個標準行爲取決於某些請求頭是否出現(x-forwarded-for和x-forwarded-proto),這些請求頭的名稱都是約定好的,因此對於大多數前端和代理都是有效的。

你能夠向application.properties添加如下設置裏開啓該功能,好比:

server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto

(這些屬性出現一個就會開啓該功能,或者你能夠經過添加一個TomcatEmbeddedServletContainerFactory bean本身添加RemoteIpValve)

Spring Security也能夠配置成針對因此或某些請求須要一個安全渠道(channel)。想要在一個Spring Boot應用中開啓它,你只需將application.properties中的security.require_ssl設置爲true便可。

  1. 熱交換 =======

12.1. 從新加載靜態內容

Spring Boot有不少用於熱加載的選項。使用IDE開發是一個不錯的方式,特別是須要調試的時候(全部的現代IDEs都容許從新加載靜態資源,一般也支持對變動的Java類進行熱交換)。Maven和Gradle插件也支持命令行下的靜態文件熱加載。若是你使用其餘高級工具編寫css/js,並使用外部的css/js編譯器,那你就能夠充分利用該功能。

12.2. 在不重啓容器的狀況下從新加載Thymeleaf模板

若是你正在使用Thymeleaf,那就將spring.thymeleaf.cache設置爲false。查看ThymeleafAutoConfiguration能夠獲取其餘Thymeleaf自定義選項。

12.3. 在不重啓容器的狀況下從新加載FreeMarker模板

若是你正在使用FreeMarker,那就將spring.freemarker.cache設置爲false。查看FreeMarkerAutoConfiguration 能夠獲取其餘FreeMarker自定義選項。

12.4. 在不重啓容器的狀況下從新加載Groovy模板

若是你正在使用Groovy模板,那就將spring.groovy.template.cache設置爲false。查看GroovyTemplateAutoConfiguration能夠獲取其餘Groovy自定義選項。

12.5. 在不重啓容器的狀況下從新加載Velocity模板

若是你正在使用Velocity,那就將spring.velocity.cache設置爲false。查看VelocityAutoConfiguration能夠獲取其餘Velocity自定義選項。

12.6. 在不重啓容器的狀況下從新加載Java類

現代IDEs(Eclipse, IDEA等)都支持字節碼的熱交換,因此若是你作了一個沒有影響類或方法簽名的改變,它會利索地從新加載並無任何影響。

Spring Loaded在這方面走的更遠,它可以從新加載方法簽名改變的類定義。若是對它進行一些自定義配置能夠強制ApplicationContext刷新本身(但沒有通用的機制來確保這對一個運行中的應用老是安全的,因此它可能只是一個開發時間的技巧)。

12.6.1. 使用Maven配置Spring Loaded

爲了在Maven命令行下使用Spring Loaded,你只需將它做爲一個依賴添加到Spring Boot插件聲明中便可,好比:

org.springframework.boot spring-boot-maven-plugin org.springframework springloaded 1.2.0.RELEASE 正常狀況下,這在Eclipse和IntelliJ中工做的至關漂亮,只要它們有相應的,和Maven默認一致的構建配置(Eclipse m2e對此支持的更好,開箱即用)。

13 構建

13.1. 使用Maven自定義依賴版本

若是你使用Maven進行一個直接或間接繼承spring-boot-dependencies(好比spring-boot-starter-parent)的構建,並想覆蓋一個特定的第三方依賴,那你能夠添加合適的元素。瀏覽spring-boot-dependencies POM能夠獲取一個全面的屬性列表。例如,想要選擇一個不一樣的slf4j版本,你能夠添加如下內容:

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

注:這隻在你的Maven項目繼承(直接或間接)自spring-boot-dependencies纔有用。若是你使用import,將spring-boot-dependencies添加到本身的dependencyManagement片斷,那你必須本身從新定義artifact而不是覆蓋屬性。

注:每一個Spring Boot發佈都是基於一些特定的第三方依賴集進行設計和測試的,覆蓋版本可能致使兼容性問題。

13.2. 使用Maven建立可執行JAR

spring-boot-maven-plugin可以用來建立可執行的'胖'JAR。若是你正在使用spring-boot-starter-parent POM,你能夠簡單地聲明該插件,而後你的jar將被從新打包:

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

若是沒有使用parent POM,你仍舊可使用該插件。不過,你須要另外添加一個片斷:

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

查看插件文檔獲取詳細的用例。

13.3. 建立其餘的可執行JAR

若是你想將本身的項目以library jar的形式被其餘項目依賴,而且須要它是一個可執行版本(例如demo),你須要使用略微不一樣的方式來配置該構建。

對於Maven來講,正常的JAR插件和Spring Boot插件都有一個'classifier',你能夠添加它來建立另外的JAR。示例以下(使用Spring Boot Starter Parent管理插件版本,其餘配置採用默認設置):

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

上述配置會產生兩個jars,默認的一個和使用帶有classifier 'exec'的Boot插件構建的可執行的一個。

對於Gradle用戶來講,步驟相似。示例以下:

bootRepackage  {
    classifier = 'exec'
}

13.4. 在可執行jar運行時提取特定的版本

在一個可執行jar中,爲了運行,多數內嵌的庫不須要拆包(unpacked),然而有一些庫可能會遇到問題。例如,JRuby包含它本身的內嵌jar,它假定jruby-complete.jar自己老是可以直接做爲文件訪問的。

爲了處理任何有問題的庫,你能夠標記那些特定的內嵌jars,讓它們在可執行jar第一次運行時自動解壓到一個臨時文件夾中。例如,爲了將JRuby標記爲使用Maven插件拆包,你須要添加以下的配置:

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

使用Gradle徹底上述操做:

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

13.6. 遠程調試一個使用Maven啓動的Spring Boot項目

想要爲使用Maven啓動的Spring Boot應用添加一個遠程調試器,你可使用mave插件的jvmArguments屬性。詳情參考示例。

13.7. 遠程調試一個使用Gradle啓動的Spring Boot項目

想要爲使用Gradle啓動的Spring Boot應用添加一個遠程調試器,你可使用build.gradle的applicationDefaultJvmArgs屬性或--debug-jvm命令行選項。

build.gradle:

applicationDefaultJvmArgs = [
    "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
]

命令行:

$ gradle run --debug-jvm

詳情查看Gradle應用插件。

13.9. 如何使用Java6

若是想在Java6環境中使用Spring Boot,你須要改變一些配置。具體的變化取決於你應用的功能。

13.9.1. 內嵌Servlet容器兼容性

若是你在使用Boot的內嵌Servlet容器,你須要使用一個兼容Java6的容器。Tomcat 7和Jetty 8都是Java 6兼容的。具體參考Section 63.15, 「Use Tomcat 7」和Section 63.16, 「Use Jetty 8」。

13.9.2. JTA API兼容性

Java事務API自身並不要求Java 7,而是官方的API jar包含的已構建類要求Java 7。若是你正在使用JTA,那麼你須要使用可以在Java 6工做的構建版本替換官方的JTA 1.2 API jar。爲了完成該操做,你須要排除任何對javax.transaction:javax.transaction-api的傳遞依賴,並使用org.jboss.spec.javax.transaction:jboss-transaction-api1.2spec:1.0.0.Final依賴替換它們。

14 傳統部署

14.1. 建立一個可部署的war文件

產生一個可部署war包的第一步是提供一個SpringBootServletInitializer子類,並覆蓋它的configure方法。這充分利用了Spring框架對Servlet 3.0的支持,並容許你在應用經過servlet容器啓動時配置它。一般,你只需把應用的主類改成繼承SpringBootServletInitializer便可:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

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

}

下一步是更新你的構建配置,這樣你的項目將產生一個war包而不是jar包。若是你使用Maven,並使用spring-boot-starter-parent(爲了配置Maven的war插件),全部你須要作的就是更改pom.xml的packaging爲war:

<packaging>war</packaging>

若是你使用Gradle,你須要修改build.gradle來將war插件應用到項目上:

apply plugin: 'war'

該過程最後的一步是確保內嵌的servlet容器不能干擾war包將部署的servlet容器。爲了達到這個目的,你須要將內嵌容器的依賴標記爲provided。

若是使用Maven:

<dependencies>
    <!-- … -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- … -->
</dependencies>

若是使用Gradle:

dependencies {
    // …
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    // …
}

若是你使用Spring Boot構建工具,將內嵌容器依賴標記爲provided將產生一個可執行war包,在lib-provided目錄有該war包的provided依賴。這意味着,除了部署到servlet容器,你還能夠經過使用命令行java -jar命令來運行應用。

注:查看Spring Boot基於以上配置的一個Maven示例應用。

14.2. 爲老的servlet容器建立一個可部署的war文件

老的Servlet容器不支持在Servlet 3.0中使用的ServletContextInitializer啓動處理。你仍舊能夠在這些容器使用Spring和Spring Boot,但你須要爲應用添加一個web.xml,並將它配置爲經過一個DispatcherServlet加載一個ApplicationContext。

14.3. 將現有的應用轉換爲Spring Boot

對於一個非web項目,轉換爲Spring Boot應用很容易(拋棄建立ApplicationContext的代碼,取而代之的是調用SpringApplication或SpringApplicationBuilder)。Spring MVC web應用一般先建立一個可部署的war應用,而後將它遷移爲一個可執行的war或jar。建議閱讀Getting Started Guide on Converting a jar to a war.。

經過繼承SpringBootServletInitializer建立一個可執行war(好比,在一個名爲Application的類中),而後添加Spring Boot的@EnableAutoConfiguration註解。示例:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        // Customize the application or call application.sources(...) to add sources
        // Since our example is itself a @Configuration class we actually don't
        // need to override this method.
        return application;
    }

}

記住無論你往sources放什麼東西,它僅是一個Spring ApplicationContext,正常狀況下,任何生效的在這裏也會起做用。有一些beans你能夠先移除,而後讓Spring Boot提供它的默認實現,不過有可能須要先完成一些事情。

靜態資源能夠移到classpath根目錄下的/public(或/static,/resources,/META-INF/resources)。一樣的方式也適合於messages.properties(Spring Boot在classpath根目錄下自動發現這些配置)。

美妙的(Vanilla usage of)Spring DispatcherServlet和Spring Security不須要改變。若是你的應用有其餘特性,好比使用其餘servlets或filters,那你可能須要添加一些配置到你的Application上下文中,按如下操做替換web.xml的那些元素:

在容器中安裝一個Servlet或ServletRegistrationBean類型的@Bean,就好像web.xml中的和<servlet-mapping/>。 一樣的添加一個Filter或FilterRegistrationBean類型的@Bean(相似於和<filter-mapping/>)。 在XML文件中的ApplicationContext能夠經過@Import添加到你的Application中。簡單的狀況下,大量使用註解配置能夠在幾行內定義@Bean定義。 一旦war可使用,咱們就經過添加一個main方法到Application來讓它能夠執行,好比:

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

應用能夠劃分爲多個類別:

沒有web.xml的Servlet 3.0+應用
有web.xml的應用
有上下文層次的應用
沒有上下文層次的應用
全部這些均可以進行適當的轉化,但每一個可能須要稍微不一樣的技巧。

Servlet 3.0+的應用轉化的至關簡單,若是它們已經使用Spring Servlet 3.0+初始化器輔助類。一般全部來自一個存在的WebApplicationInitializer的代碼能夠移到一個SpringBootServletInitializer中。若是一個存在的應用有多個ApplicationContext(好比,若是它使用AbstractDispatcherServletInitializer),那你能夠將全部上下文源放進一個單一的SpringApplication。你遇到的主要難題多是若是那樣不能工做,那你就要維護上下文層次。參考示例entry on building a hierarchy。一個存在的包含web相關特性的父上下文一般須要分解,這樣全部的ServletContextAware組件都處於子上下文中。

對於還不是Spring應用的應用來講,上面的指南有助於你把應用轉換爲一個Spring Boot應用,但你也能夠選擇其餘方式。

14.4. 部署WAR到Weblogic

想要將Spring Boot應用部署到Weblogic,你須要確保你的servlet初始化器直接實現WebApplicationInitializer(即便你繼承的基類已經實現了它)。

一個傳統的Weblogic初始化器可能以下所示:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

}

若是使用logback,你須要告訴Weblogic你傾向使用的打包版本而不是服務器預裝的版本。你能夠經過添加一個具備以下內容的WEB-INF/weblogic.xml實現該操做:

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
    xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
        http://xmlns.oracle.com/weblogic/weblogic-web-app
        http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
    <wls:container-descriptor>
        <wls:prefer-application-packages>
            <wls:package-name>org.slf4j</wls:package-name>
        </wls:prefer-application-packages>
    </wls:container-descriptor>
</wls:weblogic-web-app>
相關文章
相關標籤/搜索