Spring Boot 參考指南
介紹
轉(zhuǎn)載自:https://www.gitbook.com/book/qbgbook/spring-boot-reference-guide-zh/details
帶目錄瀏覽地址:http://www.maoyupeng.com/spring-boot-api.html
1.Spring Boot文檔
本節(jié)提供一個Spring Boot參考文檔的簡明概述。你可以把它作為文檔其余部分的導(dǎo)航号杠。你可以從頭到尾依次閱讀該參考指南,或跳過你不感興趣的章節(jié)枝哄。
1.1關(guān)于本文檔
Spring Boot參考指南有html,pdf和epub形式的文檔。在docs.spring.io/spring-boot/docs/current/reference可獲取到最新的副本番挺。
在對副本不收取任何費用姆坚,并且不管是打印還是電子版每個副本都包含版權(quán)聲明的情況下,你可以自己使用本文檔副本岸裙,也可以分發(fā)給其他人猖败。
開始
如果你想從總體上對Spring Boot或Spring入門,本章節(jié)就是為你準(zhǔn)備的降允!在這里恩闻,我們將回答基本的"what?","how?"和"why?"問題剧董。你會發(fā)現(xiàn)一個溫雅的Spring Boot介紹及安裝指南幢尚。然后我們構(gòu)建第一個Spring Boot應(yīng)用矿筝,并討論一些我們需要遵循的核心原則端铛。
2.1 Spring Boot介紹
Spring Boot使開發(fā)獨立的,產(chǎn)品級別的基于Spring的應(yīng)用變得非常簡單潮尝,你只需"just run"毅臊。 我們?yōu)镾pring平臺及第三方庫提供開箱即用的設(shè)置理茎,這樣你就可以有條不紊地開始。多數(shù)Spring Boot應(yīng)用需要很少的Spring配置管嬉。
你可以使用Spring Boot創(chuàng)建Java應(yīng)用皂林,并使用java -jar啟動它或采用傳統(tǒng)的war部署方式。我們也提供了一個運(yùn)行"spring腳本"的命令行工具蚯撩。
我們主要的目標(biāo)是:
- 為所有的Spring開發(fā)提供一個從根本上更快的和廣泛使用的入門經(jīng)驗础倍。
- 開箱即用,但你可以通過不采用默認(rèn)設(shè)置來擺脫這種方式胎挎。
- 提供一系列大型項目常用的非功能性特征(比如沟启,內(nèi)嵌服務(wù)器忆家,安全,指標(biāo)德迹,健康檢測芽卿,外部化配置)。
- 絕對不需要代碼生成及XML配置浦辨。
2.2 系統(tǒng)要求
默認(rèn)情況下蹬竖,Spring Boot 1.3.0.BUILD-SNAPSHOT 需要Java7和Spring框架4.1.3或以上。你可以在Java6下使用Spring Boot流酬,不過需要添加額外配置币厕。具體參考Section 73.9, “How to use Java 6” 。構(gòu)建環(huán)境明確支持的有Maven(3.2+)和Gradle(1.12+)芽腾。
注:盡管你可以在Java6或Java7環(huán)境下使用Spring Boot旦装,通常我們建議你如果可能的話就使用Java8。
2.2.1 Servlet容器
下列內(nèi)嵌容器支持開箱即用(out of the box):
名稱 | Servlet版本 | Java版本 |
---|---|---|
Tomcat 8 | 3.1 | Java 7+ |
Tomcat 7 | 3.0 | Java 6+ |
Jetty 9 | 3.1 | Java 7+ |
Jetty 8 | 3.0 | Java 6+ |
Undertow 1.1 | 3.1 | Java 7+ |
你也可以將Spring Boot應(yīng)用部署到任何兼容Servlet 3.0+的容器摊滔。
2.3 Spring Boot安裝
Spring Boot可以跟典型的Java開發(fā)工具一塊使用或安裝為一個命令行工具阴绢。不管怎樣,你將需要安裝Java SDK v1.6 或更高版本艰躺。在開始之前呻袭,你需要檢查下當(dāng)前安裝的Java版本:
$ java -version
如果你是一個Java新手,或你只是想體驗一下Spring Boot腺兴,你可能想先嘗試Spring Boot CLI左电,否則繼續(xù)閱讀經(jīng)典地安裝指南。
注:盡管Spring Boot兼容Java 1.6页响,如果可能的話篓足,你應(yīng)該考慮使用Java最新版本。
2.3.1 為Java開發(fā)者準(zhǔn)備的安裝指南
你可以像使用其他任何標(biāo)準(zhǔn)Java庫那樣使用Spring Boot闰蚕,只需簡單地在你的classpath下包含正確的spring-boot-*.jar文件栈拖。Spring Boot不需要集成任何特殊的工具,所以你可以使用任何IDE或文本編輯器没陡;Spring Boot應(yīng)用也沒有什么特殊之處涩哟,所以你可以像任何其他Java程序那樣運(yùn)行和調(diào)試。
盡管你可以拷貝Spring Boot jars盼玄,不過贴彼,我們通常推薦你使用一個支持依賴管理的構(gòu)建工具(比如Maven或Gradle)。
2.3.1.1 Maven安裝
Spring Boot兼容Apache Maven 3.2或更高版本强岸。如果沒有安裝Maven,你可以參考maven.apache.org指南砾赔。
注:在很多操作系統(tǒng)上蝌箍,你可以通過一個包管理器安裝Maven青灼。如果你是一個OSX Homebrew用戶,可以嘗試brew install maven妓盲。Ubuntu用戶可以運(yùn)行sudo apt-get install maven杂拨。
Spring Boot依賴的groupId為org.springframework.boot。通常你的Maven POM文件需要繼承spring-boot-starter-parent悯衬,然后聲明一個或多個“Starter POMs”依賴弹沽。Spring Boot也提供了一個用于創(chuàng)建可執(zhí)行jars的Maven插件。
下面是一個典型的pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.BUILD-SNAPSHOT</version>
</parent>
<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- Package as an executable jar -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!-- Add Spring repositories -->
<!-- (you don't need this if you are using a .RELEASE version) -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
注:spring-boot-starter-parent
是使用Spring Boot的一個不錯的方式筋粗,但它不總是合適的策橘。有時你需要繼承一個不同的parent POM,或者你可能只是不喜歡我們的默認(rèn)配置娜亿。查看Section 13.1.2, “Using Spring Boot without the parent POM”獲取使用import的替代解決方案丽已。
2.3.1.2 Gradle安裝
Spring Boot兼容Gradle 1.12或更高版本。如果沒有安裝Gradle买决,你可以參考www.gradle.org上的指南沛婴。
Spring Boot依賴可以使用org.springframework.boot group來聲明。通常督赤,你的項目將聲明一個或多個“Starter POMs”依賴嘁灯。Spring Boot提供一個用于簡化依賴聲明和創(chuàng)建可執(zhí)行jars的有用的Gradle插件。
注:當(dāng)你需要構(gòu)建一個項目時躲舌,Gradle Wrapper提供一個獲取Gradle的漂亮方式丑婿。它是一個伴隨你的代碼一塊提交的小腳本和庫,用于啟動構(gòu)建進(jìn)程孽糖。具體參考Gradle Wrapper枯冈。
下面是一個典型的build.gradle文件:
buildscript {
repositories {
jcenter()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.BUILD-SNAPSHOT")
}
}
apply plugin: 'java'
apply plugin: 'spring-boot'
jar {
baseName = 'myproject'
version = '0.0.1-SNAPSHOT'
}
repositories {
jcenter()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
2.3.2 Spring Boot CLI安裝
Spring Boot是一個命令行工具,用于使用Spring進(jìn)行快速原型搭建办悟。它允許你運(yùn)行Groovy腳本尘奏,這意味著你可以使用類Java的語法,并且沒有那么多的模板代碼病蛉。
你沒有必要為了使用Spring Boot而去用CLI炫加,但它絕對是助力Spring應(yīng)用的最快方式。
2.3.2.1 手動安裝
你可以從Spring軟件倉庫下載Spring CLI分發(fā)包:
spring-boot-cli-1.3.0.BUILD-SNAPSHOT-bin.zip
spring-boot-cli-1.3.0.BUILD-SNAPSHOT-bin.tar.gz
不穩(wěn)定的snapshot分發(fā)包也能獲取到铺然。
下載完成后俗孝,遵循解壓后的存檔里的INSTALL.txt操作指南進(jìn)行安裝。一般而言魄健,在.zip文件的bin/目錄下存在一個spring腳本(Windows下是spring.bat)赋铝,或者使用java -jar來運(yùn)行一個.jar文件(該腳本會幫你確定classpath被正確設(shè)置)。
2.3.2.2 使用GVM安裝
GVM(Groovy環(huán)境管理器)可以用來管理多種不同版本的Groovy和Java二進(jìn)制包沽瘦,包括Groovy自身和Spring Boot CLI革骨∨┘猓可以從gvmtool.net獲取gvm,并使用以下命令安裝Spring Boot:
$ gvm install springboot
$ spring --version
Spring Boot v1.3.0.BUILD-SNAPSHOT
如果你正在為CLI開發(fā)新的特性良哲,并想輕松獲取你剛構(gòu)建的版本盛卡,可以使用以下命令:
$ gvm install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-1.3.0.BUILD-SNAPSHOT-bin/spring-1.3.0.BUILD-SNAPSHOT/
$ gvm use springboot dev
$ spring --version
Spring CLI v1.3.0.BUILD-SNAPSHOT
這將會在你的gvm倉庫中安裝一個名叫dev的本地spring實例。它指向你的目標(biāo)構(gòu)建位置筑凫,所以每次你重新構(gòu)建Spring Boot滑沧,spring將會是最新的。
你可以通過以下命令來驗證:
$ gvm ls springboot
================================================================================
Available Springboot Versions
================================================================================
> + dev
* 1.3.0.BUILD-SNAPSHOT
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
2.3.2.3 使用OSX Homebrew進(jìn)行安裝
如果你的環(huán)境是Mac,并使用Homebrew,想要安裝Spring Boot CLI只需如下操作:
$ brew tap pivotal/tap
$ brew install springboot
Homebrew將把spring安裝到/usr/local/bin下隆嗅。
注:如果該方案不可用,可能是因為你的brew版本太老了殖属。你只需執(zhí)行brew update并重試即可。
2.3.2.4 使用MacPorts進(jìn)行安裝
如果你的環(huán)境是Mac瓦盛,并使用MacPorts洗显,想要安裝Spring Boot CLI只需如下操作:
$ sudo port install spring-boot-cli
2.3.2.5 命令行實現(xiàn)
Spring Boot CLI啟動腳本為BASH和zsh shells提供完整的命令行實現(xiàn)。你可以在任何shell中source腳本(名稱也是spring)原环,或?qū)⑺诺侥銈€人或系統(tǒng)范圍的bash實現(xiàn)初始化中挠唆。在一個Debian系統(tǒng)里,系統(tǒng)范圍的腳本位于/shell-completion/bash下嘱吗,當(dāng)一個新的shell啟動時該目錄下的所有腳本都被執(zhí)行玄组。想要手動運(yùn)行該腳本,例如谒麦,你已經(jīng)使用GVM進(jìn)行安裝了:
$ . ~/.gvm/springboot/current/shell-completion/bash/spring
$ spring
grab help jar run test version
注:如果你使用Homebrew或MacPorts安裝Spring Boot CLI俄讹,命令行實現(xiàn)腳本會自動注冊到你的shell。
2.3.2.6 Spring CLI示例快速入門
下面是一個相當(dāng)簡單的web應(yīng)用绕德,你可以用它測試你的安裝是否成功患膛。創(chuàng)建一個名叫app.groovy的文件:
@RestController
class ThisWillActuallyRun {
@RequestMapping("/")
String home() {
"Hello World!"
}
}
然后簡單地從一個shell中運(yùn)行它:
$ spring run app.groovy
注:當(dāng)你首次運(yùn)行該應(yīng)用時將會花費一點時間,因為需要下載依賴耻蛇。后續(xù)運(yùn)行將會快很多踪蹬。
在你最喜歡的瀏覽器中打開localhost:8080,然后你應(yīng)該看到以下輸出:
Hello World!
2.3.3 從Spring Boot早期版本升級
如果你正在升級一個Spring Boot早期版本臣咖,查看下放在project wiki上的"release notes"跃捣。你會發(fā)現(xiàn)每次發(fā)布的更新指南和一個"new and noteworthy"特性列表。
想要升級一個已安裝的CLI夺蛇,你需要使用合適的包管理命令(例如疚漆,brew upgrade),或如果你是手動安裝CLI,按照standard instructions操作并記得更新你的PATH環(huán)境變量以移除任何老的引用娶聘。
2.3.4 開發(fā)你的第一個Spring Boot應(yīng)用
讓我們使用Java開發(fā)一個簡單的"Hello World!" web應(yīng)用灵临,來強(qiáng)調(diào)下Spring Boot的一些關(guān)鍵特性。我們將使用Maven構(gòu)建該項目趴荸,因為大多數(shù)IDEs都支持它。
注:spring.io網(wǎng)站包含很多使用Spring Boot的"入門"指南宦焦。如果你正在找特定問題的解決方案发钝,可以先去那瞅瞅。
在開始前波闹,你需要打開一個終端酝豪,檢查是否安裝可用的Java版本和Maven:
$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
$ mvn -v
Apache Maven 3.2.3 (33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4; 2014-08-11T13:58:10-07:00)
Maven home: /Users/user/tools/apache-maven-3.1.1
Java version: 1.7.0_51, vendor: Oracle Corporation
注:該示例需要創(chuàng)建自己的文件夾。后續(xù)的操作假設(shè)你已創(chuàng)建一個合適的文件夾精堕,并且它是你的“當(dāng)前目錄”孵淘。
2.3.5 創(chuàng)建POM
我們需要以創(chuàng)建一個Maven pom.xml文件作為開始。該pom.xml是用來構(gòu)建項目的處方歹篓。打開你最喜歡的文本編輯器瘫证,然后添加以下內(nèi)容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.BUILD-SNAPSHOT</version>
</parent>
<!-- Additional lines to be added here... -->
<!-- (you don't need this if you are using a .RELEASE version) -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
這會給你一個可運(yùn)轉(zhuǎn)的構(gòu)建,你可以通過運(yùn)行mvn package測試它(現(xiàn)在你可以忽略"jar將是空的-沒有包含任何內(nèi)容庄撮!"的警告)背捌。
注:目前你可以將該項目導(dǎo)入一個IDE(大多數(shù)現(xiàn)代的Java IDE都包含對Maven的內(nèi)建支持)。簡單起見洞斯,我們將繼續(xù)使用普通的文本編輯器完成該示例毡庆。
2.3.6 添加classpath依賴
Spring Boot提供很多"Starter POMs",這能夠讓你輕松的將jars添加到你的classpath下烙如。我們的示例程序已經(jīng)在POM的partent節(jié)點使用了spring-boot-starter-parent么抗。spring-boot-starter-parent是一個特殊的starter,它提供了有用的Maven默認(rèn)設(shè)置亚铁。同時蝇刀,它也提供了一個dependency-management節(jié)點,這樣對于”blessed“依賴你可以省略version標(biāo)記刀闷。
其他的”Starter POMs“簡單的提供依賴熊泵,這些依賴可能是你開發(fā)特定類型的應(yīng)用時需要的。由于正在開發(fā)一個web應(yīng)用甸昏,我們將添加一個spring-boot-starter-web依賴-但在此之前顽分,讓我們看下目前所擁有的:
$ mvn dependency:tree
[INFO] com.example:myproject:jar:0.0.1-SNAPSHOT
mvn dependency:tree
命令以樹形表示來打印你的項目依賴。你可以看到spring-boot-starter-parent
本身并沒有提供依賴施蜜。編輯我們的pom.xml卒蘸,并在parent節(jié)點下添加spring-boot-starter-web
依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
如果再次運(yùn)行mvn dependency:tree
,你將看到現(xiàn)在有了一些其他依賴,包括Tomcat web服務(wù)器和Spring Boot自身缸沃。
2.3.7 編寫代碼
為了完成應(yīng)用程序恰起,我們需要創(chuàng)建一個單獨的Java文件。Maven默認(rèn)會編譯src/main/java
下的源碼趾牧,所以你需要創(chuàng)建那樣的文件結(jié)構(gòu)检盼,然后添加一個名為src/main/java/Example.java
的文件:
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;
@RestController
@EnableAutoConfiguration
public class Example {
@RequestMapping("/")
String home() {
return "Hello World!";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Example.class, args);
}
}
盡管這里沒有太多代碼,但很多事情正在發(fā)生翘单。讓我們分步探討重要的部分吨枉。
2.3.7.1 @RestController和@RequestMapping注解
我們的Example類上使用的第一個注解是@RestController。這被稱為一個構(gòu)造型(stereotype)注解哄芜。它為閱讀代碼的人們提供建議貌亭。對于Spring,該類扮演了一個特殊角色认臊。在本示例中圃庭,我們的類是一個web @Controller,所以當(dāng)處理進(jìn)來的web請求時失晴,Spring會詢問它剧腻。
@RequestMapping注解提供路由信息。它告訴Spring任何來自"/"路徑的HTTP請求都應(yīng)該被映射到home方法涂屁。@RestController注解告訴Spring以字符串的形式渲染結(jié)果恕酸,并直接返回給調(diào)用者。
注:@RestController和@RequestMapping注解是Spring MVC注解(它們不是Spring Boot的特定部分)胯陋。具體查看Spring參考文檔的MVC章節(jié)蕊温。
2.3.7.2 @EnableAutoConfiguration注解
第二個類級別的注解是@EnableAutoConfiguration。這個注解告訴Spring Boot根據(jù)添加的jar依賴猜測你想如何配置Spring遏乔。由于spring-boot-starter-web添加了Tomcat和Spring MVC义矛,所以auto-configuration將假定你正在開發(fā)一個web應(yīng)用并相應(yīng)地對Spring進(jìn)行設(shè)置。
Starter POMs和Auto-Configuration:設(shè)計auto-configuration的目的是更好的使用"Starter POMs"盟萨,但這兩個概念沒有直接的聯(lián)系凉翻。你可以自由地挑選starter POMs以外的jar依賴,并且Spring Boot將仍舊盡最大努力去自動配置你的應(yīng)用捻激。
2.3.7.3 main方法
我們的應(yīng)用程序最后部分是main方法制轰。這只是一個標(biāo)準(zhǔn)的方法,它遵循Java對于一個應(yīng)用程序入口點的約定胞谭。我們的main方法通過調(diào)用run垃杖,將業(yè)務(wù)委托給了Spring Boot的SpringApplication類。SpringApplication將引導(dǎo)我們的應(yīng)用丈屹,啟動Spring调俘,相應(yīng)地啟動被自動配置的Tomcat web服務(wù)器伶棒。我們需要將Example.class
作為參數(shù)傳遞給run方法來告訴SpringApplication誰是主要的Spring組件。為了暴露任何的命令行參數(shù)彩库,args數(shù)組也會被傳遞過去店归。
2.3.8 運(yùn)行示例
到此我們的應(yīng)用應(yīng)該可以工作了她按。由于使用了spring-boot-starter-parent
POM,這樣我們就有了一個非常有用的run目標(biāo)狠轻,我們可以用它啟動程序展氓。在項目根目錄下輸入mvn spring-boot:run
來啟動應(yīng)用:
$ mvn spring-boot:run
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.3.0.BUILD-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.222 seconds (JVM running for 6.514)
如果使用一個瀏覽器打開localhost:8080
侮繁,你應(yīng)該可以看到以下輸出:
Hello World!
點擊ctrl-c
溫雅地關(guān)閉應(yīng)用程序北秽。
2.3.9 創(chuàng)建一個可執(zhí)行jar
讓我們通過創(chuàng)建一個完全自包含的可執(zhí)行jar文件來結(jié)束我們的示例锄蹂,該jar文件可以在生產(chǎn)環(huán)境運(yùn)行√谷裕可執(zhí)行jars(有時候被成為胖jars "fat jars")是包含你的編譯后的類和你的代碼運(yùn)行所需的依賴jar的存檔。
可執(zhí)行jars和Java:Java沒有提供任何標(biāo)準(zhǔn)的加載內(nèi)嵌jar文件(即jar文件中還包含jar文件)的方法叨襟。如果你想發(fā)布一個自包含的應(yīng)用這就是一個問題繁扎。為了解決該問題,很多開發(fā)者采用"共享的"jars糊闽。一個共享的jar簡單地將來自所有jars的類打包進(jìn)一個單獨的“超級jar”梳玫。采用共享jar方式的問題是很難區(qū)分在你的應(yīng)用程序中可以使用哪些庫。在多個jars中如果存在相同的文件名(但內(nèi)容不一樣)也會是一個問題右犹。Spring Boot采取一個不同的途徑提澎,并允許你真正的內(nèi)嵌jars。
為了創(chuàng)建可執(zhí)行的jar念链,需要將spring-boot-maven-plugin添加到我們的pom.xml中盼忌。在dependencies節(jié)點下插入以下內(nèi)容:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
注:spring-boot-starter-paren
POM包含用于綁定repackage目標(biāo)的<executions>配置。如果你不使用parent POM掂墓,你將需要自己聲明該配置谦纱。具體參考插件文檔。
保存你的pom.xml君编,然后從命令行運(yùn)行mvn package
:
$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building myproject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] .... ..
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ myproject ---
[INFO] Building jar: /Users/developer/example/spring-boot-example/target/myproject-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:1.3.0.BUILD-SNAPSHOT:repackage (default) @ myproject ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
如果查看target目錄跨嘉,你應(yīng)該看到myproject-0.0.1-SNAPSHOT.jar。該文件應(yīng)該有10Mb左右的大小吃嘿。如果想偷看內(nèi)部結(jié)構(gòu)祠乃,你可以運(yùn)行jar tvf
:
$ jar tvf target/myproject-0.0.1-SNAPSHOT.jar
在target目錄下,你應(yīng)該也能看到一個很小的名為myproject-0.0.1-SNAPSHOT.jar.original的文件兑燥。這是在Spring Boot重新打包前Maven創(chuàng)建的原始jar文件亮瓷。
為了運(yùn)行該應(yīng)用程序,你可以使用java -jar
命令:
$ java -jar target/myproject-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.3.0.BUILD-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.536 seconds (JVM running for 2.864)
和以前一樣降瞳,點擊ctrl-c來溫柔地退出程序寺庄。
使用Spring Boot
本章節(jié)將會詳細(xì)介紹如何使用Spring Boot。它覆蓋了構(gòu)建系統(tǒng),自動配置和運(yùn)行/部署選項等主題斗塘。我們也覆蓋了一些Spring Boot最佳實踐赢织。盡管Spring Boot沒有什么特別的(只是一個你能消費的庫),但仍有一些建議馍盟,如果你遵循的話將會讓你的開發(fā)進(jìn)程更容易于置。
如果你剛接觸Spring Boot,那最好先讀下上一章節(jié)的Getting Started指南贞岭。
3.1 構(gòu)建系統(tǒng)
強(qiáng)烈建議你選擇一個支持依賴管理八毯,能消費發(fā)布到Maven中央倉庫的artifacts的構(gòu)建系統(tǒng)。我們推薦你選擇Maven或Gradle瞄桨。選擇其他構(gòu)建系統(tǒng)來使用Spring Boot也是可能的(比如Ant)话速,但它們不會被很好的支持。
3.1.1 Maven
Maven用戶可以繼承spring-boot-starter-parent項目來獲取合適的默認(rèn)設(shè)置芯侥。該父項目提供以下特性:
- 默認(rèn)編譯級別為Java 1.6
- 源碼編碼為UTF-8
- 一個依賴管理節(jié)點泊交,允許你省略普通依賴的<version>標(biāo)簽,繼承自spring-boot-dependencies POM柱查。
- 合適的資源過濾
- 合適的插件配置(exec插件廓俭,surefire,Git commit ID唉工,shade)
- 針對application.properties和application.yml的資源過濾
最后一點:由于默認(rèn)配置文件接收Spring風(fēng)格的占位符(${...}
)研乒,Maven filtering改用@..@
占位符(你可以使用Maven屬性resource.delimiter
來覆蓋它)。
3.1.1.1 繼承starter parent
想配置你的項目繼承spring-boot-starter-parent
只需要簡單地設(shè)置parent
為:
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.BUILD-SNAPSHOT</version>
</parent>
注:你應(yīng)該只需要在該依賴上指定Spring Boot版本淋硝。如果導(dǎo)入其他的starters雹熬,你可以放心的省略版本號。
3.1.1.2 使用沒有父POM的Spring Boot
不是每個人都喜歡繼承spring-boot-starter-parent
POM谣膳。你可能需要使用公司標(biāo)準(zhǔn)parent橄唬,或你可能傾向于顯式聲明所有Maven配置。
如果你不使用spring-boot-starter-parent
参歹,通過使用一個scope=import
的依賴仰楚,你仍能獲取到依賴管理的好處:
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.3.0.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.1.1.3 改變java版本
spring-boot-starter-parent
選擇相當(dāng)保守的Java兼容策略。如果你遵循我們的建議犬庇,使用最新的Java版本僧界,你可以添加一個java.version
屬性:
<properties>
<java.version>1.8</java.version>
</properties>
3.1.1.4 使用Spring Boot Maven插件
Spring Boot包含一個Maven插件,它可以將項目打包成一個可執(zhí)行jar臭挽。如果想使用它捂襟,你可以將該插件添加到<plugins>節(jié)點處:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
注:如果使用Spring Boot starter parent pom,你只需要添加該插件而無需配置它欢峰,除非你想改變定義在partent中的設(shè)置葬荷。
3.1.2 Gradle
Gradle用戶可以直接在它們的dependencies節(jié)點處導(dǎo)入”starter POMs“涨共。跟Maven不同的是,這里沒有用于導(dǎo)入共享配置的"超父"(super parent)宠漩。
apply plugin: 'java'
repositories { jcenter() }
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.3.0.BUILD-SNAPSHOT")
}
spring-boot-gradle-plugin插件也是可以使用的举反,它提供創(chuàng)建可執(zhí)行jar和從source運(yùn)行項目的任務(wù)。它也添加了一個ResolutionStrategy用于讓你省略常用依賴的版本號:
buildscript {
repositories { jcenter() }
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.BUILD-SNAPSHOT")
}
}
apply plugin: 'java'
apply plugin: 'spring-boot'
repositories { jcenter() }
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
3.1.3 Ant
使用Apache Ant構(gòu)建一個Spring Boot項目是完全可能的扒吁,然而火鼻,Spring Boot沒有為它提供特殊的支持或插件。Ant腳本可以使用Ivy依賴管理系統(tǒng)來導(dǎo)入starter POMs雕崩。
查看Section 73.8, “Build an executable archive with Ant”獲取更多指導(dǎo)魁索。
3.1.4 Starter POMs
Starter POMs是可以包含到應(yīng)用中的一個方便的依賴關(guān)系描述符集合。你可以獲取所有Spring及相關(guān)技術(shù)的一站式服務(wù)盼铁,而不需要翻閱示例代碼粗蔚,拷貝粘貼大量的依賴描述符。例如饶火,如果你想使用Spring和JPA進(jìn)行數(shù)據(jù)庫訪問鹏控,只需要在你的項目中包含spring-boot-starter-data-jpa
依賴,然后你就可以開始了趁窃。
該starters包含很多你搭建項目,快速運(yùn)行所需的依賴急前,并提供一致的醒陆,管理的傳遞依賴集。
名字有什么含義:所有的starters遵循一個相似的命名模式:spring-boot-starter-*
裆针,在這里*是一種特殊類型的應(yīng)用程序刨摩。該命名結(jié)構(gòu)旨在幫你找到需要的starter。很多IDEs集成的Maven允許你通過名稱搜索依賴世吨。例如澡刹,使用相應(yīng)的Eclipse或STS插件,你可以簡單地在POM編輯器中點擊ctrl-space耘婚,然后輸入"spring-boot-starter
"可以獲取一個完整列表罢浇。
下面的應(yīng)用程序starters是Spring Boot在org.springframework.boot
組下提供的:
Spring Boot application starters
名稱 | 描述 |
---|---|
spring-boot-starter | 核心Spring Boot starter,包括自動配置支持沐祷,日志和YAML |
spring-boot-starter-actuator | 生產(chǎn)準(zhǔn)備的特性嚷闭,用于幫你監(jiān)控和管理應(yīng)用 |
spring-boot-starter-amqp | 對"高級消息隊列協(xié)議"的支持史隆,通過spring-rabbit實現(xiàn) |
spring-boot-starter-aop | 對面向切面編程的支持谣妻,包括spring-aop和AspectJ |
spring-boot-starter-batch | 對Spring Batch的支持,包括HSQLDB數(shù)據(jù)庫 |
spring-boot-starter-cloud-connectors | 對Spring Cloud Connectors的支持葬凳,簡化在云平臺下(例如兢榨,Cloud Foundry 和Heroku)服務(wù)的連接 |
spring-boot-starter-data-elasticsearch | 對Elasticsearch搜索和分析引擎的支持嗅榕,包括spring-data-elasticsearch |
spring-boot-starter-data-gemfire | 對GemFire分布式數(shù)據(jù)存儲的支持顺饮,包括spring-data-gemfire |
spring-boot-starter-data-jpa | 對"Java持久化API"的支持,包括spring-data-jpa凌那,spring-orm和Hibernate |
spring-boot-starter-data-mongodb | 對MongoDB NOSQL數(shù)據(jù)庫的支持兼雄,包括spring-data-mongodb |
spring-boot-starter-data-rest | 對通過REST暴露Spring Data倉庫的支持,通過spring-data-rest-webmvc實現(xiàn) |
spring-boot-starter-data-solr | 對Apache Solr搜索平臺的支持案怯,包括spring-data-solr |
spring-boot-starter-freemarker | 對FreeMarker模板引擎的支持 |
spring-boot-starter-groovy-templates | 對Groovy模板引擎的支持 |
spring-boot-starter-hateoas | 對基于HATEOAS的RESTful服務(wù)的支持君旦,通過spring-hateoas實現(xiàn) |
spring-boot-starter-hornetq | 對"Java消息服務(wù)API"的支持,通過HornetQ實現(xiàn) |
spring-boot-starter-integration | 對普通spring-integration模塊的支持 |
spring-boot-starter-jdbc | 對JDBC數(shù)據(jù)庫的支持 |
spring-boot-starter-jersey | 對Jersey RESTful Web服務(wù)框架的支持 |
spring-boot-starter-jta-atomikos | 對JTA分布式事務(wù)的支持嘲碱,通過Atomikos實現(xiàn) |
spring-boot-starter-jta-bitronix | 對JTA分布式事務(wù)的支持金砍,通過Bitronix實現(xiàn) |
spring-boot-starter-mail | 對javax.mail的支持 |
spring-boot-starter-mobile | 對spring-mobile的支持 |
spring-boot-starter-mustache | 對Mustache模板引擎的支持 |
spring-boot-starter-redis | 對REDIS鍵值數(shù)據(jù)存儲的支持,包括spring-redis |
spring-boot-starter-security | 對spring-security的支持 |
spring-boot-starter-social-facebook | 對spring-social-facebook的支持 |
spring-boot-starter-social-linkedin | 對spring-social-linkedin的支持 |
spring-boot-starter-social-twitter | 對spring-social-twitter的支持 |
spring-boot-starter-test | 對常用測試依賴的支持麦锯,包括JUnit, Hamcrest和Mockito恕稠,還有spring-test模塊 |
spring-boot-starter-thymeleaf | 對Thymeleaf模板引擎的支持,包括和Spring的集成 |
spring-boot-starter-velocity | 對Velocity模板引擎的支持 |
spring-boot-starter-web | 對全棧web開發(fā)的支持扶欣,包括Tomcat和spring-webmvc |
spring-boot-starter-websocket | 對WebSocket開發(fā)的支持 |
spring-boot-starter-ws 對Spring | Web服務(wù)的支持 |
除了應(yīng)用程序的starters鹅巍,下面的starters可以用于添加生產(chǎn)準(zhǔn)備的特性。
Spring Boot生產(chǎn)準(zhǔn)備的starters
名稱 | 描述 |
---|---|
spring-boot-starter-actuator | 添加生產(chǎn)準(zhǔn)備特性料祠,比如指標(biāo)和監(jiān)控 |
spring-boot-starter-remote-shell | 添加遠(yuǎn)程ssh shell支持 |
最后骆捧,Spring Boot包含一些可用于排除或交換具體技術(shù)方面的starters。
Spring Boot technical starters
名稱 | 描述 |
---|---|
spring-boot-starter-jetty | 導(dǎo)入Jetty HTTP引擎(作為Tomcat的替代) |
spring-boot-starter-log4j | 對Log4J日志系統(tǒng)的支持 |
spring-boot-starter-logging | 導(dǎo)入Spring Boot的默認(rèn)日志系統(tǒng)(Logback) |
spring-boot-starter-tomcat | 導(dǎo)入Spring Boot的默認(rèn)HTTP引擎(Tomcat) |
spring-boot-starter-undertow | 導(dǎo)入Undertow HTTP引擎(作為Tomcat的替代) |
注:查看GitHub上位于spring-boot-starters
模塊內(nèi)的README文件髓绽,可以獲取到一個社區(qū)貢獻(xiàn)的其他starter POMs列表敛苇。
3.2 組織你的代碼
Spring Boot不需要使用任何特殊的代碼結(jié)構(gòu),然而顺呕,這里有一些有用的最佳實踐枫攀。
3.2.1 使用"default"包
當(dāng)類沒有包含package
聲明時,它被認(rèn)為處于default package
下株茶。通常不推薦使用default package
来涨,并應(yīng)該避免使用它。因為對于使用@ComponentScan
启盛,@EntityScan
或@SpringBootApplication
注解的Spring Boot應(yīng)用來說蹦掐,來自每個jar的類都會被讀取,這會造成一定的問題僵闯。
注:我們建議你遵循Java推薦的包命名規(guī)范笤闯,使用一個反轉(zhuǎn)的域名(例如com.example.project
)。
3.2.2 定位main應(yīng)用類
我們通常建議你將main應(yīng)用類放在位于其他類上面的根包(root package)中棍厂。通常使用@EnableAutoConfiguration
注解你的main類颗味,并且暗地里為某些項定義了一個基礎(chǔ)“search package
”。例如牺弹,如果你正在編寫一個JPA應(yīng)用浦马,被EnableAutoConfiguration
注解的類所在包將被用來搜索@Entity
項时呀。
使用根包允許你使用@ComponentScan
注解而不需要定義一個basePackage屬性。如果main類位于根包中晶默,你也可以使用@SpringBootApplication
注解谨娜。
下面是一個典型的結(jié)構(gòu):
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java
Application.java
文件將聲明main方法,還有基本的@Configuration
磺陡。
package com.example.myproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3.3 配置類
Spring Boot提倡基于Java的配置趴梢。盡管你可以使用一個XML源來調(diào)用SpringApplication.run()
,我們通常建議你使用@Configuration
類作為主要源币他。一般定義main方法的類也是主要@Configuration
的一個很好候選坞靶。
注:很多使用XML配置的Spring配置示例已經(jīng)被發(fā)布到網(wǎng)絡(luò)上。你應(yīng)該總是盡可能的使用基于Java的配置蝴悉。搜索查看enable*
注解就是一個好的開端彰阴。
3.3.1 導(dǎo)入其他配置類
你不需要將所有的@Configuration
放進(jìn)一個單獨的類。@Import
注解可以用來導(dǎo)入其他配置類拍冠。另外尿这,你也可以使用@ComponentScan
注解自動收集所有的Spring組件,包括@Configuration
類庆杜。
3.3.2 導(dǎo)入XML配置
如果你絕對需要使用基于XML的配置射众,我們建議你仍舊從一個@Configuration
類開始。你可以使用附加的@ImportResource
注解加載XML配置文件晃财。
3.4 自動配置
Spring Boot自動配置(auto-configuration
)嘗試根據(jù)你添加的jar依賴自動配置你的Spring應(yīng)用叨橱。例如,如果你的classpath下存在HSQLDB
拓劝,并且你沒有手動配置任何數(shù)據(jù)庫連接beans雏逾,那么我們將自動配置一個內(nèi)存型(in-memory)數(shù)據(jù)庫嘉裤。
你可以通過將@EnableAutoConfiguration
或@SpringBootApplication
注解添加到一個@Configuration
類上來選擇自動配置郑临。
注:你只需要添加一個@EnableAutoConfiguration
注解。我們建議你將它添加到主@Configuration
類上屑宠。
3.4.1 逐步替換自動配置
自動配置是非侵占性的厢洞,任何時候你都可以定義自己的配置類來替換自動配置的特定部分。例如典奉,如果你添加自己的DataSource
bean躺翻,默認(rèn)的內(nèi)嵌數(shù)據(jù)庫支持將不被考慮。
如果需要找出當(dāng)前應(yīng)用了哪些自動配置及應(yīng)用的原因卫玖,你可以使用--debug
開關(guān)啟動應(yīng)用公你。這將會記錄一個自動配置的報告并輸出到控制臺。
3.4.2 禁用特定的自動配置
如果發(fā)現(xiàn)應(yīng)用了你不想要的特定自動配置類假瞬,你可以使用@EnableAutoConfiguration
注解的排除屬性來禁用它們陕靠。
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;
@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
3.5 Spring Beans和依賴注入
你可以自由地使用任何標(biāo)準(zhǔn)的Spring框架技術(shù)去定義beans和它們注入的依賴迂尝。簡單起見,我們經(jīng)常使用@ComponentScan
注解搜索beans剪芥,并結(jié)合@Autowired
構(gòu)造器注入垄开。
如果使用上面建議的結(jié)構(gòu)組織代碼(將應(yīng)用類放到根包下),你可以添加@ComponentScan
注解而不需要任何參數(shù)税肪。你的所有應(yīng)用程序組件(@Component
, @Service
, @Repository
, @Controller
等)將被自動注冊為Spring Beans溉躲。
下面是一個@Service Bean
的示例,它使用構(gòu)建器注入獲取一個需要的RiskAssessor bean益兄。
package com.example.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DatabaseAccountService implements AccountService {
private final RiskAssessor riskAssessor;
@Autowired
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
注:注意如何使用構(gòu)建器注入來允許riskAssessor
字段被標(biāo)記為final
锻梳,這意味著riskAssessor
后續(xù)是不能改變的。
3.6 使用@SpringBootApplication注解
很多Spring Boot開發(fā)者總是使用@Configuration
偏塞,@EnableAutoConfiguration
和@ComponentScan
注解他們的main類唱蒸。由于這些注解被如此頻繁地一塊使用(特別是你遵循以上最佳實踐時),Spring Boot提供一個方便的@SpringBootApplication
選擇灸叼。
該@SpringBootApplication注解等價于以默認(rèn)屬性使用@Configuration
神汹,@EnableAutoConfiguration
和@ComponentScan
。
package com.example.myproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3.7 運(yùn)行應(yīng)用程序
將應(yīng)用打包成jar并使用一個內(nèi)嵌HTTP服務(wù)器的一個最大好處是古今,你可以像其他方式那樣運(yùn)行你的應(yīng)用程序屁魏。調(diào)試Spring Boot應(yīng)用也很簡單;你不需要任何特殊IDE或擴(kuò)展捉腥。
注:本章節(jié)只覆蓋基于jar的打包氓拼,如果選擇將應(yīng)用打包成war文件,你最好參考一下服務(wù)器和IDE文檔抵碟。
3.7.1 從IDE中運(yùn)行
你可以從IDE中運(yùn)行Spring Boot應(yīng)用桃漾,就像一個簡單的Java應(yīng)用乳怎,但是忍些,你首先需要導(dǎo)入項目。導(dǎo)入步驟跟你的IDE和構(gòu)建系統(tǒng)有關(guān)铝穷。大多數(shù)IDEs能夠直接導(dǎo)入Maven項目敦迄,例如Eclipse用戶可以選擇File菜單的Import…? --> Existing Maven Projects
恋追。
如果不能直接將項目導(dǎo)入IDE,你可以需要使用構(gòu)建系統(tǒng)生成IDE元數(shù)據(jù)罚屋。Maven有針對Eclipse和IDEA的插件苦囱;Gradle為各種IDEs提供插件。
注:如果意外地運(yùn)行一個web應(yīng)用兩次脾猛,你將看到一個"端口已在使用中"錯誤撕彤。為了確保任何存在的實例是關(guān)閉的,STS用戶可以使用Relaunch按鈕而不是Run按鈕猛拴。
3.7.2 作為一個打包后的應(yīng)用運(yùn)行
如果使用Spring Boot Maven或Gradle插件創(chuàng)建一個可執(zhí)行jar羹铅,你可以使用java -jar運(yùn)行你的應(yīng)用瞧柔。例如:
$ java -jar target/myproject-0.0.1-SNAPSHOT.jar
運(yùn)行一個打包的程序并開啟遠(yuǎn)程調(diào)試支持是可能的,這允許你將調(diào)試器附加到打包的應(yīng)用程序上:
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myproject-0.0.1-SNAPSHOT.jar
3.7.3 使用Maven插件運(yùn)行
Spring Boot Maven插件包含一個run目標(biāo)睦裳,它可以用來快速編譯和運(yùn)行應(yīng)用程序造锅。應(yīng)用程序以一種暴露的方式運(yùn)行,由于即時"熱"加載廉邑,你可以編輯資源哥蔚。
$ mvn spring-boot:run
你可能想使用有用的操作系統(tǒng)環(huán)境變量:
$ export MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128M -Djava.security.egd=file:/dev/./urandom
("egd"設(shè)置是通過為Tomcat提供一個更快的會話keys熵源來加速Tomcat的。)
3.7.4 使用Gradle插件運(yùn)行
Spring Boot Gradle插件也包含一個run目標(biāo)蛛蒙,它可以用來以暴露的方式運(yùn)行你的應(yīng)用程序糙箍。不管你什么時候?qū)?code>spring-boot-plugin,bootRun任務(wù)總是被添加進(jìn)去牵祟。
$ gradle bootRun
你可能想使用那些有用的操作系統(tǒng)環(huán)境變量:
$ export JAVA_OPTS=-Xmx1024m -XX:MaxPermSize=128M -Djava.security.egd=file:/dev/./urandom
3.7.5 熱交換
由于Spring Boot應(yīng)用程序只是普通的Java應(yīng)用深夯,那JVM熱交換(hot-swapping)應(yīng)該能出色的工作。JVM熱交換在它能替換的字節(jié)碼上有些限制诺苹,更全面的解決方案可以使用Spring Loaded項目或JRebel咕晋。
關(guān)于熱交換可以參考“How-to”相應(yīng)章節(jié)。
3.8 打包用于生產(chǎn)的應(yīng)用程序
可執(zhí)行jars可用于生產(chǎn)部署收奔。由于它們是自包含的掌呜,非常適合基于云的部署。關(guān)于其他“生產(chǎn)準(zhǔn)備”的特性坪哄,比如健康監(jiān)控质蕉,審計和指標(biāo)REST,或JMX端點翩肌,可以考慮添加spring-boot-actuator模暗。具體參考Part V, “Spring Boot Actuator: Production-ready features”。
Spring Boot特性
4.1 SpringApplication
SpringApplication類提供了一種從main()方法啟動Spring應(yīng)用的便捷方式念祭。在很多情況下兑宇,你只需委托給SpringApplication.run這個靜態(tài)方法:
public static void main(String[] args){
SpringApplication.run(MySpringConfiguration.class, args);
}
當(dāng)應(yīng)用啟動時,你應(yīng)該會看到類似下面的東西(這是何方神獸棒卷?顾孽?):
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v1.2.2.BUILD-SNAPSHOT
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
默認(rèn)情況下會顯示INFO級別的日志信息祝钢,包括一些相關(guān)的啟動詳情比规,比如啟動應(yīng)用的用戶等。
4.1.1 自定義Banner
通過在classpath下添加一個banner.txt或設(shè)置banner.location來指定相應(yīng)的文件可以改變啟動過程中打印的banner拦英。如果這個文件有特殊的編碼蜒什,你可以使用banner.encoding設(shè)置它(默認(rèn)為UTF-8)。
在banner.txt中可以使用如下的變量:
變量 | 描述 |
---|---|
${application.version} | MANIFEST.MF中聲明的應(yīng)用版本號疤估,例如1.0 |
${application.formatted-version} | MANIFEST.MF中聲明的被格式化后的應(yīng)用版本號(被括號包裹且以v作為前綴)灾常,用于顯示霎冯,例如(v1.0) |
${spring-boot.version} | 正在使用的Spring Boot版本號,例如1.2.2.BUILD-SNAPSHOT |
${spring-boot.formatted-version} | 正在使用的Spring Boot被格式化后的版本號(被括號包裹且以v作為前綴), 用于顯示钞瀑,例如(v1.2.2.BUILD-SNAPSHOT) |
注:如果想以編程的方式產(chǎn)生一個banner沈撞,可以使用SpringBootApplication.setBanner(…)方法。使用org.springframework.boot.Banner接口雕什,實現(xiàn)你自己的printBanner()方法缠俺。
4.1.2 自定義SpringApplication
如果默認(rèn)的SpringApplication不符合你的口味,你可以創(chuàng)建一個本地的實例并自定義它贷岸。例如壹士,關(guān)閉banner你可以這樣寫:
public static void main(String[] args){
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setShowBanner(false);
app.run(args);
}
注:傳遞給SpringApplication的構(gòu)造器參數(shù)是spring beans的配置源。在大多數(shù)情況下偿警,這些將是@Configuration類的引用躏救,但它們也可能是XML配置或要掃描包的引用。
你也可以使用application.properties文件來配置SpringApplication螟蒸。具體參考Externalized 配置盒使。查看配置選項的完整列表,可參考SpringApplication Javadoc.
4.1.3 流暢的構(gòu)建API
如果你需要創(chuàng)建一個分層的ApplicationContext(多個具有父子關(guān)系的上下文)七嫌,或你只是喜歡使用流暢的構(gòu)建API忠怖,你可以使用SpringApplicationBuilder。SpringApplicationBuilder允許你以鏈?zhǔn)椒绞秸{(diào)用多個方法抄瑟,包括可以創(chuàng)建層次結(jié)構(gòu)的parent和child方法凡泣。
new SpringApplicationBuilder()
.showBanner(false)
.sources(Parent.class)
.child(Application.class)
.run(args);
注:創(chuàng)建ApplicationContext層次時有些限制,比如皮假,Web組件(components)必須包含在子上下文(child context)中鞋拟,且相同的Environment即用于父上下文也用于子上下文中。具體參考SpringApplicationBuilder javadoc
4.1.4 Application事件和監(jiān)聽器
除了常見的Spring框架事件惹资,比如ContextRefreshedEvent贺纲,一個SpringApplication也發(fā)送一些額外的應(yīng)用事件。一些事件實際上是在ApplicationContext被創(chuàng)建前觸發(fā)的褪测。
你可以使用多種方式注冊事件監(jiān)聽器猴誊,最普通的是使用SpringApplication.addListeners(…)方法。在你的應(yīng)用運(yùn)行時侮措,應(yīng)用事件會以下面的次序發(fā)送:
- 在運(yùn)行開始懈叹,但除了監(jiān)聽器注冊和初始化以外的任何處理之前,會發(fā)送一個ApplicationStartedEvent分扎。
- 在Environment將被用于已知的上下文澄成,但在上下文被創(chuàng)建前,會發(fā)送一個ApplicationEnvironmentPreparedEvent。
- 在refresh開始前墨状,但在bean定義已被加載后卫漫,會發(fā)送一個ApplicationPreparedEvent。
- 啟動過程中如果出現(xiàn)異常肾砂,會發(fā)送一個ApplicationFailedEvent列赎。
注:你通常不需要使用應(yīng)用程序事件,但知道它們的存在會很方便(在某些場合可能會使用到)镐确。在Spring內(nèi)部粥谬,Spring Boot使用事件處理各種各樣的任務(wù)。
4.1.5 Web環(huán)境
一個SpringApplication將嘗試為你創(chuàng)建正確類型的ApplicationContext辫塌。在默認(rèn)情況下漏策,使用AnnotationConfigApplicationContext或AnnotationConfigEmbeddedWebApplicationContext取決于你正在開發(fā)的是否是web應(yīng)用。
用于確定一個web環(huán)境的算法相當(dāng)簡單(基于是否存在某些類)臼氨。如果需要覆蓋默認(rèn)行為掺喻,你可以使用setWebEnvironment(boolean webEnvironment)。通過調(diào)用setApplicationContextClass(…)储矩,你可以完全控制ApplicationContext的類型感耙。
注:當(dāng)JUnit測試?yán)锸褂肧pringApplication時,調(diào)用setWebEnvironment(false)是可取的持隧。
4.1.6 命令行啟動器
如果你想獲取原始的命令行參數(shù)即硼,或一旦SpringApplication啟動,你需要運(yùn)行一些特定的代碼,你可以實現(xiàn)CommandLineRunner接口。在所有實現(xiàn)該接口的Spring beans上將調(diào)用run(String… args)方法芦瘾。
import org.springframework.boot.*
import org.springframework.stereotype.*
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
如果一些CommandLineRunner beans被定義必須以特定的次序調(diào)用绽媒,你可以額外實現(xiàn)org.springframework.core.Ordered接口或使用org.springframework.core.annotation.Order注解浩蓉。
4.1.7 Application退出
每個SpringApplication在退出時為了確保ApplicationContext被優(yōu)雅的關(guān)閉,將會注冊一個JVM的shutdown鉤子。所有標(biāo)準(zhǔn)的Spring生命周期回調(diào)(比如,DisposableBean接口或@PreDestroy注解)都能使用绝编。
此外,如果beans想在應(yīng)用結(jié)束時返回一個特定的退出碼(exit code)貌踏,可以實現(xiàn)org.springframework.boot.ExitCodeGenerator接口十饥。
4.2 外化配置
Spring Boot允許外化(externalize)你的配置,這樣你能夠在不同的環(huán)境下使用相同的代碼祖乳。你可以使用properties文件逗堵,YAML文件,環(huán)境變量和命令行參數(shù)來外化配置凡资。使用@Value注解砸捏,可以直接將屬性值注入到你的beans中,并通過Spring的Environment抽象或綁定到結(jié)構(gòu)化對象來訪問隙赁。
Spring Boot使用一個非常特別的PropertySource次序來允許對值進(jìn)行合理的覆蓋垦藏,需要以下面的次序考慮屬性:
- 命令行參數(shù)
- 來自于java:comp/env的JNDI屬性
- Java系統(tǒng)屬性(System.getProperties())
- 操作系統(tǒng)環(huán)境變量
- 只有在random.*里包含的屬性會產(chǎn)生一個RandomValuePropertySource
- 在打包的jar外的應(yīng)用程序配置文件(application.properties,包含YAML和profile變量)
- 在打包的jar內(nèi)的應(yīng)用程序配置文件(application.properties伞访,包含YAML和profile變量)
- 在@Configuration類上的@PropertySource注解
- 默認(rèn)屬性(使用SpringApplication.setDefaultProperties指定)
下面是一個具體的示例(假設(shè)你開發(fā)一個使用name屬性的@Component):
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
你可以將一個application.properties文件捆綁到j(luò)ar內(nèi)掂骏,用來提供一個合理的默認(rèn)name屬性值。當(dāng)運(yùn)行在生產(chǎn)環(huán)境時厚掷,可以在jar外提供一個application.properties文件來覆蓋name屬性弟灼。對于一次性的測試,你可以使用特定的命令行開關(guān)啟動(比如冒黑,java -jar app.jar --name="Spring")田绑。
4.2.1 配置隨機(jī)值
RandomValuePropertySource在注入隨機(jī)值(比如,密鑰或測試用例)時很有用抡爹。它能產(chǎn)生整數(shù)掩驱,longs或字符串,比如:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
random.int*語法是OPEN value (,max) CLOSE冬竟,此處OPEN欧穴,CLOSE可以是任何字符,并且value泵殴,max是整數(shù)涮帘。如果提供max,那么value是最小的值笑诅,max是最大的值(不包含在內(nèi))调缨。
4.2.2 訪問命令行屬性
默認(rèn)情況下,SpringApplication將任何可選的命令行參數(shù)(以'--'開頭吆你,比如同蜻,--server.port=9000)轉(zhuǎn)化為property,并將其添加到Spring Environment中早处。如上所述湾蔓,命令行屬性總是優(yōu)先于其他屬性源。
如果你不想將命令行屬性添加到Environment里砌梆,你可以使用SpringApplication.setAddCommandLineProperties(false)來禁止它們默责。
4.2.3 Application屬性文件
SpringApplication將從以下位置加載application.properties文件,并把它們添加到Spring Environment中:
- 當(dāng)前目錄下的一個/config子目錄
- 當(dāng)前目錄
- 一個classpath下的/config包
- classpath根路徑(root)
這個列表是按優(yōu)先級排序的(列表中位置高的將覆蓋位置低的)咸包。
注:你可以使用YAML('.yml')文件替代'.properties'桃序。
如果不喜歡將application.properties作為配置文件名,你可以通過指定spring.config.name環(huán)境屬性來切換其他的名稱烂瘫。你也可以使用spring.config.location環(huán)境屬性來引用一個明確的路徑(目錄位置或文件路徑列表以逗號分割)媒熊。
$ java -jar myproject.jar --spring.config.name=myproject
//or
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
如果spring.config.location包含目錄(相對于文件)奇适,那它們應(yīng)該以/結(jié)尾(在加載前,spring.config.name產(chǎn)生的名稱將被追加到后面)芦鳍。不管spring.config.location是什么值嚷往,默認(rèn)的搜索路徑classpath:,classpath:/config,file:,file:config/總會被使用。以這種方式柠衅,你可以在application.properties中為應(yīng)用設(shè)置默認(rèn)值皮仁,然后在運(yùn)行的時候使用不同的文件覆蓋它,同時保留默認(rèn)配置菲宴。
注:如果你使用環(huán)境變量而不是系統(tǒng)配置贷祈,大多數(shù)操作系統(tǒng)不允許以句號分割(period-separated)的key名稱,但你可以使用下劃線(underscores)代替(比如喝峦,使用SPRING_CONFIG_NAME代替spring.config.name)势誊。如果你的應(yīng)用運(yùn)行在一個容器中,那么JNDI屬性(java:comp/env)或servlet上下文初始化參數(shù)可以用來取代環(huán)境變量或系統(tǒng)屬性谣蠢,當(dāng)然也可以使用環(huán)境變量或系統(tǒng)屬性键科。
4.2.4 特定的Profile屬性
除了application.properties文件,特定配置屬性也能通過命令慣例application-{profile}.properties來定義漩怎。特定Profile屬性從跟標(biāo)準(zhǔn)application.properties相同的路徑加載勋颖,并且特定profile文件會覆蓋默認(rèn)的配置。
4.2.5 屬性占位符
當(dāng)application.properties里的值被使用時勋锤,它們會被存在的Environment過濾饭玲,所以你能夠引用先前定義的值(比如,系統(tǒng)屬性)叁执。
app.name=MyApp
app.description=${app.name} is a Spring Boot application
注:你也能使用相應(yīng)的技巧為存在的Spring Boot屬性創(chuàng)建'短'變量茄厘,具體參考Section 63.3, “Use ‘short’ command line arguments”。
4.2.6 使用YAML代替Properties
YAML是JSON的一個超集谈宛,也是一種方便的定義層次配置數(shù)據(jù)的格式次哈。無論你何時將SnakeYAML 庫放到classpath下,SpringApplication類都會自動支持YAML作為properties的替換吆录。
注:如果你使用'starter POMs'窑滞,spring-boot-starter會自動提供SnakeYAML。
4.2.6.1 加載YAML
Spring框架提供兩個便利的類用于加載YAML文檔恢筝,YamlPropertiesFactoryBean會將YAML作為Properties來加載哀卫,YamlMapFactoryBean會將YAML作為Map來加載。
示例:
environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App
上面的YAML文檔會被轉(zhuǎn)化到下面的屬性中:
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]間接引用作為屬性keys的形式撬槽,例如下面的YAML:
my:
servers:
- dev.bar.com
- foo.bar.com
將會轉(zhuǎn)化到下面的屬性中:
my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com
使用Spring DataBinder工具綁定那樣的屬性(這是@ConfigurationProperties做的事)此改,你需要確定目標(biāo)bean中有個java.util.List或Set類型的屬性,并且需要提供一個setter或使用可變的值初始化它侄柔,比如共啃,下面的代碼將綁定上面的屬性:
@ConfigurationProperties(prefix="my")
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}
}
4.2.6.2 在Spring環(huán)境中使用YAML暴露屬性
YamlPropertySourceLoader類能夠用于將YAML作為一個PropertySource導(dǎo)出到Sprig Environment占调。這允許你使用熟悉的@Value注解和占位符語法訪問YAML屬性。
4.2.6.3 Multi-profile YAML文檔
你可以在單個文件中定義多個特定配置(profile-specific)的YAML文檔移剪,并通過一個spring.profiles key標(biāo)示應(yīng)用的文檔究珊。例如:
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
server:
address: 192.168.1.120
在上面的例子中,如果development配置被激活挂滓,那server.address屬性將是127.0.0.1苦银。如果development和production配置(profiles)沒有啟用啸胧,則該屬性的值將是192.168.1.100赶站。
4.2.6.4 YAML缺點
YAML文件不能通過@PropertySource注解加載。所以纺念,在這種情況下贝椿,如果需要使用@PropertySource注解的方式加載值,那就要使用properties文件陷谱。
4.2.7 類型安全的配置屬性
使用@Value("${property}")注解注入配置屬性有時可能比較笨重烙博,特別是需要使用多個properties或你的數(shù)據(jù)本身有層次結(jié)構(gòu)。為了控制和校驗?zāi)愕膽?yīng)用配置烟逊,Spring Boot提供一個允許強(qiáng)類型beans的替代方法來使用properties渣窜。
示例:
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
private String username;
private InetAddress remoteAddress;
// ... getters and setters
}
當(dāng)@EnableConfigurationProperties注解應(yīng)用到你的@Configuration時,任何被@ConfigurationProperties注解的beans將自動被Environment屬性配置宪躯。這種風(fēng)格的配置特別適合與SpringApplication的外部YAML配置進(jìn)行配合使用。
# application.yml
connection:
username: admin
remoteAddress: 192.168.1.1
# additional configuration as required
為了使用@ConfigurationProperties beans,你可以使用與其他任何bean相同的方式注入它們操软。
@Service
public class MyService {
@Autowired
private ConnectionSettings connection;
//...
@PostConstruct
public void openConnection() {
Server server = new Server();
this.connection.configure(server);
}
}
你可以通過在@EnableConfigurationProperties注解中直接簡單的列出屬性類來快捷的注冊@ConfigurationProperties bean的定義遗嗽。
@Configuration
@EnableConfigurationProperties(ConnectionSettings.class)
public class MyConfiguration {
}
注:使用@ConfigurationProperties能夠產(chǎn)生可被IDEs使用的元數(shù)據(jù)文件。具體參考Appendix B, Configuration meta-data臣缀。
4.2.7.1 第三方配置
正如使用@ConfigurationProperties注解一個類坝橡,你也可以在@Bean方法上使用它。當(dāng)你需要綁定屬性到不受你控制的第三方組件時精置,這種方式非常有用计寇。
為了從Environment屬性配置一個bean,將@ConfigurationProperties添加到它的bean注冊過程:
@ConfigurationProperties(prefix = "foo")
@Bean
public FooComponent fooComponent() {
...
}
和上面ConnectionSettings的示例方式相同脂倦,任何以foo為前綴的屬性定義都會被映射到FooComponent上饲常。
4.2.7.2 松散的綁定(Relaxed binding)
Spring Boot使用一些寬松的規(guī)則用于綁定Environment屬性到@ConfigurationProperties beans,所以Environment屬性名和bean屬性名不需要精確匹配狼讨。常見的示例中有用的包括虛線分割(比如贝淤,context--path綁定到contextPath)和將環(huán)境屬性轉(zhuǎn)為大寫字母(比如,PORT綁定port)政供。
示例:
@Component
@ConfigurationProperties(prefix="person")
public class ConnectionSettings {
private String firstName;
}
下面的屬性名都能用于上面的@ConfigurationProperties類:
屬性 | 說明 |
---|---|
person.firstName | 標(biāo)準(zhǔn)駝峰規(guī)則 |
person.first-name | 虛線表示播聪,推薦用于.properties和.yml文件中 |
PERSON_FIRST_NAME | 大寫形式朽基,使用系統(tǒng)環(huán)境變量時推薦 |
Spring會嘗試強(qiáng)制外部的應(yīng)用屬性在綁定到@ConfigurationProperties beans時類型是正確的。如果需要自定義類型轉(zhuǎn)換离陶,你可以提供一個ConversionService bean(bean id為conversionService)或自定義屬性編輯器(通過一個CustomEditorConfigurer bean)稼虎。
4.2.7.3 @ConfigurationProperties校驗
Spring Boot將嘗試校驗外部的配置,默認(rèn)使用JSR-303(如果在classpath路徑中)招刨。你可以輕松的為你的@ConfigurationProperties類添加JSR-303 javax.validation約束注解:
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
@NotNull
private InetAddress remoteAddress;
// ... getters and setters
}
你也可以通過創(chuàng)建一個叫做configurationPropertiesValidator的bean來添加自定義的Spring Validator霎俩。
注:spring-boot-actuator模塊包含一個暴露所有@ConfigurationProperties beans的端點。簡單地將你的web瀏覽器指向/configprops或使用等效的JMX端點沉眶。具體參考Production ready features打却。
4.3 Profiles
Spring Profiles提供了一種隔離應(yīng)用程序配置的方式,并讓這些配置只能在特定的環(huán)境下生效谎倔。任何@Component或@Configuration都能被@Profile標(biāo)記柳击,從而限制加載它的時機(jī)。
@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
以正常的Spring方式片习,你可以使用一個spring.profiles.active的Environment屬性來指定哪個配置生效捌肴。你可以使用平常的任何方式來指定該屬性,例如藕咏,可以將它包含到你的application.properties中:
spring.profiles.active=dev,hsqldb
或使用命令行開關(guān):
--spring.profiles.active=dev,hsqldb
4.3.1 添加激活的配置(profiles)
spring.profiles.active屬性和其他屬性一樣都遵循相同的排列規(guī)則状知,最高的PropertySource獲勝。也就是說孽查,你可以在application.properties中指定生效的配置饥悴,然后使用命令行開關(guān)替換它們。
有時卦碾,將特定的配置屬性添加到生效的配置中而不是替換它們是有用的铺坞。spring.profiles.include屬性可以用來無條件的添加生效的配置。SpringApplication的入口點也提供了一個用于設(shè)置額外配置的Java API(比如洲胖,在那些通過spring.profiles.active屬性生效的配置之上):參考setAdditionalProfiles()方法济榨。
示例:當(dāng)一個應(yīng)用使用下面的屬性,并用--spring.profiles.active=prod開關(guān)運(yùn)行绿映,那proddb和prodmq配置也會生效:
---
my.property: fromyamlfile
---
spring.profiles: prod
spring.profiles.include: proddb,prodmq
注:spring.profiles屬性可以定義到一個YAML文檔中擒滑,用于決定什么時候該文檔被包含進(jìn)配置中。具體參考Section 63.6, “Change configuration depending on the environment”
4.3.2 以編程方式設(shè)置profiles
在應(yīng)用運(yùn)行前叉弦,你可以通過調(diào)用SpringApplication.setAdditionalProfiles(…)方法丐一,以編程的方式設(shè)置生效的配置。使用Spring的ConfigurableEnvironment接口激動配置也是可行的淹冰。
4.3.3 Profile特定配置文件
application.properties(或application.yml)和通過@ConfigurationProperties引用的文件這兩種配置特定變種都被當(dāng)作文件來加載的库车,具體參考Section 23.3, “Profile specific properties”。
4.5 日志
Spring Boot內(nèi)部日志系統(tǒng)使用的是Commons Logging樱拴,但開放底層的日志實現(xiàn)柠衍。默認(rèn)為會Java Util Logging, Log4J, Log4J2和Logback提供配置洋满。每種情況下都會預(yù)先配置使用控制臺輸出,也可以使用可選的文件輸出珍坊。
默認(rèn)情況下牺勾,如果你使用'Starter POMs',那么就會使用Logback記錄日志阵漏。為了確保那些使用Java Util Logging, Commons Logging, Log4J或SLF4J的依賴庫能夠正常工作驻民,正確的Logback路由也被包含進(jìn)來。
注:如果上面的列表看起來令人困惑履怯,不要擔(dān)心回还,Java有很多可用的日志框架。通常虑乖,你不需要改變?nèi)罩疽蕾嚺城鳎琒pring Boot默認(rèn)的就能很好的工作晾虑。
4.4.1 日志格式
Spring Boot默認(rèn)的日志輸出格式如下:
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: [/*]
輸出的節(jié)點(items)如下:
- 日期和時間 - 精確到毫秒疹味,且易于排序。
- 日志級別 - ERROR, WARN, INFO, DEBUG 或 TRACE帜篇。
- Process ID糙捺。
- 一個用于區(qū)分實際日志信息開頭的---分隔符。
- 線程名 - 包括在方括號中(控制臺輸出可能會被截斷)笙隙。
- 日志名 - 通常是源class的類名(縮寫)洪灯。
- 日志信息。
4.4.2 控制臺輸出
默認(rèn)的日志配置會在寫日志消息時將它們回顯到控制臺竟痰。默認(rèn)签钩,ERROR, WARN和INFO級別的消息會被記錄』悼欤可以在啟動應(yīng)用時铅檩,通過--debug標(biāo)識開啟控制臺的DEBUG級別日志記錄。
$ java -jar myapp.jar --debug
如果你的終端支持ANSI莽鸿,為了增加可讀性將會使用彩色的日志輸出昧旨。你可以設(shè)置spring.output.ansi.enabled為一個支持的值來覆蓋自動檢測。
4.4.3 文件輸出
默認(rèn)情況下祥得,Spring Boot只會將日志記錄到控制臺而不會寫進(jìn)日志文件兔沃。如果除了輸出到控制臺你還想寫入到日志文件,那你需要設(shè)置logging.file或logging.path屬性(例如在你的application.properties中)级及。
下表顯示如何組合使用logging.*
:
logging.file | logging.path | 示例 | 描述 |
---|---|---|---|
(none) | (none) | 只記錄到控制臺 | |
Specific file | (none) | my.log | 寫到特定的日志文件里乒疏,名稱可以是一個精確的位置或相對于當(dāng)前目錄 |
(none) | Specific folder | /var/log | 寫到特定文件夾下的spring.log里,名稱可以是一個精確的位置或相對于當(dāng)前目錄 |
日志文件每達(dá)到10M就會被輪換(分割)饮焦,和控制臺一樣怕吴,默認(rèn)記錄ERROR, WARN和INFO級別的信息入偷。
4.4.4 日志級別
所有支持的日志系統(tǒng)在Spring的Environment(例如在application.properties里)都有通過'logging.level.*=LEVEL'('LEVEL'是TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF中的一個)設(shè)置的日志級別。
示例:application.properties
logging.level.org.springframework.web: DEBUG
logging.level.org.hibernate: ERROR
4.4.5 自定義日志配置
通過將適當(dāng)?shù)膸焯砑拥絚lasspath械哟,可以激活各種日志系統(tǒng)疏之。然后在classpath的根目錄(root)或通過Spring Environment的logging.config屬性指定的位置提供一個合適的配置文件來達(dá)到進(jìn)一步的定制(注意由于日志是在ApplicationContext被創(chuàng)建之前初始化的,所以不可能在Spring的@Configuration文件中暇咆,通過@PropertySources控制日志锋爪。系統(tǒng)屬性和平常的Spring Boot外部配置文件能正常工作)。
根據(jù)你的日志系統(tǒng)爸业,下面的文件會被加載:
日志系統(tǒng) | 定制 |
---|---|
Logback | logback.xml |
Log4j | log4j.properties或log4j.xml |
Log4j2 | log4j2.xml |
JDK (Java Util Logging) | logging.properties |
為了幫助定制一些其他的屬性其骄,從Spring的Envrionment轉(zhuǎn)換到系統(tǒng)屬性:
Spring Environment | System Property | 評價 |
---|---|---|
logging.file | LOG_FILE | 如果定義,在默認(rèn)的日志配置中使用 |
logging.path | LOG_PATH | 如果定義扯旷,在默認(rèn)的日志配置中使用 |
PID | PID | 當(dāng)前的處理進(jìn)程(process)ID(如果能夠被發(fā)現(xiàn)且還沒有作為操作系統(tǒng)環(huán)境變量被定義) |
所有支持的日志系統(tǒng)在解析它們的配置文件時都能查詢系統(tǒng)屬性拯爽。具體可以參考spring-boot.jar中的默認(rèn)配置。
注:在運(yùn)行可執(zhí)行的jar時钧忽,Java Util Logging有類加載問題毯炮,我們建議你盡可能避免使用它。
4.5 開發(fā)web應(yīng)用
Spring Boot非常適合開發(fā)web應(yīng)用程序耸黑。你可以使用內(nèi)嵌的Tomcat桃煎,Jetty或Undertow輕輕松松地創(chuàng)建一個HTTP服務(wù)器棉圈。大多數(shù)的web應(yīng)用都使用spring-boot-starter-web模塊進(jìn)行快速搭建和運(yùn)行决乎。
4.5.1 Spring Web MVC 框架
Spring Web MVC框架(通常簡稱為"Spring MVC")是一個富"模型复颈,視圖歹茶,控制器"的web框架福荸。 Spring MVC允許你創(chuàng)建特定的@Controller或@RestController beans來處理傳入的HTTP請求焕窝。 使用@RequestMapping注解可以將控制器中的方法映射到相應(yīng)的HTTP請求菌赖。
示例:
@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) {
// ...
}
}
4.5.1.1 Spring MVC自動配置
Spring Boot為Spring MVC提供適用于多數(shù)應(yīng)用的自動配置功能汗贫。在Spring默認(rèn)基礎(chǔ)上伴郁,自動配置添加了以下特性:
- 引入ContentNegotiatingViewResolver和BeanNameViewResolver beans耿战。
- 對靜態(tài)資源的支持,包括對WebJars的支持蛾绎。
- 自動注冊Converter昆箕,GenericConverter,F(xiàn)ormatter beans租冠。
- 對HttpMessageConverters的支持鹏倘。
- 自動注冊MessageCodeResolver。
- 對靜態(tài)index.html的支持顽爹。
- 對自定義Favicon的支持纤泵。
如果想全面控制Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc對其注解捏题。如果想保留Spring Boot MVC的特性玻褪,并只是添加其他的MVC配置(攔截器,formatters公荧,視圖控制器等)带射,你可以添加自己的WebMvcConfigurerAdapter類型的@Bean(不使用@EnableWebMvc注解)。
4.5.1.2 HttpMessageConverters
Spring MVC使用HttpMessageConverter接口轉(zhuǎn)換HTTP請求和響應(yīng)循狰。合理的缺省值被包含的恰到好處(out of the box)窟社,例如對象可以自動轉(zhuǎn)換為JSON(使用Jackson庫)或XML(如果Jackson XML擴(kuò)展可用則使用它,否則使用JAXB)绪钥。字符串默認(rèn)使用UTF-8編碼灿里。
如果需要添加或自定義轉(zhuǎn)換器,你可以使用Spring Boot的HttpMessageConverters類:
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);
}
}
任何在上下文中出現(xiàn)的HttpMessageConverter bean將會添加到converters列表程腹,你可以通過這種方式覆蓋默認(rèn)的轉(zhuǎn)換器(converters)匣吊。
4.5.1.3 MessageCodesResolver
Spring MVC有一個策略,用于從綁定的errors產(chǎn)生用來渲染錯誤信息的錯誤碼:MessageCodesResolver寸潦。如果設(shè)置spring.mvc.message-codes-resolver.format
屬性為PREFIX_ERROR_CODE
或POSTFIX_ERROR_CODE
(具體查看DefaultMessageCodesResolver.Format
枚舉值)色鸳,Spring Boot會為你創(chuàng)建一個MessageCodesResolver。
4.5.1.4 靜態(tài)內(nèi)容
默認(rèn)情況下甸祭,Spring Boot從classpath下一個叫/static(/public缕碎,/resources或/META-INF/resources)的文件夾或從ServletContext根目錄提供靜態(tài)內(nèi)容褥影。這使用了Spring MVC的ResourceHttpRequestHandler池户,所以你可以通過添加自己的WebMvcConfigurerAdapter并覆寫addResourceHandlers方法來改變這個行為(加載靜態(tài)文件)。
在一個單獨的web應(yīng)用中凡怎,容器默認(rèn)的servlet是開啟的校焦,如果Spring決定不處理某些請求,默認(rèn)的servlet作為一個回退(降級)將從ServletContext根目錄加載內(nèi)容统倒。大多數(shù)時候寨典,這不會發(fā)生(除非你修改默認(rèn)的MVC配置),因為Spring總能夠通過DispatcherServlet處理請求房匆。
此外耸成,上述標(biāo)準(zhǔn)的靜態(tài)資源位置有個例外情況是Webjars內(nèi)容。任何在/webjars/**路徑下的資源都將從jar文件中提供浴鸿,只要它們以Webjars的格式打包井氢。
注:如果你的應(yīng)用將被打包成jar,那就不要使用src/main/webapp文件夾岳链。盡管該文件夾是一個共同的標(biāo)準(zhǔn)花竞,但它僅在打包成war的情況下起作用,并且如果產(chǎn)生一個jar掸哑,多數(shù)構(gòu)建工具都會靜悄悄的忽略它约急。
4.5.1.5 模板引擎
正如REST web服務(wù)零远,你也可以使用Spring MVC提供動態(tài)HTML內(nèi)容。Spring MVC支持各種各樣的模板技術(shù)厌蔽,包括Velocity, FreeMarker和JSPs牵辣。很多其他的模板引擎也提供它們自己的Spring MVC集成。
Spring Boot為以下的模板引擎提供自動配置支持:
注:如果可能的話奴饮,應(yīng)該忽略JSPs服猪,因為在內(nèi)嵌的servlet容器使用它們時存在一些已知的限制。
當(dāng)你使用這些引擎的任何一種拐云,并采用默認(rèn)的配置罢猪,你的模板將會從src/main/resources/templates目錄下自動加載。
注:IntelliJ IDEA根據(jù)你運(yùn)行應(yīng)用的方式會對classpath進(jìn)行不同的整理叉瘩。在IDE里通過main方法運(yùn)行你的應(yīng)用跟從Maven或Gradle或打包好的jar中運(yùn)行相比會導(dǎo)致不同的順序膳帕。這可能導(dǎo)致Spring Boot不能從classpath下成功地找到模板。如果遇到這個問題薇缅,你可以在IDE里重新對classpath進(jìn)行排序危彩,將模塊的類和資源放到第一位∮捐耄或者汤徽,你可以配置模塊的前綴為classpath*:/templates/,這樣會查找classpath下的所有模板目錄灸撰。
4.5.1.6 錯誤處理
Spring Boot默認(rèn)提供一個/error映射用來以合適的方式處理所有的錯誤谒府,并且它在servlet容器中注冊了一個全局的 錯誤頁面。對于機(jī)器客戶端(相對于瀏覽器而言浮毯,瀏覽器偏重于人的行為)完疫,它會產(chǎn)生一個具有詳細(xì)錯誤,HTTP狀態(tài)债蓝,異常信息的JSON響應(yīng)壳鹤。對于瀏覽器客戶端,它會產(chǎn)生一個白色標(biāo)簽樣式(whitelabel)的錯誤視圖饰迹,該視圖將以HTML格式顯示同樣的數(shù)據(jù)(可以添加一個解析為erro的View來自定義它)芳誓。為了完全替換默認(rèn)的行為,你可以實現(xiàn)ErrorController啊鸭,并注冊一個該類型的bean定義锹淌,或簡單地添加一個ErrorAttributes類型的bean以使用現(xiàn)存的機(jī)制,只是替換顯示的內(nèi)容莉掂。
如果在某些條件下需要比較多的錯誤頁面葛圃,內(nèi)嵌的servlet容器提供了一個統(tǒng)一的Java DSL(領(lǐng)域特定語言)來自定義錯誤處理。 示例:
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer(){
return new MyCustomizer();
}
// ...
private static class MyCustomizer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
}
}
你也可以使用常規(guī)的Spring MVC特性來處理錯誤,比如@ExceptionHandler方法和@ControllerAdvice库正。ErrorController將會撿起任何沒有處理的異常曲楚。
N.B. 如果你為一個路徑注冊一個ErrorPage,最終被一個過濾器(Filter)處理(對于一些非Spring web框架褥符,像Jersey和Wicket這很常見)龙誊,然后過濾器需要顯式注冊為一個ERROR分發(fā)器(dispatcher)。
@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter());
...
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
return registration;
}
注:默認(rèn)的FilterRegistrationBean沒有包含ERROR分發(fā)器類型喷楣。
4.5.1.7 Spring HATEOAS
如果你正在開發(fā)一個使用超媒體的RESTful API趟大,Spring Boot將為Spring HATEOAS提供自動配置,這在多數(shù)應(yīng)用中都工作良好铣焊。自動配置替換了對使用@EnableHypermediaSupport的需求逊朽,并注冊一定數(shù)量的beans來簡化構(gòu)建基于超媒體的應(yīng)用,這些beans包括一個LinkDiscoverer和配置好的用于將響應(yīng)正確編排為想要的表示的ObjectMapper曲伊。ObjectMapper可以根據(jù)spring.jackson.*屬性或一個存在的Jackson2ObjectMapperBuilder bean進(jìn)行自定義叽讳。
通過使用@EnableHypermediaSupport,你可以控制Spring HATEOAS的配置坟募。注意這會禁用上述的對ObjectMapper的自定義岛蚤。
4.5.2 JAX-RS和Jersey
如果喜歡JAX-RS為REST端點提供的編程模型,你可以使用可用的實現(xiàn)替代Spring MVC懈糯。如果在你的應(yīng)用上下文中將Jersey 1.x和Apache Celtix的Servlet或Filter注冊為一個@Bean谤逼,那它們工作的相當(dāng)好瑰剃。Jersey 2.x有一些原生的Spring支持羡棵,所以我們會在Spring Boot為它提供自動配置支持沉御,連同一個啟動器(starter)。
想要開始使用Jersey 2.x只需要加入spring-boot-starter-jersey依賴蜂奸,然后你需要一個ResourceConfig類型的@Bean犁苏,用于注冊所有的端點(endpoints)。
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(Endpoint.class);
}
}
所有注冊的端點都應(yīng)該被@Components和HTTP資源annotations(比如@GET)注解扩所。
@Component
@Path("/hello")
public class Endpoint {
@GET
public String message() {
return "Hello";
}
}
由于Endpoint是一個Spring組件(@Component),所以它的生命周期受Spring管理朴乖,并且你可以使用@Autowired添加依賴及使用@Value注入外部配置祖屏。Jersey servlet將被注冊,并默認(rèn)映射到/*买羞。你可以將@ApplicationPath添加到ResourceConfig來改變該映射袁勺。
默認(rèn)情況下,Jersey將在一個ServletRegistrationBean類型的@Bean中被設(shè)置成名稱為jerseyServletRegistration的Servlet畜普。通過創(chuàng)建自己的相同名稱的bean期丰,你可以禁止或覆蓋這個bean。你也可以通過設(shè)置spring.jersey.type=filter來使用一個Filter代替Servlet(在這種情況下,被覆蓋或替換的@Bean是jerseyFilterRegistration)钝荡。該servlet有@Order屬性街立,你可以通過spring.jersey.filter.order進(jìn)行設(shè)置。不管是Servlet還是Filter注冊都可以使用spring.jersey.init.*定義一個屬性集合作為初始化參數(shù)傳遞過去埠通。
這里有一個Jersey示例赎离,你可以查看如何設(shè)置相關(guān)事項。
4.5.3 內(nèi)嵌servlet容器支持
Spring Boot支持內(nèi)嵌的Tomcat, Jetty和Undertow服務(wù)器端辱。多數(shù)開發(fā)者只需要使用合適的'Starter POM'來獲取一個完全配置好的實例即可梁剔。默認(rèn)情況下,內(nèi)嵌的服務(wù)器會在8080端口監(jiān)聽HTTP請求舞蔽。
4.5.3.1 Servlets和Filters
當(dāng)使用內(nèi)嵌的servlet容器時荣病,你可以直接將servlet和filter注冊為Spring的beans。在配置期間渗柿,如果你想引用來自application.properties的值众雷,這是非常方便的。默認(rèn)情況下做祝,如果上下文只包含單一的Servlet砾省,那它將被映射到根路徑(/)。在多Servlet beans的情況下混槐,bean的名稱將被用作路徑的前綴编兄。過濾器會被映射到/*。
如果基于約定(convention-based)的映射不夠靈活声登,你可以使用ServletRegistrationBean和FilterRegistrationBean類實現(xiàn)完全的控制狠鸳。如果你的bean實現(xiàn)了ServletContextInitializer接口,也可以直接注冊它們悯嗓。
4.5.3.2 EmbeddedWebApplicationContext
Spring Boot底層使用了一個新的ApplicationContext類型件舵,用于對內(nèi)嵌servlet容器的支持。EmbeddedWebApplicationContext是一個特殊類型的WebApplicationContext脯厨,它通過搜索一個單一的EmbeddedServletContainerFactory bean來啟動自己铅祸。通常,TomcatEmbeddedServletContainerFactory合武,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory將被自動配置临梗。
注:你通常不需要知道這些實現(xiàn)類。大多數(shù)應(yīng)用將被自動配置稼跳,并根據(jù)你的行為創(chuàng)建合適的ApplicationContext和EmbeddedServletContainerFactory盟庞。
4.5.3.3 自定義內(nèi)嵌servlet容器
常見的Servlet容器設(shè)置可以通過Spring Environment屬性進(jìn)行配置。通常汤善,你會把這些屬性定義到application.properties文件中什猖。 常見的服務(wù)器設(shè)置包括:
- server.port - 進(jìn)來的HTTP請求的監(jiān)聽端口號
- server.address - 綁定的接口地址
- server.sessionTimeout - session超時時間
具體參考ServerProperties票彪。
編程方式的自定義
如果需要以編程的方式配置內(nèi)嵌的servlet容器,你可以注冊一個實現(xiàn)EmbeddedServletContainerCustomizer接口的Spring bean不狮。EmbeddedServletContainerCustomizer提供對ConfigurableEmbeddedServletContainer的訪問降铸,ConfigurableEmbeddedServletContainer包含很多自定義的setter方法。
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
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方法遂黍,也提供了一些受保護(hù)的鉤子方法以滿足你的某些特殊需求终佛。具體參考相關(guān)文檔。
4.5.3.4 JSP的限制
在內(nèi)嵌的servlet容器中運(yùn)行一個Spring Boot應(yīng)用時(并打包成一個可執(zhí)行的存檔archive)雾家,容器對JSP的支持有一些限制铃彰。
- tomcat只支持war的打包方式,不支持可執(zhí)行的jar芯咧。
- 內(nèi)嵌的Jetty目前不支持JSPs牙捉。
- Undertow不支持JSPs。
這里有個JSP示例敬飒,你可以查看如何設(shè)置相關(guān)事項邪铲。
4.6 安全
如果Spring Security在classpath下,那么web應(yīng)用默認(rèn)對所有的HTTP路徑(也稱為終點无拗,端點带到,表示API的具體網(wǎng)址)使用'basic'認(rèn)證。為了給web應(yīng)用添加方法級別的保護(hù)英染,你可以添加@EnableGlobalMethodSecurity并使用想要的設(shè)置揽惹。其他信息參考Spring Security Reference。
默認(rèn)的AuthenticationManager有一個單一的user('user'的用戶名和隨機(jī)密碼會在應(yīng)用啟動時以INFO日志級別打印出來)四康。如下:
Using default security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35
注:如果你對日志配置進(jìn)行微調(diào)搪搏,確保org.springframework.boot.autoconfigure.security類別能記錄INFO信息,否則默認(rèn)的密碼不會被打印闪金。
你可以通過提供security.user.password改變默認(rèn)的密碼疯溺。這些和其他有用的屬性通過SecurityProperties(以security為前綴的屬性)被外部化了。
默認(rèn)的安全配置(security configuration)是在SecurityAutoConfiguration和導(dǎo)入的類中實現(xiàn)的(SpringBootWebSecurityConfiguration用于web安全毕泌,AuthenticationManagerConfiguration用于與非web應(yīng)用也相關(guān)的認(rèn)證配置)喝检。你可以添加一個@EnableWebSecurity bean來徹底關(guān)掉Spring Boot的默認(rèn)配置。為了對它進(jìn)行自定義撼泛,你需要使用外部的屬性配置和WebSecurityConfigurerAdapter類型的beans(比如,添加基于表單的登陸)澡谭。在Spring Boot示例里有一些安全相關(guān)的應(yīng)用可以帶你體驗常見的用例愿题。
在一個web應(yīng)用中你能得到的基本特性如下:
一個使用內(nèi)存存儲的AuthenticationManager bean和唯一的user(查看SecurityProperties.User獲取user的屬性)损俭。
忽略(不保護(hù))常見的靜態(tài)資源路徑(/css/, /js/, /images/**和 */favicon.ico)。
對其他的路徑實施HTTP Basic安全保護(hù)潘酗。
安全相關(guān)的事件會發(fā)布到Spring的ApplicationEventPublisher(成功和失敗的認(rèn)證杆兵,拒絕訪問)。
Spring Security提供的常見底層特性(HSTS, XSS, CSRF, 緩存)默認(rèn)都被開啟仔夺。
上述所有特性都能打開和關(guān)閉琐脏,或使用外部的配置進(jìn)行修改(security.)。為了覆蓋訪問規(guī)則(access rules)而不改變其他自動配置的特性缸兔,你可以添加一個使用@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)注解的WebSecurityConfigurerAdapter類型的@Bean日裙。
如果Actuator也在使用,你會發(fā)現(xiàn):
即使應(yīng)用路徑不受保護(hù)惰蜜,被管理的路徑也會受到保護(hù)昂拂。
安全相關(guān)的事件被轉(zhuǎn)換為AuditEvents(審計事件),并發(fā)布給AuditService抛猖。
默認(rèn)的用戶有ADMIN和USER的角色格侯。
使用外部屬性能夠修改Actuator(執(zhí)行器)的安全特性(management.security.*)。為了覆蓋應(yīng)用程序的訪問規(guī)則财著,你可以添加一個WebSecurityConfigurerAdapter類型的@Bean联四。同時,如果不想覆蓋執(zhí)行器的訪問規(guī)則撑教,你可以使用@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)注解該bean朝墩,否則使用@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)注解該bean。
4.7 使用sql數(shù)據(jù)庫
Spring框架為使用SQL數(shù)據(jù)庫提供了廣泛的支持驮履。從使用JdbcTemplate直接訪問JDBC到完全的對象關(guān)系映射技術(shù)鱼辙,比如Hibernate瘾杭。Spring Data提供一個額外的功能如筛,直接從接口創(chuàng)建Repository實現(xiàn),并使用約定從你的方法名生成查詢瞭吃。
4.7.1 配置DataSource
Java的javax.sql.DataSource接口提供了一個標(biāo)準(zhǔn)的使用數(shù)據(jù)庫連接的方法恐似。傳統(tǒng)做法是杜跷,一個DataSource使用一個URL連同相應(yīng)的證書去初始化一個數(shù)據(jù)庫連接。
4.7.1.1 對內(nèi)嵌數(shù)據(jù)庫的支持
開發(fā)應(yīng)用時使用內(nèi)存數(shù)據(jù)庫是很實用的矫夷。顯而易見地葛闷,內(nèi)存數(shù)據(jù)庫不需要提供持久化存儲。你不需要在應(yīng)用啟動時填充數(shù)據(jù)庫双藕,也不需要在應(yīng)用結(jié)束時丟棄數(shù)據(jù)淑趾。
Spring Boot可以自動配置的內(nèi)嵌數(shù)據(jù)庫包括H2, HSQL和Derby。你不需要提供任何連接URLs忧陪,只需要簡單的添加你想使用的內(nèi)嵌數(shù)據(jù)庫依賴扣泊。
示例:典型的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>
注:對于自動配置的內(nèi)嵌數(shù)據(jù)庫近范,你需要依賴spring-jdbc。在示例中延蟹,它通過spring-boot-starter-data-jpa被傳遞地拉過來了评矩。
4.7.1.2 連接到一個生產(chǎn)環(huán)境數(shù)據(jù)庫
在生產(chǎn)環(huán)境中,數(shù)據(jù)庫連接可以使用DataSource池進(jìn)行自動配置阱飘。下面是選取一個特定實現(xiàn)的算法:
- 由于Tomcat數(shù)據(jù)源連接池的性能和并發(fā)斥杜,在tomcat可用時,我們總是優(yōu)先使用它沥匈。
- 如果HikariCP可用蔗喂,我們將使用它。
- 如果Commons DBCP可用咐熙,我們將使用它弱恒,但在生產(chǎn)環(huán)境不推薦使用它。
- 最后棋恼,如果Commons DBCP2可用返弹,我們將使用它。
如果你使用spring-boot-starter-jdbc或spring-boot-starter-data-jpa 'starter POMs'爪飘,你將會自動獲取對tomcat-jdbc的依賴义起。
注:其他的連接池可以手動配置。如果你定義自己的DataSource bean师崎,自動配置不會發(fā)生默终。
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
其他可選的配置可以查看DataSourceProperties齐蔽。同時注意你可以通過spring.datasource.*配置任何DataSource實現(xiàn)相關(guān)的特定屬性:具體參考你使用的連接池實現(xiàn)的文檔。
注:既然Spring Boot能夠從大多數(shù)數(shù)據(jù)庫的url上推斷出driver-class-name床估,那么你就不需要再指定它了含滴。對于一個將要創(chuàng)建的DataSource連接池,我們需要能夠驗證Driver是否可用丐巫,所以我們會在做任何事情之前檢查它谈况。比如,如果你設(shè)置spring.datasource.driverClassName=com.mysql.jdbc.Driver递胧,然后這個類就會被加載碑韵。
4.7.1.3 連接到一個JNDI數(shù)據(jù)庫
如果正在將Spring Boot應(yīng)用部署到一個應(yīng)用服務(wù)器,你可能想要用應(yīng)用服務(wù)器內(nèi)建的特性來配置和管理你的DataSource缎脾,并使用JNDI訪問它祝闻。
spring.datasource.jndi-name屬性可以用來替代spring.datasource.url,spring.datasource.username和spring.datasource.password去從一個特定的JNDI路徑訪問DataSource遗菠。比如治筒,下面application.properties中的片段展示了如何獲取JBoss定義的DataSource:
spring.datasource.jndi-name=java:jboss/datasources/customers
4.7.2 使用JdbcTemplate
Spring的JdbcTemplate和NamedParameterJdbcTemplate類是被自動配置的屉栓,你可以在自己的beans中通過@Autowire直接注入它們舷蒲。
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;
}
// ...
}
4.7.3 JPA和Spring Data
Java持久化API是一個允許你將對象映射為關(guān)系數(shù)據(jù)庫的標(biāo)準(zhǔn)技術(shù)耸袜。spring-boot-starter-data-jpa POM提供了一種快速上手的方式。它提供下列關(guān)鍵的依賴:
- Hibernate - 一個非常流行的JPA實現(xiàn)牲平。
- Spring Data JPA - 讓實現(xiàn)基于JPA的repositories更容易堤框。
- Spring ORMs - Spring框架的核心ORM支持。
注:我們不想在這涉及太多關(guān)于JPA或Spring Data的細(xì)節(jié)纵柿。你可以參考來自spring.io的指南使用JPA獲取數(shù)據(jù)蜈抓,并閱讀Spring Data JPA和Hibernate的參考文檔。
4.7.3.1 實體類
傳統(tǒng)上昂儒,JPA實體類被定義到一個persistence.xml文件中沟使。在Spring Boot中,這個文件不是必需的渊跋,并被'實體掃描'替代腊嗡。默認(rèn)情況下,在你主(main)配置類(被@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注解自定義實體掃描路徑蒿囤。具體參考Section 67.4, “Separate @Entity definitions from Spring configuration”客们。
4.7.3.2 Spring Data JPA倉庫
Spring Data JPA倉庫(repositories)是用來定義訪問數(shù)據(jù)的接口。根據(jù)你的方法名材诽,JPA查詢會被自動創(chuàng)建底挫。比如,一個CityRepository接口可能聲明一個findAllByState(String state)方法脸侥,用來查找給定狀態(tài)的所有城市建邓。
對于比較復(fù)雜的查詢,你可以使用Spring Data的Query來注解你的方法湿痢。
Spring Data倉庫通常繼承自Repository或CrudRepository接口涝缝。如果你使用自動配置,包括在你的主配置類(被@EnableAutoConfiguration或@SpringBootApplication注解的類)的包下的倉庫將會被搜索譬重。
下面是一個傳統(tǒng)的Spring Data倉庫:
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的表面拒逮。具體查看它的參考指南。
4.7.3.2 創(chuàng)建和刪除JPA數(shù)據(jù)庫
默認(rèn)情況下臀规,只有在你使用內(nèi)嵌數(shù)據(jù)庫(H2, HSQL或Derby)時滩援,JPA數(shù)據(jù)庫才會被自動創(chuàng)建。你可以使用spring.jpa.*屬性顯示的設(shè)置JPA塔嬉。比如玩徊,為了創(chuàng)建和刪除表你可以將下面的配置添加到application.properties中:
spring.jpa.hibernate.ddl-auto=create-drop
注:Hibernate自己內(nèi)部對創(chuàng)建租悄,刪除表支持(如果你恰好記得這回事更好)的屬性是hibernate.hbm2ddl.auto。使用spring.jpa.properties.*(前綴在被添加到實體管理器之前會被剝離掉)恩袱,你可以設(shè)置Hibernate本身的屬性泣棋,比如hibernate.hbm2ddl.auto。示例:spring.jpa.properties.hibernate.globally_quoted_identifiers=true
將傳遞hibernate.globally_quoted_identifiers到Hibernate實體管理器畔塔。
默認(rèn)情況下潭辈,DDL執(zhí)行(或驗證)被延遲到ApplicationContext啟動。這也有一個spring.jpa.generate-ddl標(biāo)識澈吨,如果Hibernate自動配置被激活把敢,那該標(biāo)識就不會被使用,因為ddl-auto設(shè)置粒度更細(xì)谅辣。
4.8 使用NoSQL技術(shù)
Spring Data提供其他項目修赞,用來幫你使用各種各樣的NoSQL技術(shù),包括MongoDB, Neo4J, Elasticsearch, Solr, Redis, Gemfire, Couchbase和Cassandra桑阶。Spring Boot為Redis, MongoDB, Elasticsearch, Solr和Gemfire提供自動配置柏副。你可以充分利用其他項目,但你需要自己配置它們联逻。具體查看projects.spring.io/spring-data中合適的參考文檔搓扯。
4.8.1 Redis
Redis是一個緩存,消息中間件及具有豐富特性的鍵值存儲系統(tǒng)包归。Spring Boot為Jedis客戶端庫和由Spring Data Redis提供的基于Jedis客戶端的抽象提供自動配置锨推。spring-boot-starter-redis'Starter POM'為收集依賴提供一種便利的方式。
4.8.1.1 連接Redis
你可以注入一個自動配置的RedisConnectionFactory公壤,StringRedisTemplate或普通的跟其他Spring Bean相同的RedisTemplate實例换可。默認(rèn)情況下,這個實例將嘗試使用localhost:6379連接Redis服務(wù)器厦幅。
@Component
public class MyBean {
private StringRedisTemplate template;
@Autowired
public MyBean(StringRedisTemplate template) {
this.template = template;
}
// ...
}
如果你添加一個你自己的任何自動配置類型的@Bean沾鳄,它將替換默認(rèn)的(除了RedisTemplate的情況藏否,它是根據(jù)bean的名稱'redisTemplate'而不是它的類型進(jìn)行排除的)蒸绩。如果在classpath路徑下存在commons-pool2庭呜,默認(rèn)你會獲得一個連接池工廠缸夹。
4.8.2 MONGODB
MongoDB是一個開源的NoSQL文檔數(shù)據(jù)庫,它使用一個JSON格式的模式(schema)替換了傳統(tǒng)的基于表的關(guān)系數(shù)據(jù)盅抚。Spring Boot為使用MongoDB提供了很多便利壮虫,包括spring-boot-starter-data-mongodb'Starter POM'践盼。
4.8.2.1 連接MongoDB數(shù)據(jù)庫
你可以注入一個自動配置的org.springframework.data.mongodb.MongoDbFactory來訪問Mongo數(shù)據(jù)庫塔猾。默認(rèn)情況下篙骡,該實例將嘗試使用URL:mongodb://localhost/test連接一個MongoDB服務(wù)器。
import org.springframework.data.mongodb.MongoDbFactory;
import com.mongodb.DB;
@Component
public class MyBean {
private final MongoDbFactory mongo;
@Autowired
public MyBean(MongoDbFactory mongo) {
this.mongo = mongo;
}
// ...
public void example() {
DB db = mongo.getDb();
// ...
}
}
你可以通過設(shè)置spring.data.mongodb.uri來改變該url,或指定一個host/port糯俗。比如尿褪,你可能會在你的application.properties中設(shè)置如下的屬性:
spring.data.mongodb.host=mongoserver
spring.data.mongodb.port=27017
注:如果沒有指定spring.data.mongodb.port,那將使用默認(rèn)的端口27017得湘。你可以簡單的從上面的示例中刪除這一行杖玲。如果不使用Spring Data Mongo,你可以注入com.mongodb.Mongo beans而不是使用MongoDbFactory忽刽。
如果想全面控制MongoDB連接的建立天揖,你也可以聲明自己的MongoDbFactory或Mongo,@Beans跪帝。
4.8.2.2 MongoDBTemplate
Spring Data Mongo提供了一個MongoTemplate類,它的設(shè)計和Spring的JdbcTemplate很相似些阅。正如JdbcTemplate一樣伞剑,Spring Boot會為你自動配置一個bean,你只需簡單的注入它即可:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final MongoTemplate mongoTemplate;
@Autowired
public MyBean(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
// ...
}
具體參考MongoOperations Javadoc市埋。
4.8.1.3 Spring Data MongoDB倉庫
Spring Data的倉庫包括對MongoDB的支持黎泣。正如上面討論的JPA倉庫,基本的原則是查詢會自動基于你的方法名創(chuàng)建缤谎。
實際上抒倚,不管是Spring Data JPA還是Spring Data MongoDB都共享相同的基礎(chǔ)設(shè)施。所以你可以使用上面的JPA示例坷澡,并假設(shè)那個City現(xiàn)在是一個Mongo數(shù)據(jù)類而不是JPA @Entity托呕,它將以同樣的方式工作。
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);
}
4.8.3 Gemfire
Spring Data Gemfire為使用Pivotal Gemfire數(shù)據(jù)管理平臺提供了方便的频敛,Spring友好的工具项郊。Spring Boot提供了一個用于聚集依賴的spring-boot-starter-data-gemfire'Starter POM'。目前不支持Gemfire的自動配置斟赚,但你可以使用一個單一的注解使Spring Data倉庫支持它着降。
4.8.4 Solr
Apache Solr是一個搜索引擎。Spring Boot為solr客戶端庫及Spring Data Solr提供的基于solr客戶端庫的抽象提供了基本的配置拗军。Spring Boot提供了一個用于聚集依賴的spring-boot-starter-data-solr'Starter POM'任洞。
4.8.4.1 連接Solr
你可以像其他Spring beans一樣注入一個自動配置的SolrServer實例。默認(rèn)情況下发侵,該實例將嘗試使用localhost:8983/solr連接一個服務(wù)器交掏。
@Component
public class MyBean {
private SolrServer solr;
@Autowired
public MyBean(SolrServer solr) {
this.solr = solr;
}
// ...
}
如果你添加一個自己的SolrServer類型的@Bean,它將會替換默認(rèn)的器紧。
4.8.4.2 Spring Data Solr倉庫
Spring Data的倉庫包括了對Apache Solr的支持耀销。正如上面討論的JPA倉庫,基本的原則是查詢會自動基于你的方法名創(chuàng)建。
實際上熊尉,不管是Spring Data JPA還是Spring Data Solr都共享相同的基礎(chǔ)設(shè)施罐柳。所以你可以使用上面的JPA示例,并假設(shè)那個City現(xiàn)在是一個@SolrDocument類而不是JPA @Entity狰住,它將以同樣的方式工作张吉。
注:具體參考Spring Data Solr文檔。
4.8.5 Elasticsearch
Elastic Search是一個開源的催植,分布式肮蛹,實時搜索和分析引擎。Spring Boot為Elasticsearch及Spring Data Elasticsearch提供的基于它的抽象提供了基本的配置创南。Spring Boot提供了一個用于聚集依賴的spring-boot-starter-data-elasticsearch'Starter POM'伦忠。
4.8.5.1 連接Elasticsearch
你可以像其他Spring beans那樣注入一個自動配置的ElasticsearchTemplate或Elasticsearch客戶端實例。默認(rèn)情況下稿辙,該實例將嘗試連接到一個本地內(nèi)存服務(wù)器(在Elasticsearch項目中的一個NodeClient)昆码,但你可以通過設(shè)置spring.data.elasticsearch.clusterNodes為一個以逗號分割的host:port列表來將其切換到一個遠(yuǎn)程服務(wù)器(比如,TransportClient)邻储。
@Component
public class MyBean {
private ElasticsearchTemplate template;
@Autowired
public MyBean(ElasticsearchTemplate template) {
this.template = template;
}
// ...
}
如果你添加一個你自己的ElasticsearchTemplate類型的@Bean赋咽,它將替換默認(rèn)的。
4.8.5.2 Spring Data Elasticseach倉庫
Spring Data的倉庫包括了對Elasticsearch的支持吨娜。正如上面討論的JPA倉庫脓匿,基本的原則是查詢會自動基于你的方法名創(chuàng)建。
實際上宦赠,不管是Spring Data JPA還是Spring Data Elasticsearch都共享相同的基礎(chǔ)設(shè)施陪毡。所以你可以使用上面的JPA示例,并假設(shè)那個City現(xiàn)在是一個Elasticsearch @Document類而不是JPA @Entity袱瓮,它將以同樣的方式工作缤骨。
注:具體參考Spring Data Elasticsearch文檔。
4.9 消息
Spring Framework框架為集成消息系統(tǒng)提供了擴(kuò)展(extensive)支持:從使用JmsTemplate簡化JMS API尺借,到實現(xiàn)一個完整異步消息接收的底層設(shè)施绊起。
Spring AMQP提供一個相似的用于'高級消息隊列協(xié)議'的特征集,并且Spring Boot也為RabbitTemplate和RabbitMQ提供了自動配置選項燎斩。
Spring Websocket提供原生的STOMP消息支持虱歪,并且Spring Boot通過starters和一些自動配置也提供了對它的支持。
4.9.1 JMS
javax.jms.ConnectionFactory接口提供了一個標(biāo)準(zhǔn)的用于創(chuàng)建一個javax.jms.Connection的方法栅表,javax.jms.Connection用于和JMS代理(broker)交互笋鄙。
盡管為了使用JMS,Spring需要一個ConnectionFactory怪瓶,但通常你不需要直接使用它萧落,而是依賴于上層消息抽象(具體參考Spring框架的相關(guān)章節(jié))。Spring Boot也會自動配置發(fā)送和接收消息需要的設(shè)施(infrastructure)。
4.9.1.1 HornetQ支持
如果在classpath下發(fā)現(xiàn)HornetQ找岖,Spring Boot會自動配置ConnectionFactory陨倡。如果需要代理,將會開啟一個內(nèi)嵌的许布,已經(jīng)自動配置好的代理(除非顯式設(shè)置mode屬性)兴革。支持的modes有:embedded(顯式聲明使用一個內(nèi)嵌的代理,如果該代理在classpath下不可用將導(dǎo)致一個錯誤)蜜唾,native(使用netty傳輸協(xié)議連接代理)杂曲。當(dāng)后者被配置,Spring Boot配置一個連接到一個代理的ConnectionFactory袁余,該代理運(yùn)行在使用默認(rèn)配置的本地機(jī)器上擎勘。
注:如果使用spring-boot-starter-hornetq,連接到一個已存在的HornetQ實例所需的依賴都會被提供泌霍,同時還有用于集成JMS的Spring基礎(chǔ)設(shè)施货抄。將org.hornetq:hornetq-jms-server添加到你的應(yīng)用中,你就可以使用embedded模式朱转。
HornetQ配置被spring.hornetq.*中的外部配置屬性所控制。例如积暖,你可能在application.properties聲明以下片段:
spring.hornetq.mode=native
spring.hornetq.host=192.168.1.210
spring.hornetq.port=9876
當(dāng)內(nèi)嵌代理時藤为,你可以選擇是否啟用持久化,并且列表中的目標(biāo)都應(yīng)該是可用的夺刑。這些可以通過一個以逗號分割的列表來指定一些默認(rèn)的配置項缅疟,或定義org.hornetq.jms.server.config.JMSQueueConfiguration或org.hornetq.jms.server.config.TopicConfiguration類型的bean(s)來配置更高級的隊列和主題。具體參考HornetQProperties遍愿。
沒有涉及JNDI查找存淫,目標(biāo)是通過名字解析的,名字即可以使用HornetQ配置中的name屬性沼填,也可以是配置中提供的names桅咆。
4.9.1.2 ActiveQ支持
如果發(fā)現(xiàn)ActiveMQ在classpath下可用,Spring Boot會配置一個ConnectionFactory坞笙。如果需要代理岩饼,將會開啟一個內(nèi)嵌的,已經(jīng)自動配置好的代理(只要配置中沒有指定代理URL)薛夜。
ActiveMQ配置是通過spring.activemq.*中的外部配置來控制的籍茧。例如,你可能在application.properties中聲明下面的片段:
spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret
具體參考ActiveMQProperties梯澜。
默認(rèn)情況下先鱼,如果目標(biāo)還不存在,ActiveMQ將創(chuàng)建一個箱玷,所以目標(biāo)是通過它們提供的名稱解析出來的。
4.9.1.3 使用JNDI ConnectionFactory
如果你在一個應(yīng)用服務(wù)器中運(yùn)行你的應(yīng)用俭茧,Spring Boot將嘗試使用JNDI定位一個JMS ConnectionFactory。默認(rèn)情況會檢查java:/JmsXA和java:/ XAConnectionFactory螟蝙。如果需要的話恢恼,你可以使用spring.jms.jndi-name屬性來指定一個替代位置。
spring.jms.jndi-name=java:/MyConnectionFactory
4.9.1.4 發(fā)送消息
Spring的JmsTemplate會被自動配置胰默,你可以將它直接注入到你自己的beans中:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final JmsTemplate jmsTemplate;
@Autowired
public MyBean(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
// ...
}
注:JmsMessagingTemplate(Spring4.1新增的)也可以使用相同的方式注入
4.9.1.5 接收消息
當(dāng)JMS基礎(chǔ)設(shè)施能夠使用時场斑,任何bean都能夠被@JmsListener注解,以創(chuàng)建一個監(jiān)聽者端點牵署。如果沒有定義JmsListenerContainerFactory漏隐,一個默認(rèn)的將會被自動配置。下面的組件在someQueue目標(biāo)上創(chuàng)建一個監(jiān)聽者端點奴迅。
@Component
public class MyBean {
@JmsListener(destination = "someQueue")
public void processMessage(String content) {
// ...
}
}
具體查看@EnableJms javadoc青责。
4.10 發(fā)送郵件
Spring框架使用JavaMailSender接口為發(fā)送郵件提供了一個簡單的抽象,并且Spring Boot也為它提供了自動配置和一個starter模塊取具。 具體查看JavaMailSender參考文檔脖隶。
如果spring.mail.host和相關(guān)的庫(通過spring-boot-starter-mail定義)都存在,一個默認(rèn)的JavaMailSender將被創(chuàng)建暇检。該sender可以通過spring.mail命名空間下的配置項進(jìn)一步自定義产阱,具體參考MailProperties。
4.11 使用JTA處理分布式事務(wù)
Spring Boot使用一個Atomkos或Bitronix的內(nèi)嵌事務(wù)管理器來支持跨多個XA資源的分布式JTA事務(wù)块仆。當(dāng)部署到一個恰當(dāng)?shù)腏2EE應(yīng)用服務(wù)器時也會支持JTA事務(wù)构蹬。
當(dāng)發(fā)現(xiàn)一個JTA環(huán)境時,Spring Boot將使用Spring的JtaTransactionManager來管理事務(wù)悔据。自動配置的JMS庄敛,DataSource和JPA beans將被升級以支持XA事務(wù)。你可以使用標(biāo)準(zhǔn)的Spring idioms科汗,比如@Transactional藻烤,來參與到一個分布式事務(wù)中。如果你處于JTA環(huán)境里肛捍,但仍舊想使用本地事務(wù)隐绵,你可以將spring.jta.enabled屬性設(shè)置為false來禁用JTA自動配置功能。
4.11.1 使用一個Atomikos事務(wù)管理器
Atomikos是一個非常流行的開源事務(wù)管理器拙毫,它可以嵌入到你的Spring Boot應(yīng)用中依许。你可以使用spring-boot-starter-jta-atomikosStarter
POM去獲取正確的Atomikos庫。Spring Boot會自動配置Atomikos缀蹄,并將合適的depends-on應(yīng)用到你的Spring Beans上峭跳,確保它們以正確的順序啟動和關(guān)閉膘婶。
默認(rèn)情況下,Atomikos事務(wù)日志將被記錄在應(yīng)用home目錄(你的應(yīng)用jar文件放置的目錄)下的transaction-logs文件夾中蛀醉。你可以在application.properties文件中通過設(shè)置spring.jta.log-dir屬性來自定義該目錄悬襟。以spring.jta.開頭的屬性能用來自定義Atomikos的UserTransactionServiceIml實現(xiàn)。具體參考AtomikosProperties javadoc拯刁。
注:為了確保多個事務(wù)管理器能夠安全地和相應(yīng)的資源管理器配合脊岳,每個Atomikos實例必須設(shè)置一個唯一的ID。默認(rèn)情況下垛玻,該ID是Atomikos實例運(yùn)行的機(jī)器上的IP地址割捅。為了確保生產(chǎn)環(huán)境中該ID的唯一性,你需要為應(yīng)用的每個實例設(shè)置不同的spring.jta.transaction-manager-id屬性值帚桩。
4.11.2 使用一個Bitronix事務(wù)管理器
Bitronix是另一個流行的開源JTA事務(wù)管理器實現(xiàn)亿驾。你可以使用spring-boot-starter-jta-bitronixstarter POM為項目添加合適的Birtronix依賴。和Atomikos類似账嚎,Spring Boot將自動配置Bitronix莫瞬,并對beans進(jìn)行后處理(post-process)以確保它們以正確的順序啟動和關(guān)閉。
默認(rèn)情況下郭蕉,Bitronix事務(wù)日志將被記錄到應(yīng)用home目錄下的transaction-logs文件夾中疼邀。通過設(shè)置spring.jta.log-dir屬性,你可以自定義該目錄召锈。以spring.jta.開頭的屬性將被綁定到bitronix.tm.Configuration bean檩小,你可以通過這完成進(jìn)一步的自定義。具體參考Bitronix文檔烟勋。
注:為了確保多個事務(wù)管理器能夠安全地和相應(yīng)的資源管理器配合,每個Bitronix實例必須設(shè)置一個唯一的ID筐付。默認(rèn)情況下卵惦,該ID是Bitronix實例運(yùn)行的機(jī)器上的IP地址。為了確保生產(chǎn)環(huán)境中該ID的唯一性瓦戚,你需要為應(yīng)用的每個實例設(shè)置不同的spring.jta.transaction-manager-id屬性值沮尿。
4.11.3 使用一個J2EE管理的事務(wù)管理器
如果你將Spring Boot應(yīng)用打包為一個war或ear文件,并將它部署到一個J2EE的應(yīng)用服務(wù)器中较解,那你就能使用應(yīng)用服務(wù)器內(nèi)建的事務(wù)管理器畜疾。Spring Boot將嘗試通過查找常見的JNDI路徑(java:comp/UserTransaction, java:comp/TransactionManager等)來自動配置一個事務(wù)管理器。如果使用應(yīng)用服務(wù)器提供的事務(wù)服務(wù)印衔,你通常需要確保所有的資源都被應(yīng)用服務(wù)器管理啡捶,并通過JNDI暴露出去。Spring Boot通過查找JNDI路徑j(luò)ava:/JmsXA或java:/XAConnectionFactory獲取一個ConnectionFactory來自動配置JMS奸焙,并且你可以使用spring.datasource.jndi-name屬性配置你的DataSource瞎暑。
4.12 Spring集成
Spring集成提供基于消息和其他協(xié)議的彤敛,比如HTTP,TCP等的抽象了赌。如果Spring集成在classpath下可用墨榄,它將會通過@EnableIntegration注解被初始化。如果classpath下'spring-integration-jmx'可用勿她,則消息處理統(tǒng)計分析將被通過JMX發(fā)布出去袄秩。具體參考IntegrationAutoConfiguration類。
4.13 基于JMX的監(jiān)控和管理
Java管理擴(kuò)展(JMX)提供了一個標(biāo)準(zhǔn)的用于監(jiān)控和管理應(yīng)用的機(jī)制逢并。默認(rèn)情況下之剧,Spring Boot將創(chuàng)建一個id為‘mbeanServer’的MBeanServer,并導(dǎo)出任何被Spring JMX注解(@ManagedResource,@ManagedAttribute,@ManagedOperation)的beans筒狠。具體參考JmxAutoConfiguration類猪狈。
4.14 測試
Spring Boot提供很多有用的測試應(yīng)用的工具。spring-boot-starter-test POM提供Spring Test辩恼,JUnit雇庙,Hamcrest和Mockito的依賴。在spring-boot核心模塊org.springframework.boot.test包下也有很多有用的測試工具灶伊。
4.14.1 測試作用域依賴
如果使用spring-boot-starter-test ‘Starter POM’(在test作用域內(nèi))疆前,你將發(fā)現(xiàn)下列被提供的庫:
- Spring Test - 對Spring應(yīng)用的集成測試支持
- JUnit - 事實上的(de-facto)標(biāo)準(zhǔn),用于Java應(yīng)用的單元測試聘萨。
- Hamcrest - 一個匹配對象的庫(也稱為約束或前置條件)竹椒,它允許assertThat等JUnit類型的斷言。
- Mockito - 一個Java模擬框架米辐。
這也有一些我們寫測試用例時經(jīng)常用到的庫胸完。如果它們不能滿足你的要求,你可以隨意添加其他的測試用的依賴庫翘贮。
4.14.2 測試Spring應(yīng)用
依賴注入最大的優(yōu)點就是它能夠讓你的代碼更容易進(jìn)行單元測試赊窥。你只需簡單的通過new操作符實例化對象,而不需要涉及Spring狸页。你也可以使用模擬對象替換真正的依賴锨能。
你常常需要在進(jìn)行單元測試后,開始集成測試(在這個過程中只需要涉及到Spring的ApplicationContext)芍耘。在執(zhí)行集成測試時址遇,不需要部署應(yīng)用或連接到其他基礎(chǔ)設(shè)施是非常有用的。
Spring框架包含一個dedicated測試模塊斋竞,用于這樣的集成測試倔约。你可以直接聲明對org.springframework:spring-test的依賴,或使用spring-boot-starter-test ‘Starter POM’以透明的方式拉取它窃页。
如果你以前沒有使用過spring-test模塊跺株,可以查看Spring框架參考文檔中的相關(guān)章節(jié)复濒。
4.14.3 測試Spring Boot應(yīng)用
一個Spring Boot應(yīng)用只是一個Spring ApplicationContext,所以在測試它時除了正常情況下處理一個vanilla Spring context外不需要做其他特別事情乒省。唯一需要注意的是巧颈,如果你使用SpringApplication創(chuàng)建上下文,外部配置袖扛,日志和Spring Boot的其他特性只會在默認(rèn)的上下文中起作用砸泛。
Spring Boot提供一個@SpringApplicationConfiguration注解用來替換標(biāo)準(zhǔn)的spring-test @ContextConfiguration注解。如果使用@SpringApplicationConfiguration來設(shè)置你的測試中使用的ApplicationContext,它最終將通過SpringApplication創(chuàng)建,并且你將獲取到Spring Boot的其他特性彤枢。
示例如下:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)
public class CityRepositoryIntegrationTests {
@Autowired
CityRepository repository;
// ...
}
提示:上下文加載器會通過查找@WebIntegrationTest或@WebAppConfiguration注解來猜測你想測試的是否是web應(yīng)用(例如,是否使用MockMVC盏筐,MockMVC和@WebAppConfiguration是spring-test的一部分)。
如果想讓一個web應(yīng)用啟動砸讳,并監(jiān)聽它的正常的端口琢融,你可以使用HTTP來測試它(比如,使用RestTemplate)簿寂,并使用@WebIntegrationTest注解你的測試類(或它的一個父類)漾抬。這很有用,因為它意味著你可以對你的應(yīng)用進(jìn)行全棧測試常遂,但在一次HTTP交互后纳令,你需要在你的測試類中注入相應(yīng)的組件并使用它們斷言應(yīng)用的內(nèi)部狀態(tài)。
示例:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)
@WebIntegrationTest
public class CityRepositoryIntegrationTests {
@Autowired
CityRepository repository;
RestTemplate restTemplate = new TestRestTemplate();
// ... interact with the running server
}
注:Spring測試框架在每次測試時會緩存應(yīng)用上下文克胳。因此平绩,只要你的測試共享相同的配置,不管你實際運(yùn)行多少測試漠另,開啟和停止服務(wù)器只會發(fā)生一次馒过。
你可以為@WebIntegrationTest添加環(huán)境變量屬性來改變應(yīng)用服務(wù)器端口號,比如@WebIntegrationTest("server.port:9000")酗钞。此外,你可以將server.port和management.port屬性設(shè)置為0來讓你的集成測試使用隨機(jī)的端口號来累,例如:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebIntegrationTest({"server.port=0", "management.port=0"})
public class SomeIntegrationTests {
// ...
}
可以查看Section 64.4, “Discover the HTTP port at runtime”砚作,它描述了如何在測試期間發(fā)現(xiàn)分配的實際端口。
4.14.3.1 使用Spock測試Spring Boot應(yīng)用
如果期望使用Spock測試一個Spring Boot應(yīng)用嘹锁,你應(yīng)該將Spock的spock-spring模塊依賴添加到應(yīng)用的構(gòu)建中葫录。spock-spring將Spring的測試框架集成到了Spock里。
注意你不能使用上述提到的@SpringApplicationConfiguration注解领猾,因為Spock找不到@ContextConfiguration元注解米同。為了繞過該限制骇扇,你應(yīng)該直接使用@ContextConfiguration注解,并使用Spring Boot特定的上下文加載器來配置它面粮。
@ContextConfiguration(loader = SpringApplicationContextLoader.class)
class ExampleSpec extends Specification {
// ...
}
注:上面描述的注解在Spock中可以使用少孝,比如,你可以使用@WebIntegrationTest注解你的Specification以滿足測試需要熬苍。
4.14.4 測試工具
打包進(jìn)spring-boot的一些有用的測試工具類稍走。
4.14.4.1 ConfigFileApplicationContextInitializer
ConfigFileApplicationContextInitializer是一個ApplicationContextInitializer,可以用來測試加載Spring Boot的application.properties文件柴底。當(dāng)不需要使用@SpringApplicationConfiguration提供的全部特性時婿脸,你可以使用它。
@ContextConfiguration(classes = Config.class,initializers = ConfigFileApplicationContextInitializer.class)
4.14.4.2 EnvironmentTestUtils
EnvironmentTestUtils允許你快速添加屬性到一個ConfigurableEnvironment或ConfigurableApplicationContext柄驻。只需簡單的使用key=value字符串調(diào)用它: ```java EnvironmentTestUtils.addEnvironment(env, "org=Spring", "name=Boot");
4.14.4.3 OutputCapture
OutputCapture是一個JUnit Rule狐树,用于捕獲System.out和System.err輸出。只需簡單的將捕獲聲明為一個@Rule鸿脓,并使用toString()斷言:
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.test.OutputCapture;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class MyTest {
@Rule
public OutputCapture capture = new OutputCapture();
@Test
public void testName() throws Exception {
System.out.println("Hello World!");
assertThat(capture.toString(), containsString("World"));
}
}
4.14.4.4 TestRestTemplate
TestRestTemplate是一個方便進(jìn)行集成測試的Spring RestTemplate子類抑钟。你會獲取到一個普通的模板或一個發(fā)送基本HTTP認(rèn)證(使用用戶名和密碼)的模板。在任何情況下答憔,這些模板都表現(xiàn)出對測試友好:不允許重定向(這樣你可以對響應(yīng)地址進(jìn)行斷言)味赃,忽略cookies(這樣模板就是無狀態(tài)的),對于服務(wù)端錯誤不會拋出異常虐拓。推薦使用Apache HTTP Client(4.3.2或更好的版本)心俗,但不強(qiáng)制這樣做。如果在classpath下存在Apache HTTP Client蓉驹,TestRestTemplate將以正確配置的client進(jìn)行響應(yīng)城榛。
public class MyTest {
RestTemplate template = new TestRestTemplate();
@Test
public void testRequest() throws Exception {
HttpHeaders headers = template.getForEntity("http://myhost.com", String.class).getHeaders();
assertThat(headers.getLocation().toString(), containsString("myotherhost"));
}
}
4.15 開發(fā)自動配置和使用條件
如果你在一個開發(fā)者共享庫的公司工作,或你在從事一個開源或商業(yè)型的庫态兴,你可能想要開發(fā)自己的auto-configuration狠持。Auto-configuration類能夠在外部的jars中綁定,并仍能被Spring Boot發(fā)現(xiàn)瞻润。
4.15.1 理解auto-configured beans
從底層來講喘垂,auto-configured是使用標(biāo)準(zhǔn)的@Configuration實現(xiàn)的類,另外的@Conditional注解用來約束在什么情況下使用auto-configuration绍撞。通常auto-configuration類使用@ConditionalOnClass和@ConditionalOnMissingBean注解正勒。這是為了確保只有在相關(guān)的類被發(fā)現(xiàn),和你沒有聲明自己的@Configuration時才應(yīng)用auto-configuration傻铣。
你可以瀏覽spring-boot-autoconfigure的源碼章贞,查看我們提供的@Configuration類(查看META-INF/spring.factories文件)。
4.15.2 定位auto-configuration候選者
Spring Boot會檢查你發(fā)布的jar中是否存在META-INF/spring.factories文件非洲。該文件應(yīng)該列出以EnableAutoConfiguration為key的配置類:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
如果配置需要應(yīng)用特定的順序鸭限,你可以使用@AutoConfigureAfter或@AutoConfigureBefore注解蜕径。例如,你想提供web-specific配置败京,你的類就需要應(yīng)用在WebMvcAutoConfiguration后面兜喻。
4.15.3 Condition注解
你幾乎總是需要在你的auto-configuration類里添加一個或更多的@Condition注解。@ConditionalOnMissingBean注解是一個常見的示例喧枷,它經(jīng)常用于允許開發(fā)者覆蓋auto-configuration虹统,如果他們不喜歡你提供的默認(rèn)行為。
Spring Boot包含很多@Conditional注解隧甚,你可以在自己的代碼中通過注解@Configuration類或單獨的@Bean方法來重用它們车荔。
4.15.3.1 Class條件
@ConditionalOnClass和@ConditionalOnMissingClass注解允許根據(jù)特定類是否出現(xiàn)來跳過配置。由于注解元數(shù)據(jù)是使用ASM來解析的戚扳,你實際上可以使用value屬性來引用真正的類忧便,即使該類可能實際上并沒有出現(xiàn)在運(yùn)行應(yīng)用的classpath下。如果你傾向于使用一個String值來指定類名帽借,你也可以使用name屬性珠增。
4.15.3.2 Bean條件
@ConditionalOnBean和@ConditionalOnMissingBean注解允許根據(jù)特定beans是否出現(xiàn)來跳過配置。你可以使用value屬性來指定beans(by type)砍艾,也可以使用name來指定beans(by name)蒂教。search屬性允許你限制搜索beans時需要考慮的ApplicationContext的層次。
注:當(dāng)@Configuration類被解析時@Conditional注解會被處理脆荷。Auto-configure @Configuration總是最后被解析(在所有用戶定義beans后面)凝垛,然而,如果你將那些注解用到常規(guī)的@Configuration類蜓谋,需要注意不能引用那些還沒有創(chuàng)建好的bean定義梦皮。
4.15.3.3 Property條件
@ConditionalOnProperty注解允許根據(jù)一個Spring Environment屬性來決定是否包含配置√一溃可以使用prefix和name屬性指定要檢查的配置屬性剑肯。默認(rèn)情況下,任何存在的只要不是false的屬性都會匹配观堂。你也可以使用havingValue和matchIfMissing屬性創(chuàng)建更高級的檢測让网。
4.15.3.4 Resource條件
@ConditionalOnResource注解允許只有在特定資源出現(xiàn)時配置才會被包含。資源可以使用常見的Spring約定命名师痕,例如file:/home/user/test.dat寂祥。
4.15.3.5 Web Application條件
@ConditionalOnWebApplication和@ConditionalOnNotWebApplication注解允許根據(jù)應(yīng)用是否為一個'web應(yīng)用'來決定是否包含配置。一個web應(yīng)用是任何使用Spring WebApplicationContext七兜,定義一個session作用域或有一個StandardServletEnvironment的應(yīng)用。
4.15.3.6 SpEL表達(dá)式條件
@ConditionalOnExpression注解允許根據(jù)SpEL表達(dá)式結(jié)果來跳過配置福扬。
4.16 WebSockets
Spring Boot為內(nèi)嵌的Tomcat(8和7)腕铸,Jetty 9和Undertow提供WebSockets自動配置惜犀。如果你正在將一個war包部署到一個單獨的容器,Spring Boot會假設(shè)該容器會對它的WebSocket支持相關(guān)的配置負(fù)責(zé)狠裹。
Spring框架提供豐富的WebSocket支持虽界,通過spring-boot-starter-websocket模塊可以輕易獲取到。
Spring Boot執(zhí)行器:Production-ready特性
Spring Boot包含很多其他的特性涛菠,它們可以幫你監(jiān)控和管理發(fā)布到生產(chǎn)環(huán)境的應(yīng)用莉御。你可以選擇使用HTTP端點,JMX或遠(yuǎn)程shell(SSH或Telnet)來管理和監(jiān)控應(yīng)用俗冻。審計(Auditing)礁叔,健康(health)和數(shù)據(jù)采集(metrics gathering)會自動應(yīng)用到你的應(yīng)用。
5.1 開啟production-ready特性
spring-boot-actuator模塊提供了Spring Boot所有的production-ready特性迄薄。啟用該特性的最簡單方式就是添加對spring-boot-starter-actuator ‘Starter POM’的依賴琅关。
執(zhí)行器(Actuator)的定義:執(zhí)行器是一個制造業(yè)術(shù)語,指的是用于移動或控制東西的一個機(jī)械裝置讥蔽。一個很小的改變就能讓執(zhí)行器產(chǎn)生大量的運(yùn)動涣易。
基于Maven的項目想要添加執(zhí)行器只需添加下面的'starter'依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
對于Gradle,使用下面的聲明:
dependencies {
compile("org.springframework.boot:spring-boot-starter-actuator")
}
5.2 端點
執(zhí)行器端點允許你監(jiān)控應(yīng)用及與應(yīng)用進(jìn)行交互冶伞。Spring Boot包含很多內(nèi)置的端點新症,你也可以添加自己的。例如响禽,health端點提供了應(yīng)用的基本健康信息硬毕。
端點暴露的方式取決于你采用的技術(shù)類型儒老。大部分應(yīng)用選擇HTTP監(jiān)控,端點的ID映射到一個URL。例如剪菱,默認(rèn)情況下,health端點將被映射到/health姐叁。
下面的端點都是可用的:
ID | 描述 | 敏感(Sensitive) |
---|---|---|
autoconfig | 顯示一個auto-configuration的報告航背,該報告展示所有auto-configuration候選者及它們被應(yīng)用或未被應(yīng)用的原因 | true |
beans | 顯示一個應(yīng)用中所有Spring Beans的完整列表 | true |
configprops | 顯示一個所有@ConfigurationProperties的整理列表 | true |
dump | 執(zhí)行一個線程轉(zhuǎn)儲 | true |
env | 暴露來自Spring ConfigurableEnvironment的屬性 | true |
health | 展示應(yīng)用的健康信息(當(dāng)使用一個未認(rèn)證連接訪問時顯示一個簡單的'status',使用認(rèn)證連接訪問則顯示全部信息詳情) | false |
info | 顯示任意的應(yīng)用信息 | false |
metrics | 展示當(dāng)前應(yīng)用的'指標(biāo)'信息 | true |
mappings | 顯示一個所有@RequestMapping路徑的整理列表 | true |
shutdown | 允許應(yīng)用以優(yōu)雅的方式關(guān)閉(默認(rèn)情況下不啟用) | true |
trace | 顯示trace信息(默認(rèn)為最新的一些HTTP請求) | true |
注:根據(jù)一個端點暴露的方式巫击,sensitive參數(shù)可能會被用做一個安全提示禀晓。例如,在使用HTTP訪問sensitive端點時需要提供用戶名/密碼(如果沒有啟用web安全坝锰,可能會簡化為禁止訪問該端點)粹懒。
5.2.1 自定義端點
使用Spring屬性可以自定義端點。你可以設(shè)置端點是否開啟(enabled)顷级,是否敏感(sensitive)凫乖,甚至它的id。例如,下面的application.properties改變了敏感性和beans端點的id帽芽,也啟用了shutdown删掀。
endpoints.beans.id=springbeans
endpoints.beans.sensitive=false
endpoints.shutdown.enabled=true
注:前綴endpoints + . + name被用來唯一的標(biāo)識被配置的端點。
默認(rèn)情況下导街,除了shutdown外的所有端點都是啟用的披泪。如果希望指定選擇端點的啟用,你可以使用endpoints.enabled屬性搬瑰。例如款票,下面的配置禁用了除info外的所有端點:
endpoints.enabled=false
endpoints.info.enabled=true
5.2.2 健康信息
健康信息可以用來檢查應(yīng)用的運(yùn)行狀態(tài)。它經(jīng)常被監(jiān)控軟件用來提醒人們生產(chǎn)系統(tǒng)是否停止泽论。health端點暴露的默認(rèn)信息取決于端點是如何被訪問的艾少。對于一個非安全,未認(rèn)證的連接只返回一個簡單的'status'信息佩厚。對于一個安全或認(rèn)證過的連接其他詳細(xì)信息也會展示(具體參考Section 41.6, “HTTP Health endpoint access restrictions” )姆钉。
健康信息是從你的ApplicationContext中定義的所有HealthIndicator beans收集過來的。Spring Boot包含很多auto-configured的HealthIndicators抄瓦,你也可以寫自己的潮瓶。
5.2.3 安全與HealthIndicators
HealthIndicators返回的信息常常性質(zhì)上有點敏感。例如钙姊,你可能不想將數(shù)據(jù)庫服務(wù)器的詳情發(fā)布到外面毯辅。因此,在使用一個未認(rèn)證的HTTP連接時煞额,默認(rèn)只會暴露健康狀態(tài)(health status)思恐。如果想將所有的健康信息暴露出去,你可以把endpoints.health.sensitive設(shè)置為false膊毁。
為防止'拒絕服務(wù)'攻擊胀莹,Health響應(yīng)會被緩存。你可以使用endpoints.health.time-to-live屬性改變默認(rèn)的緩存時間(1000毫秒)婚温。
5.2.3.1 自動配置的HealthIndicators
下面的HealthIndicators會被Spring Boot自動配置(在合適的時候):
名稱 | 描述 |
---|---|
DiskSpaceHealthIndicator | 低磁盤空間檢測 |
DataSourceHealthIndicator | 檢查是否能從DataSource獲取連接 |
MongoHealthIndicator | 檢查一個Mongo數(shù)據(jù)庫是否可用(up) |
RabbitHealthIndicator | 檢查一個Rabbit服務(wù)器是否可用(up) |
RedisHealthIndicator | 檢查一個Redis服務(wù)器是否可用(up) |
SolrHealthIndicator | 檢查一個Solr服務(wù)器是否可用(up) |
5.2.3.2 編寫自定義HealthIndicators
想提供自定義健康信息描焰,你可以注冊實現(xiàn)了HealthIndicator接口的Spring beans。你需要提供一個health()方法的實現(xiàn)栅螟,并返回一個Health響應(yīng)荆秦。Health響應(yīng)需要包含一個status和可選的用于展示的詳情。
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyHealth implements HealthIndicator {
@Override
public Health health() {
int errorCode = check(); // perform some specific health check
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
}
除了Spring Boot預(yù)定義的Status類型力图,Health也可以返回一個代表新的系統(tǒng)狀態(tài)的自定義Status步绸。在這種情況下,需要提供一個HealthAggregator接口的自定義實現(xiàn)吃媒,或使用management.health.status.order屬性配置默認(rèn)的實現(xiàn)瓤介。
例如吕喘,假設(shè)一個新的,代碼為FATAL的Status被用于你的一個HealthIndicator實現(xiàn)中刑桑。為了配置嚴(yán)重程度兽泄,你需要將下面的配置添加到application屬性文件中:
management.health.status.order: DOWN, OUT_OF_SERVICE, UNKNOWN, UP
如果使用HTTP訪問health端點,你可能想要注冊自定義的status漾月,并使用HealthMvcEndpoint進(jìn)行映射。例如胃珍,你可以將FATAL映射為HttpStatus.SERVICE_UNAVAILABLE梁肿。
5.2.4 自定義應(yīng)用info信息
通過設(shè)置Spring屬性info.*,你可以定義info端點暴露的數(shù)據(jù)觅彰。所有在info關(guān)鍵字下的Environment屬性都將被自動暴露吩蔑。例如,你可以將下面的配置添加到application.properties:
info.app.name=MyService
info.app.description=My awesome service
info.app.version=1.0.0
5.2.4.1 在構(gòu)建時期自動擴(kuò)展info屬性
你可以使用已經(jīng)存在的構(gòu)建配置自動擴(kuò)展info屬性填抬,而不是對在項目構(gòu)建配置中存在的屬性進(jìn)行硬編碼烛芬。這在Maven和Gradle都是可能的。
使用Maven自動擴(kuò)展屬性
對于Maven項目飒责,你可以使用資源過濾來自動擴(kuò)展info屬性赘娄。如果使用spring-boot-starter-parent,你可以通過@..@占位符引用Maven的'project properties'宏蛉。
project.artifactId=myproject
project.name=Demo
project.version=X.X.X.X
project.description=Demo project for info endpoint
info.build.artifact=@project.artifactId@
info.build.name=@project.name@
info.build.description=@project.description@
info.build.version=@project.version@
注:在上面的示例中遣臼,我們使用project.*來設(shè)置一些值以防止由于某些原因Maven的資源過濾沒有開啟。Maven目標(biāo)spring-boot:run直接將src/main/resources添加到classpath下(出于熱加載的目的)拾并。這就繞過了資源過濾和自動擴(kuò)展屬性的特性揍堰。你可以使用exec:java替換該目標(biāo)或自定義插件的配置,具體參考plugin usage page嗅义。
如果你不使用starter parent屏歹,在你的pom.xml你需要添加(處于元素內(nèi)):
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
和(處于內(nèi)):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
</configuration>
</plugin>
使用Gradle自動擴(kuò)展屬性
通過配置Java插件的processResources任務(wù),你也可以自動使用來自Gradle項目的屬性擴(kuò)展info屬性之碗。
processResources {
expand(project.properties)
}
然后你可以通過占位符引用Gradle項目的屬性:
info.build.name=${name}
info.build.description=${description}
info.build.version=${version}
5.2.4.2 Git提交信息
info端點的另一個有用特性是蝙眶,當(dāng)項目構(gòu)建完成后,它可以發(fā)布關(guān)于你的git源碼倉庫狀態(tài)的信息继控。如果在你的jar中包含一個git.properties文件械馆,git.branch和git.commit屬性將被加載。
對于Maven用戶武通,spring-boot-starter-parent POM包含一個能夠產(chǎn)生git.properties文件的預(yù)配置插件霹崎。只需要簡單的將下面的聲明添加到你的POM中:
<build>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</plugin>
</plugins>
</build>
對于Gradle用戶可以使用一個相似的插件gradle-git,盡管為了產(chǎn)生屬性文件可能需要稍微多點工作冶忱。
5.3 基于HTTP的監(jiān)控和管理
如果你正在開發(fā)一個Spring MVC應(yīng)用尾菇,Spring Boot執(zhí)行器自動將所有啟用的端點通過HTTP暴露出去。默認(rèn)約定使用端點的id作為URL路徑,例如派诬,health暴露為/health劳淆。
5.3.1 保護(hù)敏感端點
如果你的項目中添加的有Spring Security,所有通過HTTP暴露的敏感端點都會受到保護(hù)默赂。默認(rèn)情況下會使用基本認(rèn)證(basic authentication沛鸵,用戶名為user,密碼為應(yīng)用啟動時在控制臺打印的密碼)缆八。
你可以使用Spring屬性改變用戶名曲掰,密碼和訪問端點需要的安全角色。例如奈辰,你可能會在application.properties中添加下列配置:
security.user.name=admin
security.user.password=secret
management.security.role=SUPERUSER
注:如果你不使用Spring Security栏妖,那你的HTTP端點就被公開暴露,你應(yīng)該慎重考慮啟用哪些端點奖恰。具體參考Section 40.1, “Customizing endpoints”吊趾。
5.3.2 自定義管理服務(wù)器的上下文路徑
有時候?qū)⑺械墓芾矶丝趧澐值揭粋€路徑下是有用的。例如瑟啃,你的應(yīng)用可能已經(jīng)將/info作為他用论泛。你可以用management.contextPath屬性為管理端口設(shè)置一個前綴:
management.context-path=/manage
上面的application.properties示例將把端口從/{id}改為/manage/{id}(比如,/manage/info)翰守。
5.3.3 自定義管理服務(wù)器的端口
對于基于云的部署孵奶,使用默認(rèn)的HTTP端口暴露管理端點(endpoints)是明智的選擇。然而蜡峰,如果你的應(yīng)用是在自己的數(shù)據(jù)中心運(yùn)行了袁,那你可能傾向于使用一個不同的HTTP端口來暴露端點。
management.port屬性可以用來改變HTTP端口:
management.port=8081
由于你的管理端口經(jīng)常被防火墻保護(hù)湿颅,不對外暴露也就不需要保護(hù)管理端點载绿,即使你的主要應(yīng)用是安全的。在這種情況下油航,classpath下會存在Spring Security庫崭庸,你可以設(shè)置下面的屬性來禁用安全管理策略(management security):
management.security.enabled=false
(如果classpath下不存在Spring Security,那也就不需要顯示的以這種方式來禁用安全管理策略谊囚,它甚至可能會破壞應(yīng)用程序怕享。)
5.3.4 自定義管理服務(wù)器的地址
你可以通過設(shè)置management.address
屬性來定義管理端點可以使用的地址。這在你只想監(jiān)聽內(nèi)部或面向生產(chǎn)環(huán)境的網(wǎng)絡(luò)镰踏,或只監(jiān)聽來自localhost的連接時非常有用函筋。
下面的application.properties示例不允許遠(yuǎn)程管理連接:
management.port=8081
management.address=127.0.0.1
5.3.5 禁用HTTP端點
如果不想通過HTTP暴露端點,你可以將管理端口設(shè)置為-1: management.port=-1
5.3.6 HTTP Health端點訪問限制
通過health端點暴露的信息根據(jù)是否為匿名訪問而不同。默認(rèn)情況下,當(dāng)匿名訪問時,任何有關(guān)服務(wù)器的健康詳情都被隱藏了垂睬,該端點只簡單的指示服務(wù)器是運(yùn)行(up)還是停止(down)谨敛。此外究履,當(dāng)匿名訪問時,響應(yīng)會被緩存一個可配置的時間段以防止端點被用于'拒絕服務(wù)'攻擊脸狸。endpoints.health.time-to-live
屬性被用來配置緩存時間(單位為毫秒)最仑,默認(rèn)為1000毫秒,也就是1秒炊甲。
上述的限制可以被禁止盯仪,從而允許匿名用戶完全訪問health端點。想達(dá)到這個效果蜜葱,可以將endpoints.health.sensitive
設(shè)為false
。
5.4 基于JMX的監(jiān)控和管理
Java管理擴(kuò)展(JMX)提供了一種標(biāo)準(zhǔn)的監(jiān)控和管理應(yīng)用的機(jī)制耀石。默認(rèn)情況下牵囤,Spring Boot在org.springframework.boot
域下將管理端點暴露為JMX MBeans。
5.4.1 自定義MBean名稱
MBean的名稱通常產(chǎn)生于端點的id滞伟。例如揭鳞,health端點被暴露為org.springframework.boot/Endpoint/HealthEndpoint
。
如果你的應(yīng)用包含多個Spring ApplicationContext梆奈,你會發(fā)現(xiàn)存在名稱沖突野崇。為了解決這個問題,你可以將endpoints.jmx.uniqueNames
設(shè)置為true亩钟,這樣MBean的名稱總是唯一的乓梨。
你也可以自定義JMX域,所有的端點都在該域下暴露清酥。這里有個application.properties示例: ···java endpoints.jmx.domain=myapp endpoints.jmx.uniqueNames=true
5.4.2 禁用JMX端點
如果不想通過JMX暴露端點扶镀,你可以將spring.jmx.enabled屬性設(shè)置為false:
spring.jmx.enabled=false
5.4.3 使用Jolokia通過HTTP實現(xiàn)JMX遠(yuǎn)程管理
Jolokia是一個JMX-HTTP橋,它提供了一種訪問JMX beans的替代方法焰轻。想要使用Jolokia臭觉,只需添加org.jolokia:jolokia-core
的依賴。例如辱志,使用Maven需要添加下面的配置:
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
在你的管理HTTP服務(wù)器上可以通過/jolokia
訪問Jolokia蝠筑。
5.4.3.1 自定義Jolokia
Jolokia有很多配置,傳統(tǒng)上一般使用servlet參數(shù)進(jìn)行設(shè)置揩懒。使用Spring Boot什乙,你可以在application.properties中通過把參數(shù)加上jolokia.config.前綴來設(shè)置:
jolokia.config.debug=true
5.4.3.2 禁用Jolokia
如果你正在使用Jolokia,但不想讓Spring Boot配置它旭从,只需要簡單的將endpoints.jolokia.enabled屬性設(shè)置為false:
endpoints.jolokia.enabled=false
5.4.4 使用遠(yuǎn)程shell來進(jìn)行監(jiān)控和管理
Spring Boot支持集成一個稱為'CRaSH'的Java shell稳强。你可以在CRaSH中使用ssh或telnet命令連接到運(yùn)行的應(yīng)用场仲。為了啟用遠(yuǎn)程shell支持,你只需添加spring-boot-starter-remote-shell
的依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-remote-shell</artifactId>
</dependency>
注:如果想使用telnet訪問退疫,你還需添加對org.crsh:crsh.shell.telnet
的依賴渠缕。
5.4.4.1 連接遠(yuǎn)程shell
默認(rèn)情況下,遠(yuǎn)程shell監(jiān)聽端口2000以等待連接褒繁。默認(rèn)用戶名為user亦鳞,密碼為隨機(jī)生成的,并且在輸出日志中會顯示棒坏。如果應(yīng)用使用Spring Security燕差,該shell默認(rèn)使用相同的配置。如果不是坝冕,將使用一個簡單的認(rèn)證策略徒探,你可能會看到類似這樣的信息:
Using default password for shell access: ec03e16c-4cf4-49ee-b745-7c8255c1dd7e
Linux和OSX用戶可以使用ssh連接遠(yuǎn)程shell,Windows用戶可以下載并安裝PuTTY喂窟。
$ ssh -p 2000 user@localhost
user@localhost's password:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.3.0.BUILD-SNAPSHOT) on myhost
輸入help可以獲取一系列命令的幫助测暗。Spring boot提供metrics
,beans
磨澡,autoconfig
和endpoint
命令碗啄。
5.4.4.1.1 遠(yuǎn)程shell證書
你可以使用shell.auth.simple.user.name和shell.auth.simple.user.password屬性配置自定義的連接證書。也可以使用Spring Security的AuthenticationManager處理登錄職責(zé)稳摄。具體參考JavadocCrshAutoConfiguration和ShellProperties稚字。
5.4.4.2 擴(kuò)展遠(yuǎn)程shell
有很多有趣的方式可以用來擴(kuò)展遠(yuǎn)程shell。
5.4.4.2.1 遠(yuǎn)程shell命令
你可以使用Groovy或Java編寫其他的shell命令(具體參考CRaSH文檔)厦酬。默認(rèn)情況下胆描,Spring Boot會搜索以下路徑的命令:
- classpath:/commands/*
- classpath:/crash/commands/*
注:可以通過shell.commandPathPatterns屬性改變搜索路徑。
下面是一個從src/main/resources/commands/hello.groovy加載的'hello world'命令:
package commands
import org.crsh.cli.Usage
import org.crsh.cli.Command
class hello {
@Usage("Say Hello")
@Command
def main(InvocationContext context) {
return "Hello"
}
}
Spring Boot將一些額外屬性添加到了InvocationContext仗阅,你可以在命令中訪問它們:
屬性名稱 | 描述 |
---|---|
spring.boot.version | Spring Boot的版本 |
spring.version | Spring框架的核心版本 |
spring.beanfactory | 獲取Spring的BeanFactory |
spring.environment | 獲取Spring的Environment |
5.4.4.2.2 遠(yuǎn)程shell插件
除了創(chuàng)建新命令袄友,也可以擴(kuò)展CRaSH shell的其他特性。所有繼承org.crsh.plugin.CRaSHPlugin的Spring Beans將自動注冊到shell霹菊。
具體查看CRaSH參考文檔剧蚣。
5.4.5 度量指標(biāo)
Spring Boot執(zhí)行器包括一個支持'gauge'和'counter'級別的度量指標(biāo)服務(wù)。'gauge'記錄一個單一值旋廷;'counter'記錄一個增量(增加或減少)鸠按。同時,Spring Boot提供一個PublicMetrics接口饶碘,你可以實現(xiàn)它目尖,從而暴露以上兩種機(jī)制不能記錄的指標(biāo)。具體參考SystemPublicMetrics扎运。
所有HTTP請求的指標(biāo)都被自動記錄瑟曲,所以如果點擊metrics端點饮戳,你可能會看到類似以下的響應(yīng):
{
"counter.status.200.root": 20,
"counter.status.200.metrics": 3,
"counter.status.200.star-star": 5,
"counter.status.401.root": 4,
"gauge.response.star-star": 6,
"gauge.response.root": 2,
"gauge.response.metrics": 3,
"classes": 5808,
"classes.loaded": 5808,
"classes.unloaded": 0,
"heap": 3728384,
"heap.committed": 986624,
"heap.init": 262144,
"heap.used": 52765,
"mem": 986624,
"mem.free": 933858,
"processors": 8,
"threads": 15,
"threads.daemon": 11,
"threads.peak": 15,
"uptime": 494836,
"instance.uptime": 489782,
"datasource.primary.active": 5,
"datasource.primary.usage": 0.25
}
此處我們可以看到基本的memory,heap洞拨,class loading扯罐,processor和thread pool信息,連同一些HTTP指標(biāo)烦衣。在該實例中歹河,root('/'),/metrics URLs分別返回20次花吟,3次HTTP 200響應(yīng)秸歧。同時可以看到root URL返回了4次HTTP 401(unauthorized)響應(yīng)。雙asterix(star-star)來自于被Spring MVC /**匹配到的一個請求(通常為一個靜態(tài)資源)衅澈。
gauge級別展示了一個請求的最后響應(yīng)時間键菱。所以,root的最后請求被響應(yīng)耗時2毫秒今布,/metrics耗時3毫秒纱耻。
5.4.5.1 系統(tǒng)指標(biāo)
Spring Boot暴露以下系統(tǒng)指標(biāo):
- 系統(tǒng)內(nèi)存總量(mem),單位:Kb
- 空閑內(nèi)存數(shù)量(mem.free)险耀,單位:Kb
- 處理器數(shù)量(processors)
- 系統(tǒng)正常運(yùn)行時間(uptime),單位:毫秒
- 應(yīng)用上下文(就是一個應(yīng)用實例)正常運(yùn)行時間(instance.uptime)玖喘,單位:毫秒
- 系統(tǒng)平均負(fù)載(systemload.average)
- 堆信息(heap甩牺,heap.committed,heap.init累奈,heap.used)贬派,單位:Kb
- 線程信息(threads,thread.peak澎媒,thead.daemon)
- 類加載信息(classes搞乏,classes.loaded,classes.unloaded)
- 垃圾收集信息(gc.xxx.count, gc.xxx.time)
5.4.5.2 數(shù)據(jù)源指標(biāo)
Spring Boot會為你應(yīng)用中定義的支持的DataSource暴露以下指標(biāo):
- 最大連接數(shù)(datasource.xxx.max)
- 最小連接數(shù)(datasource.xxx.min)
- 活動連接數(shù)(datasource.xxx.active)
- 連接池的使用情況(datasource.xxx.usage)
所有的數(shù)據(jù)源指標(biāo)共用datasoure.前綴戒努。該前綴對每個數(shù)據(jù)源都非常合適:
- 如果是主數(shù)據(jù)源(唯一可用的數(shù)據(jù)源或存在的數(shù)據(jù)源中被@Primary標(biāo)記的)前綴為datasource.primary
- 如果數(shù)據(jù)源bean名稱以dataSource結(jié)尾请敦,那前綴就是bean的名稱去掉dataSource的部分(例如,batchDataSource的前綴是datasource.batch)
- 其他情況使用bean的名稱作為前綴
通過注冊一個自定義版本的DataSourcePublicMetrics bean储玫,你可以覆蓋部分或全部的默認(rèn)行為侍筛。默認(rèn)情況下,Spring Boot提供支持所有數(shù)據(jù)源的元數(shù)據(jù)撒穷;如果你喜歡的數(shù)據(jù)源恰好不被支持匣椰,你可以添加另外的DataSourcePoolMetadataProvider beans。具體參考DataSourcePoolMetadataProvidersConfiguration端礼。
5.4.5.3 Tomcat session指標(biāo)
如果你使用Tomcat作為內(nèi)嵌的servlet容器禽笑,session指標(biāo)將被自動暴露出去入录。 httpsessions.active
和httpsessions.max
提供了活動的和最大的session數(shù)量。
5.4.5.4 記錄自己的指標(biāo)
想要記錄你自己的指標(biāo)佳镜,只需將CounterService或GaugeService注入到你的bean中僚稿。CounterService暴露increment,decrement和reset方法邀杏;GaugeService提供一個submit方法贫奠。
下面是一個簡單的示例,它記錄了方法調(diào)用的次數(shù):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private final CounterService counterService;
@Autowired
public MyService(CounterService counterService) {
this.counterService = counterService;
}
public void exampleMethod() {
this.counterService.increment("services.system.myservice.invoked");
}
}
注:你可以將任何的字符串用作指標(biāo)的名稱望蜡,但最好遵循所選存儲或圖技術(shù)的指南唤崭。Matt Aimonetti’s Blog中有一些好的關(guān)于圖(Graphite)的指南。
5.4.5.5 添加你自己的公共指標(biāo)
想要添加額外的脖律,每次指標(biāo)端點被調(diào)用時都會重新計算的度量指標(biāo)谢肾,只需簡單的注冊其他的PublicMetrics實現(xiàn)bean(s)。默認(rèn)情況下小泉,端點會聚合所有這樣的beans芦疏,通過定義自己的MetricsEndpoint可以輕易改變這種情況。
5.4.5.6 指標(biāo)倉庫
通過綁定一個MetricRepository來實現(xiàn)指標(biāo)服務(wù)。MetricRepository
負(fù)責(zé)存儲和追溯指標(biāo)信息。Spring Boot提供一個InMemoryMetricRepository
和一個RedisMetricRepository
(默認(rèn)使用in-memory倉庫)抚官,不過你可以編寫自己的MetricRepository
鳖眼。MetricRepository
接口實際是MetricReader
接口和MetricWriter接口的上層組合。具體參考Javadoc
沒有什么能阻止你直接將MetricRepository
的數(shù)據(jù)導(dǎo)入應(yīng)用中的后端存儲,但我們建議你使用默認(rèn)的InMemoryMetricRepository
(如果擔(dān)心堆使用情況,你可以使用自定義的Map實例),然后通過一個scheduled export job填充后端倉庫(意思是先將數(shù)據(jù)保存到內(nèi)存中酪穿,然后通過異步j(luò)ob將數(shù)據(jù)持久化到數(shù)據(jù)庫,可以提高系統(tǒng)性能)晴裹。通過這種方式被济,你可以將指標(biāo)數(shù)據(jù)緩存到內(nèi)存中,然后通過低頻率或批量導(dǎo)出來減少網(wǎng)絡(luò)擁堵涧团。Spring Boot提供一個Exporter接口及一些幫你開始的基本實現(xiàn)只磷。
5.4.5.7 Dropwizard指標(biāo)
Dropwizard ‘Metrics’庫的用戶會發(fā)現(xiàn)Spring Boot指標(biāo)被發(fā)布到了com.codahale.metrics.MetricRegistry。當(dāng)你聲明對io.dropwizard.metrics:metrics-core庫的依賴時會創(chuàng)建一個默認(rèn)的com.codahale.metrics.MetricRegistry Spring bean泌绣;如果需要自定義喳瓣,你可以注冊自己的@Bean實例。來自于MetricRegistry的指標(biāo)也是自動通過/metrics端點暴露的赞别。
用戶可以通過使用合適類型的指標(biāo)名稱作為前綴來創(chuàng)建Dropwizard指標(biāo)(比如畏陕,histogram.* , meter.*)。
5.4.5.8 消息渠道集成
如果你的classpath下存在'Spring Messaging' jar仿滔,一個名為metricsChannel的MessageChannel將被自動創(chuàng)建(除非已經(jīng)存在一個)惠毁。此外犹芹,所有的指標(biāo)更新事件作為'messages'發(fā)布到該渠道上。訂閱該渠道的客戶端可以進(jìn)行額外的分析或行動鞠绰。
5.4.6 審計
Spring Boot執(zhí)行器具有一個靈活的審計框架腰埂,一旦Spring Security處于活動狀態(tài)(默認(rèn)拋出'authentication success','failure'和'access denied'異常)蜈膨,它就會發(fā)布事件屿笼。這對于報告非常有用,同時可以基于認(rèn)證失敗實現(xiàn)一個鎖定策略翁巍。
你也可以使用審計服務(wù)處理自己的業(yè)務(wù)事件驴一。為此,你可以將存在的AuditEventRepository注入到自己的組件灶壶,并直接使用它肝断,或者只是簡單地通過Spring ApplicationEventPublisher發(fā)布AuditApplicationEvent(使用ApplicationEventPublisherAware)。
5.4.7 追蹤(Tracing)
對于所有的HTTP請求Spring Boot自動啟用追蹤驰凛。你可以查看trace端點胸懈,并獲取最近一些請求的基本信息:
[{
"timestamp": 1394343677415,
"info": {
"method": "GET",
"path": "/trace",
"headers": {
"request": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Connection": "keep-alive",
"Accept-Encoding": "gzip, deflate",
"User-Agent": "Mozilla/5.0 Gecko/Firefox",
"Accept-Language": "en-US,en;q=0.5",
"Cookie": "_ga=GA1.1.827067509.1390890128; ..."
"Authorization": "Basic ...",
"Host": "localhost:8080"
},
"response": {
"Strict-Transport-Security": "max-age=31536000 ; includeSubDomains",
"X-Application-Context": "application:8080",
"Content-Type": "application/json;charset=UTF-8",
"status": "200"
}
}
}
},{
"timestamp": 1394343684465,
...
}]
5.4.7.1 自定義追蹤
如果需要追蹤其他的事件,你可以將一個TraceRepository注入到你的Spring Beans中恰响。add方法接收一個將被轉(zhuǎn)化為JSON的Map結(jié)構(gòu)趣钱,該數(shù)據(jù)將被記錄下來。
默認(rèn)情況下胚宦,使用的InMemoryTraceRepository將存儲最新的100個事件首有。如果需要擴(kuò)展該容量,你可以定義自己的InMemoryTraceRepository實例间唉。如果需要,你可以創(chuàng)建自己的替代TraceRepository實現(xiàn)利术。
5.4.8 進(jìn)程監(jiān)控
在Spring Boot執(zhí)行器中呈野,你可以找到幾個創(chuàng)建有利于進(jìn)程監(jiān)控的文件的類:
- ApplicationPidFileWriter創(chuàng)建一個包含應(yīng)用PID的文件(默認(rèn)位于應(yīng)用目錄,文件名為application.pid)
- EmbeddedServerPortFileWriter創(chuàng)建一個或多個包含內(nèi)嵌服務(wù)器端口的文件(默認(rèn)位于應(yīng)用目錄印叁,文件名為application.port)
默認(rèn)情況下被冒,這些writers沒有被激活,但你可以使用下面描述的任何方式來啟用它們轮蜕。
5.4.8.1 擴(kuò)展屬性
你需要激活META-INF/spring.factories文件里的listener(s):
org.springframework.context.ApplicationListener=\
org.springframework.boot.actuate.system.ApplicationPidFileWriter,
org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter
5.4.8.2 以編程方式
你也可以通過調(diào)用SpringApplication.addListeners(…)方法來激活一個監(jiān)聽器昨悼,并傳遞相應(yīng)的Writer對象。該方法允許你通過Writer構(gòu)造器自定義文件名和路徑跃洛。
部署到云端
對于大多數(shù)流行云PaaS(平臺即服務(wù))提供商率触,Spring Boot的可執(zhí)行jars就是為它們準(zhǔn)備的。這些提供商往往要求你帶上自己的容器汇竭;它們管理應(yīng)用的進(jìn)程(不特別針對Java應(yīng)用程序)葱蝗,所以它們需要一些中間層來將你的應(yīng)用適配到云概念中的一個運(yùn)行進(jìn)程穴张。
兩個流行的云提供商,Heroku和Cloud Foundry两曼,采取一個打包('buildpack')方法皂甘。為了啟動你的應(yīng)用程序,不管需要什么悼凑,buildpack都會將它們打包到你的部署代碼:它可能是一個JDK和一個java調(diào)用偿枕,也可能是一個內(nèi)嵌的webserver,或者是一個成熟的應(yīng)用服務(wù)器户辫。buildpack是可插拔的渐夸,但你最好盡可能少的對它進(jìn)行自定義設(shè)置。這可以減少不受你控制的功能范圍寸莫,最小化部署和生產(chǎn)環(huán)境的發(fā)散捺萌。
理想情況下,你的應(yīng)用就像一個Spring Boot可執(zhí)行jar膘茎,所有運(yùn)行需要的東西都打包到它內(nèi)部桃纯。
6.1 Cloud Foundry
如果不指定其他打包方式,Cloud Foundry會啟用它提供的默認(rèn)打包方式披坏。Cloud Foundry的Java buildpack對Spring應(yīng)用有出色的支持态坦,包括Spring Boot。你可以部署獨立的可執(zhí)行jar應(yīng)用棒拂,也可以部署傳統(tǒng)的.war形式的應(yīng)用伞梯。
一旦你構(gòu)建了應(yīng)用(比如,使用mvn clean package)并安裝了cf命令行工具帚屉,你可以使用下面的cf push命令(將路徑指向你編譯后的.jar)來部署應(yīng)用谜诫。在發(fā)布一個應(yīng)用前,確保你已登陸cf命令行客戶端攻旦。
$ cf push acloudyspringtime -p target/demo-0.0.1-SNAPSHOT.jar
查看cf push文檔獲取更多可選項喻旷。如果相同目錄下存在manifest.yml,Cloud Foundry會使用它牢屋。
就此且预,cf開始上傳你的應(yīng)用:
Uploading acloudyspringtime... OK
Preparing to start acloudyspringtime... OK
-----> Downloaded app package (8.9M)
-----> Java Buildpack source: system
-----> Downloading Open JDK 1.7.0_51 from .../x86_64/openjdk-1.7.0_51.tar.gz (1.8s)
Expanding Open JDK to .java-buildpack/open_jdk (1.2s)
-----> Downloading Spring Auto Reconfiguration from 0.8.7 .../auto-reconfiguration-0.8.7.jar (0.1s)
-----> Uploading droplet (44M)
Checking status of app 'acloudyspringtime'...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 down)
...
0 of 1 instances running (1 starting)
...
1 of 1 instances running (1 running)
App started
恭喜!應(yīng)用現(xiàn)在處于運(yùn)行狀態(tài)烙无!
檢驗部署應(yīng)用的狀態(tài)是很簡單的:
$ cf apps
Getting applications in ...
OK
name requested state instances memory disk urls
...
acloudyspringtime started 1/1 512M 1G acloudyspringtime.cfapps.io
...
一旦Cloud Foundry意識到你的應(yīng)用已經(jīng)部署锋谐,你就可以點擊給定的應(yīng)用URI,此處是acloudyspringtime.cfapps.io/截酷。
6.1.1 綁定服務(wù)
默認(rèn)情況下涮拗,運(yùn)行應(yīng)用的元數(shù)據(jù)和服務(wù)連接信息被暴露為應(yīng)用的環(huán)境變量(比如,$VCAP_SERVICES)。采用這種架構(gòu)的原因是因為Cloud Foundry多語言特性(任何語言和平臺都支持作為buildpack)多搀。進(jìn)程級別的環(huán)境變量是語言無關(guān)(language agnostic)的歧蕉。
環(huán)境變量并不總是有利于設(shè)計最簡單的API,所以Spring Boot自動提取它們康铭,然后將這些數(shù)據(jù)導(dǎo)入能夠通過Spring Environment抽象訪問的屬性里:
@Component
class MyBean implements EnvironmentAware {
private String instanceId;
@Override
public void setEnvironment(Environment environment) {
this.instanceId = environment.getProperty("vcap.application.instance_id");
}
// ...
}
所有的Cloud Foundry屬性都以vcap作為前綴惯退。你可以使用vcap屬性獲取應(yīng)用信息(比如應(yīng)用的公共URL)和服務(wù)信息(比如數(shù)據(jù)庫證書)。具體參考VcapApplicationListener Javadoc从藤。
注:Spring Cloud Connectors項目很適合比如配置數(shù)據(jù)源的任務(wù)催跪。Spring Boot提供自動配置支持和一個spring-boot-starter-cloud-connectors starter POM。
6.2 Heroku
Heroku是另外一個流行的Paas平臺夷野。想要自定義Heroku的構(gòu)建過程懊蒸,你可以提供一個Procfile,它提供部署一個應(yīng)用所需的指令悯搔。Heroku為Java應(yīng)用分配一個端口骑丸,確保能夠路由到外部URI。
你必須配置你的應(yīng)用監(jiān)聽正確的端口妒貌。下面是用于我們的starter REST應(yīng)用的Procfile:
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
Spring Boot將-D參數(shù)作為屬性通危,通過一個Spring的Environment實例訪問。server.port配置屬性適合于內(nèi)嵌的Tomcat灌曙,Jetty或Undertow實例啟用時使用菊碟。$PORT環(huán)境變量被分配給Heroku Paas使用。
Heroku默認(rèn)使用Java 1.6在刺。只要你的Maven或Gradle構(gòu)建時使用相同的版本就沒問題(Maven用戶可以設(shè)置java.version屬性)逆害。如果你想使用JDK 1.7,在你的pom.xml和Procfile臨近處創(chuàng)建一個system.properties文件蚣驼。在該文件中添加以下設(shè)置:
java.runtime.version=1.7
這就是你需要做的一切魄幕。對于Heroku部署來說,經(jīng)常做的工作就是使用git push將代碼推送到生產(chǎn)環(huán)境颖杏。
$ git push heroku master
Initializing repository, done.
Counting objects: 95, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (78/78), done.
Writing objects: 100% (95/95), 8.66 MiB | 606.00 KiB/s, done.
Total 95 (delta 31), reused 0 (delta 0)
-----> Java app detected
-----> Installing OpenJDK 1.7... done
-----> Installing Maven 3.2.3... done
-----> Installing settings.xml... done
-----> executing /app/tmp/cache/.maven/bin/mvn -B
-Duser.home=/tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229
-Dmaven.repo.local=/app/tmp/cache/.m2/repository
-s /app/tmp/cache/.m2/settings.xml -DskipTests=true clean install
[INFO] Scanning for projects...
Downloading: http://repo.spring.io/...
Downloaded: http://repo.spring.io/... (818 B at 1.8 KB/sec)
....
Downloaded: http://s3pository.heroku.com/jvm/... (152 KB at 595.3 KB/sec)
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/target/...
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/pom.xml ...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 59.358s
[INFO] Finished at: Fri Mar 07 07:28:25 UTC 2014
[INFO] Final Memory: 20M/493M
[INFO] ------------------------------------------------------------------------
-----> Discovering process types
Procfile declares types -> web
-----> Compressing... done, 70.4MB
-----> Launching... done, v6
http://agile-sierra-1405.herokuapp.com/ deployed to Heroku
To git@heroku.com:agile-sierra-1405.git
* [new branch] master -> master
現(xiàn)在你的應(yīng)用已經(jīng)啟動并運(yùn)行在Heroku纯陨。
6.3 Openshift
Openshift是RedHat公共(和企業(yè))PaaS解決方案。和Heroku相似输玷,它也是通過運(yùn)行被git提交觸發(fā)的腳本來工作的队丝,所以你可以使用任何你喜歡的方式編寫Spring Boot應(yīng)用啟動腳本靡馁,只要Java運(yùn)行時環(huán)境可用(這是在Openshift上可以要求的一個標(biāo)準(zhǔn)特性)欲鹏。為了實現(xiàn)這樣的效果,你可以使用DIY Cartridge臭墨,并在.openshift/action_scripts下hooks你的倉庫:
基本模式如下:
1.確保Java和構(gòu)建工具已被遠(yuǎn)程安裝赔嚎,比如使用一個pre_build hook(默認(rèn)會安裝Java和Maven,不會安裝Gradle)。
2.使用一個build hook去構(gòu)建你的jar(使用Maven或Gradle)泼各,比如
#!/bin/bash
cd $OPENSHIFT_REPO_DIR
mvn package -s .openshift/settings.xml -DskipTests=true
3.添加一個調(diào)用java -jar …?的start hook
#!/bin/bash
cd $OPENSHIFT_REPO_DIR
nohup java -jar target/*.jar --server.port=${OPENSHIFT_DIY_PORT} --server.address=${OPENSHIFT_DIY_IP} &
4.使用一個stop hook
#!/bin/bash
source $OPENSHIFT_CARTRIDGE_SDK_BASH
PID=$(ps -ef | grep java.*\.jar | grep -v grep | awk '{ print $2 }')
if [ -z "$PID" ]
then
client_result "Application is already stopped"
else
kill $PID
fi
5.將內(nèi)嵌的服務(wù)綁定到平臺提供的在application.properties定義的環(huán)境變量姿现,比如
spring.datasource.url: jdbc:mysql://${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/${OPENSHIFT_APP_NAME}
spring.datasource.username: ${OPENSHIFT_MYSQL_DB_USERNAME}
spring.datasource.password: ${OPENSHIFT_MYSQL_DB_PASSWORD}
在Openshift的網(wǎng)站上有一篇running Gradle in Openshift博客毛萌,如果想使用gradle構(gòu)建運(yùn)行的應(yīng)用可以參考它。由于一個Gradle bug软棺,你不能使用高于1.6版本的Gradle。
6.4 Google App Engine
Google App Engine跟Servlet 2.5 API是有聯(lián)系的尤勋,所以在不修改的情況系你是不能部署一個Spring應(yīng)用的喘落。具體查看本指南的Servlet 2.5章節(jié) Container.md)。
Spring Boot CLI
Spring Boot CLI是一個命令行工具最冰,如果想使用Spring進(jìn)行快速開發(fā)可以使用它瘦棋。它允許你運(yùn)行Groovy腳本,這意味著你可以使用熟悉的類Java語法暖哨,并且沒有那么多的模板代碼赌朋。你也可以啟動一個新的項目或為Spring Boot CLI編寫自己的命令。
7.1 安裝CLI
你可以手動安裝Spring Boot CLI篇裁,也可以使用GVM(Groovy環(huán)境管理工具)或Homebrew沛慢,MacPorts(如果你是一個OSX用戶)。參考"Getting started"的Section 10.2, “Installing the Spring Boot CLI” 可以看到全面的安裝指令茴恰。
7.2 使用CLI
一旦安裝好CLI颠焦,你可以輸入spring來運(yùn)行它。如果你不使用任何參數(shù)運(yùn)行spring往枣,將會展現(xiàn)一個簡單的幫助界面:
$ spring
usage: spring [--help] [--version]
[]
Available commands are:
run [options] [--] [args]
Run a spring groovy script
... more command help is shown here
你可以使用help獲取任何支持命令的詳細(xì)信息伐庭。例如:
$ spring help run
spring run - Run a spring groovy script
usage: spring run [options] [--] [args]
Option Description
------ -----------
--autoconfigure [Boolean] Add autoconfigure compiler
transformations (default: true)
--classpath, -cp Additional classpath entries
-e, --edit Open the file with the default system
editor
--no-guess-dependencies Do not attempt to guess dependencies
--no-guess-imports Do not attempt to guess imports
-q, --quiet Quiet logging
-v, --verbose Verbose logging of dependency
resolution
--watch Watch the specified file for changes
version命令提供一個檢查你正在使用的Spring Boot版本的快速方式:
$ spring version
Spring CLI v1.3.0.BUILD-SNAPSHOT
7.2.1 使用CLI運(yùn)行應(yīng)用
你可以使用run命令編譯和運(yùn)行Groovy源代碼。Spring Boot CLI完全自包含分冈,以致于你不需要安裝任何外部的Groovy圾另。
下面是一個使用Groovy編寫的"hello world" web應(yīng)用: hello.grooy
@RestController
class WebApplication {
@RequestMapping("/")
String home() {
"Hello World!"
}
}
想要編譯和運(yùn)行應(yīng)用,輸入:
$ spring run hello.groovy
想要給應(yīng)用傳遞命令行參數(shù)雕沉,你需要使用一個--來將它們和"spring"命令參數(shù)區(qū)分開來集乔。例如:
$ spring run hello.groovy -- --server.port=9000
想要設(shè)置JVM命令行參數(shù),你可以使用JAVA_OPTS環(huán)境變量坡椒,例如:
$ JAVA_OPTS=-Xmx1024m spring run hello.groovy
7.2.1.1 推斷"grab"依賴
標(biāo)準(zhǔn)的Groovy包含一個@Grab
注解扰路,它允許你聲明對第三方庫的依賴。這項有用的技術(shù)允許Groovy以和Maven或Gradle相同的方式下載jars倔叼,但不需要使用構(gòu)建工具汗唱。
Spring Boot進(jìn)一步延伸了該技術(shù),它會基于你的代碼嘗試推導(dǎo)你"grab"哪個庫丈攒。例如哩罪,由于WebApplication代碼上使用了@RestController
注解授霸,"Tomcat"和"Spring MVC"將被獲取(grabbed)际插。
下面items被用作"grab hints":
items | Grabs |
---|---|
JdbcTemplate,NamedParameterJdbcTemplate,DataSource | JDBC應(yīng)用 |
@EnableJms | JMS應(yīng)用 |
@EnableCaching | Caching abstraction |
@Test | JUnit |
@EnableRabbit | RabbitMQ |
@EnableReactor | Project Reactor |
繼承Specification | Spock test |
@EnableBatchProcessing | Spring Batch |
@MessageEndpoint,@EnableIntegrationPatterns | Spring Integration |
@EnableDeviceResolver | Spring Mobile |
@Controller,@RestController,@EnableWebMvc | Spring MVC + Embedded Tomcat |
@EnableWebSecurity | Spring Security |
@EnableTransactionManagement | Spring Transaction Management |
注:想要理解自定義是如何生效碘耳,可以查看Spring Boot CLI源碼中的CompilerAutoConfiguration子類。
7.2.1.2 推斷"grab"坐標(biāo)
Spring Boot擴(kuò)展Groovy標(biāo)準(zhǔn)"@Grab"注解使其能夠允許你指定一個沒有g(shù)roup或version的依賴框弛,例如@Grab('freemarker')辛辨。 artifact’s的組和版本是通過查看Spring Boot的依賴元數(shù)據(jù)推斷出來的。注意默認(rèn)的元數(shù)據(jù)是和你使用的CLI版本綁定的-只有在你遷移到一個CLI新版本時它才會改變瑟枫,這樣當(dāng)你的依賴改變時你就可以控制了愉阎。在附錄的表格中可以查看默認(rèn)元數(shù)據(jù)包含的依賴和它們的版本。
7.2.1.3 默認(rèn)import語句
為了幫助你減少Groovy代碼量力奋,一些import語句被自動包含進(jìn)來了榜旦。注意上面的示例中引用@Component,@RestController和@RequestMapping而沒有使用全限定名或import語句景殷。
注:很多Spring注解在不使用import語句的情況下可以正常工作溅呢。嘗試運(yùn)行你的應(yīng)用,看一下在添加imports之前哪些會失敗猿挚。
7.2.1.4 自動創(chuàng)建main方法
跟等效的Java應(yīng)用不同咐旧,你不需要在Groovy腳本中添加一個public static void main(String[] args)方法。Spring Boot 會使用你編譯后的代碼自動創(chuàng)建一個SpringApplication绩蜻。
7.2.1.5 自定義"grab"元數(shù)據(jù)
Spring Boot提供一個新的@GrabMetadata注解铣墨,你可以使用它提供自定義的依賴元數(shù)據(jù),以覆蓋Spring Boot的默認(rèn)配置办绝。該元數(shù)據(jù)通過使用提供一個或多個配置文件坐標(biāo)的注解來指定(使用一個屬性標(biāo)識符"type"部署到Maven倉庫).伊约。配置文件中的每個實體必須遵循group:module=version的格式。
例如孕蝉,下面的聲明:
`@GrabMetadata("com.example.custom-versions:1.0.0")`
將會加載Maven倉庫處于com/example/custom-versions/1.0.0/
下的custom-versions-1.0.0.properties
文件屡律。
可以通過注解指定多個屬性文件,它們會以聲明的順序被使用降淮。例如:
`@GrabMetadata(["com.example.custom-versions:1.0.0",
"com.example.more-versions:1.0.0"])`
意味著位于more-versions的屬性將覆蓋位于custom-versions的屬性超埋。
你可以在任何能夠使用@Grab的地方使用@GrabMetadata,然而佳鳖,為了確保元數(shù)據(jù)的順序一致霍殴,你在應(yīng)用程序中最多只能使用一次@GrabMetadata。Spring IO Platform是一個非常有用的依賴元數(shù)據(jù)源(Spring Boot的超集)系吩,例如:
@GrabMetadata('io.spring.platform:platform-versions:1.0.4.RELEASE')
7.2.2 測試你的代碼
test命令允許你編譯和運(yùn)行應(yīng)用程序的測試用例来庭。常規(guī)使用方式如下:
$ spring test app.groovy tests.groovy
Total: 1, Success: 1, : Failures: 0
Passed? true
在這個示例中,test.groovy包含JUnit @Test方法或Spock Specification類淑玫。所有的普通框架注解和靜態(tài)方法在不使用import導(dǎo)入的情況下巾腕,仍舊可以使用。
下面是我們使用的test.groovy文件(含有一個JUnit測試):
class ApplicationTests {
@Test
void homeSaysHello() {
assertEquals("Hello World!", new WebApplication().home())
}
}
注:如果有多個測試源文件絮蒿,你可以傾向于使用一個test目錄來組織它們尊搬。
7.2.3 多源文件應(yīng)用
你可以在所有接收文件輸入的命令中使用shell通配符。這允許你輕松處理來自一個目錄下的多個文件土涝,例如:
$ spring run *.groovy
如果你想將'test'或'spec'代碼從主應(yīng)用代碼中分離佛寿,這項技術(shù)就十分有用了:
$ spring test app/*.groovy test/*.groovy
7.2.4 應(yīng)用打包
你可以使用jar命令打包應(yīng)用程序為一個可執(zhí)行的jar文件。例如:
$ spring jar my-app.jar *.groovy
最終的jar包括編譯應(yīng)用產(chǎn)生的類和所有依賴但壮,這樣你就可以使用java -jar來執(zhí)行它了冀泻。該jar文件也包括來自應(yīng)用classpath的實體。你可以使用--include和--exclude添加明確的路徑(兩者都是用逗號分割蜡饵,同樣都接收值為'+'和'-'的前綴弹渔,'-'意味著它們將從默認(rèn)設(shè)置中移除)。默認(rèn)包含(includes):
public/**, resources/**, static/**, templates/**, META-INF/**, *
默認(rèn)排除(excludes):
.*, repository/**, build/**, target/**, **/*.jar, **/*.groovy
查看spring help jar可以獲得更多信息溯祸。
7.2.5 初始化新工程
init命令允許你使用start.spring.io在不離開shell的情況下創(chuàng)建一個新的項目肢专。例如:
$ spring init --dependencies=web,data-jpa my-project
Using service at https://start.spring.io
Project extracted to '/Users/developer/example/my-project'
這創(chuàng)建了一個my-project目錄,它是一個基本Maven且依賴spring-boot-starter-web和spring-boot-starter-data-jpa的項目焦辅。你可以使用--list參數(shù)列出該服務(wù)的能力博杖。
$ spring init --list
=======================================
Capabilities of https://start.spring.io
=======================================
Available dependencies:
-----------------------
actuator - Actuator: Production ready features to help you monitor and manage your application
...
web - Web: Support for full-stack web development, including Tomcat and spring-webmvc
websocket - Websocket: Support for WebSocket development
ws - WS: Support for Spring Web Services
Available project types:
------------------------
gradle-build - Gradle Config [format:build, build:gradle]
gradle-project - Gradle Project [format:project, build:gradle]
maven-build - Maven POM [format:build, build:maven]
maven-project - Maven Project [format:project, build:maven] (default)
...
init命令支持很多選項,查看help輸出可以獲得更多詳情筷登。例如剃根,下面的命令創(chuàng)建一個使用Java8和war打包的gradle項目:
$ spring init --build=gradle --java-version=1.8 --dependencies=websocket --packaging=war sample-app.zip
Using service at https://start.spring.io
Content saved to 'sample-app.zip'
7.2.6 使用內(nèi)嵌shell
Spring Boot包括完整的BASH和zsh shells的命令行腳本。如果你不使用它們中的任何一個(可能你是一個Window用戶)前方,那你可以使用shell命令啟用一個集成shell狈醉。
$ spring shell
Spring Boot (v1.3.0.BUILD-SNAPSHOT)
Hit TAB to complete. Type \'help' and hit RETURN for help, and \'exit' to quit.
從內(nèi)嵌shell中可以直接運(yùn)行其他命令:
$ version
Spring CLI v1.3.0.BUILD-SNAPSHOT
內(nèi)嵌shell支持ANSI顏色輸出和tab補(bǔ)全。如果需要運(yùn)行一個原生命令惠险,你可以使用$前綴舔糖。點擊ctrl-c將退出內(nèi)嵌shell。
7.2.7 為CLI添加擴(kuò)展
使用install命令可以為CLI添加擴(kuò)展莺匠。該命令接收一個或多個格式為group:artifact:version的artifact坐標(biāo)集金吗。例如:
$ spring install com.example:spring-boot-cli-extension:1.0.0.RELEASE
除了安裝你提供坐標(biāo)的artifacts標(biāo)識外,所有依賴也會被安裝趣竣。使用uninstall可以卸載一個依賴摇庙。和install命令一樣,它接收一個或多個格式為group:artifact:version的artifact坐標(biāo)集遥缕。例如:
$ spring uninstall com.example:spring-boot-cli-extension:1.0.0.RELEASE
它會通過你提供的坐標(biāo)卸載相應(yīng)的artifacts標(biāo)識和它們的依賴卫袒。
為了卸載所有附加依賴,你可以使用--all選項单匣。例如:
$ spring uninstall --all
7.3 使用Groovy beans DSL開發(fā)應(yīng)用
Spring框架4.0版本對beans{} DSL(借鑒自Grails)提供原生支持夕凝,你可以使用相同的格式在你的Groovy應(yīng)用程序腳本中嵌入bean定義宝穗。有時候這是一個包括外部特性的很好的方式,比如中間件聲明码秉。例如:
@Configuration
class Application implements CommandLineRunner {
@Autowired
SharedService service
@Override
void run(String... args) {
println service.message
}
}
import my.company.SharedService
beans {
service(SharedService) {
message = "Hello World"
}
}
你可以使用beans{}混合位于相同文件的類聲明逮矛,只要它們都處于頂級,或如果你喜歡的話转砖,可以將beans DSL放到一個單獨的文件中须鼎。
構(gòu)建工具插件
Spring Boot為Maven和Gradle提供構(gòu)建工具插件。該插件提供各種各樣的特性府蔗,包括打包可執(zhí)行jars晋控。本節(jié)提供關(guān)于插件的更多詳情及用于擴(kuò)展一個不支持的構(gòu)建系統(tǒng)所需的幫助信息。如果你是剛剛開始姓赤,那可能需要先閱讀Part III, “Using Spring Boot”
章節(jié)的“Chapter 13, Build systems”
赡译。
8.1 Spring Boot Maven插件
Spring Boot Maven插件為Maven提供Spring Boot支持,它允許你打包可執(zhí)行jar或war存檔不铆,然后就地運(yùn)行應(yīng)用捶朵。為了使用它,你需要使用Maven 3.2 (或更高版本)狂男。
注:參考Spring Boot Maven Plugin Site可以獲取全部的插件文檔综看。
8.1.1 包含該插件
想要使用Spring Boot Maven插件只需簡單地在你的pom.xml的plugins部分包含相應(yīng)的XML:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- ... -->
<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>
</project>
該配置會在Maven生命周期的package階段重新打包一個jar或war。下面的示例顯示在target目錄下既有重新打包后的jar岖食,也有原始的jar:
$ mvn package
$ ls target/*.jar
target/myproject-1.0.0.jar target/myproject-1.0.0.jar.original
如果不包含像上面那樣的<execution/>红碑,你可以自己運(yùn)行該插件(但只有在package目標(biāo)也被使用的情況)。例如:
$ mvn package spring-boot:repackage
$ ls target/*.jar
target/myproject-1.0.0.jar target/myproject-1.0.0.jar.original
如果使用一個里程碑或快照版本泡垃,你還需要添加正確的pluginRepository元素:
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
8.1.2 打包可執(zhí)行jar和war文件
一旦spring-boot-maven-plugin被包含到你的pom.xml中析珊,它就會自動嘗試使用spring-boot:repackage目標(biāo)重寫存檔以使它們能夠執(zhí)行港柜。為了構(gòu)建一個jar或war杉武,你應(yīng)該使用常規(guī)的packaging元素配置你的項目:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- ... -->
<packaging>jar</packaging>
<!-- ... -->
</project>
生成的存檔在package階段會被Spring Boot增強(qiáng)。你想啟動的main類即可以通過指定一個配置選項百揭,也可以通過為manifest添加一個Main-Class屬性這種常規(guī)的方式實現(xiàn)存和。如果你沒有指定一個main類奕剃,該插件會搜索帶有public static void main(String[] args)方法的類。
為了構(gòu)建和運(yùn)行一個項目的artifact捐腿,你可以輸入以下命令:
$ mvn package
$ java -jar target/mymodule-0.0.1-SNAPSHOT.jar
為了構(gòu)建一個即是可執(zhí)行的纵朋,又能部署到一個外部容器的war文件,你需要標(biāo)記內(nèi)嵌容器依賴為"provided"茄袖,例如:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- ... -->
<packaging>war</packaging>
<!-- ... -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- ... -->
</dependencies>
</project>
注:具體參考“Section 74.1, “Create a deployable war file”
章節(jié)操软。
在插件信息頁面有高級的配置選項和示例。
8.2 Spring Boot Gradle插件
Spring Boot Gradle插件為Gradle提供Spring Boot支持宪祥,它允許你打包可執(zhí)行jar或war存檔聂薪,運(yùn)行Spring Boot應(yīng)用家乘,對于"神圣的"依賴可以在你的build.gradle文件中省略版本信息。
8.2.1 包含該插件
想要使用Spring Boot Gradle插件藏澳,你只需簡單的包含一個buildscript依賴仁锯,并應(yīng)用spring-boot插件:
buildscript {
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.BUILD-SNAPSHOT")
}
}
apply plugin: 'spring-boot'
如果想使用一個里程碑或快照版本,你可以添加相應(yīng)的repositories引用:
buildscript {
repositories {
maven.url "http://repo.spring.io/snapshot"
maven.url "http://repo.spring.io/milestone"
}
// ...
}
8.2.2 聲明不帶版本的依賴
spring-boot插件會為你的構(gòu)建注冊一個自定義的Gradle ResolutionStrategy笆载,它允許你在聲明對"神圣"的artifacts的依賴時獲取版本號。為了充分使用該功能涯呻,只需要想通常那樣聲明依賴凉驻,但將版本號設(shè)置為空:
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.thymeleaf:thymeleaf-spring4")
compile("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
}
注:你聲明的spring-boot Gradle插件的版本決定了"blessed"依賴的實際版本(確保可以重復(fù)構(gòu)建)复罐。你最好總是將spring-boot gradle插件版本設(shè)置為你想用的Spring Boot實際版本涝登。提供的版本詳細(xì)信息可以在附錄中找到。
spring-boot插件對于沒有指定版本的依賴只會提供一個版本效诅。如果不想使用插件提供的版本胀滚,你可以像平常那樣在聲明依賴的時候指定版本。例如:
dependencies {
compile("org.thymeleaf:thymeleaf-spring4:2.1.1.RELEASE")
}
8.2.2.1 自定義版本管理
如果你需要不同于Spring Boot的"blessed"依賴乱投,有可能的話可以自定義ResolutionStrategy使用的版本咽笼。替代的版本元數(shù)據(jù)使用versionManagement配置。例如:
dependencies {
versionManagement("com.mycorp:mycorp-versions:1.0.0.RELEASE@properties")
compile("org.springframework.data:spring-data-hadoop")
}
版本信息需要作為一個.properties文件發(fā)布到一個倉庫中戚炫。對于上面的示例剑刑,mycorp-versions.properties文件可能包含以下內(nèi)容:
org.springframework.data\:spring-data-hadoop=2.0.0.RELEASE
屬性文件優(yōu)先于Spring Boot默認(rèn)設(shè)置,如果有必要的話可以覆蓋版本號双肤。
8.2.3 默認(rèn)排除規(guī)則
Gradle處理"exclude rules"的方式和Maven稍微有些不同施掏,在使用starter POMs時這可能會引起無法預(yù)料的結(jié)果。特別地茅糜,當(dāng)一個依賴可以通過不同的路徑訪問時七芭,對該依賴聲明的exclusions將不會生效。例如蔑赘,如果一個starter POM聲明以下內(nèi)容:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.5.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
</dependencies>
commons-logging jar不會被Gradle排除狸驳,因為通過沒有exclusion元素的spring-context可以傳遞性的拉取到它(spring-context → spring-core → commons-logging)。
為了確保正確的排除被實際應(yīng)用缩赛,Spring Boot Gradle插件將自動添加排除規(guī)則锌历。所有排除被定義在spring-boot-dependencies POM,并且針對"starter" POMs的隱式規(guī)則也會被添加峦筒。
如果不想自動應(yīng)用排除規(guī)則究西,你可以使用以下配置:
springBoot {
applyExcludeRules=false
}
8.2.4 打包可執(zhí)行jar和war文件
一旦spring-boot插件被應(yīng)用到你的項目,它將使用bootRepackage任務(wù)自動嘗試重寫存檔以使它們能夠執(zhí)行物喷。為了構(gòu)建一個jar或war卤材,你需要按通常的方式配置項目遮斥。
你想啟動的main類既可以通過一個配置選項指定,也可以通過向manifest添加一個Main-Class屬性扇丛。如果你沒有指定main類术吗,該插件會搜索帶有public static void main(String[] args)方法的類。
為了構(gòu)建和運(yùn)行一個項目artifact帆精,你可以輸入以下內(nèi)容:
$ gradle build
$ java -jar build/libs/mymodule-0.0.1-SNAPSHOT.jar
為了構(gòu)建一個即能執(zhí)行也可以部署到外部容器的war包较屿,你需要將內(nèi)嵌容器依賴標(biāo)記為"providedRuntime",比如:
...
apply plugin: 'war'
war {
baseName = 'myapp'
version = '0.5.0'
}
repositories {
jcenter()
maven { url "http://repo.spring.io/libs-snapshot" }
}
configurations {
providedRuntime
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
...
}
注:具體參考“Section 74.1, “Create a deployable war file””卓练。
8.2.5 就地(in-place)運(yùn)行項目
為了在不先構(gòu)建jar的情況下運(yùn)行項目隘蝎,你可以使用"bootRun"任務(wù):
$ gradle bootRun
默認(rèn)情況下,以這種方式運(yùn)行項目可以讓你的靜態(tài)classpath資源(比如襟企,默認(rèn)位于src/main/resources下)在應(yīng)用運(yùn)行期間被重新加載嘱么。使靜態(tài)資源可以重新加載意味著bootRun任務(wù)不會使用processResources任務(wù)的輸出,比如顽悼,當(dāng)調(diào)用bootRun時曼振,你的應(yīng)用將以資源未處理的形式來使用它們。
你可以禁止直接使用靜態(tài)classpath資源蔚龙。這意味著資源不再是可重新加載的冰评,但processResources任務(wù)的輸出將會被使用。想要這樣做木羹,只需將bootRun任務(wù)的addResources設(shè)為false:
bootRun {
addResources = false
}
8.2.6 Spring Boot插件配置
Gradle插件自動擴(kuò)展你的構(gòu)建腳本DSL集索,它為腳本添加一個springBoot元素以此作為Boot插件的全局配置。你可以像配置其他Gradle擴(kuò)展那樣為springBoot設(shè)置相應(yīng)的屬性(下面有配置選項列表)汇跨。
springBoot {
backupSource = false
}
8.2.7 Repackage配置
該插件添加了一個bootRepackage任務(wù)务荆,你可以直接配置它,比如:
bootRepackage {
mainClass = 'demo.Application'
}
下面是可用的配置選項:
名稱 | 描述 |
---|---|
enabled | 布爾值穷遂,用于控制repackager的開關(guān)(如果你只想要Boot的其他特性而不是這個函匕,那它就派上用場了) |
mainClass | 要運(yùn)行的main類。如果沒有指定蚪黑,則使用project屬性mainClassName盅惜。如果沒有定義mainClassName id,則搜索存檔以尋找一個合適的類忌穿。"合適"意味著一個唯一的抒寂,具有良好格式的main()方法的類(如果找到多個則構(gòu)建會失敗)掠剑。你也可以通過"run"任務(wù)(main屬性)指定main類的名稱屈芜,和/或?qū)?startScripts"(mainClassName屬性)作為"springBoot"配置的替代。 |
classifier | 添加到存檔的一個文件名字段(在擴(kuò)展之前),這樣最初保存的存檔仍舊存放在最初的位置井佑。在存檔被重新打包(repackage)的情況下属铁,該屬性默認(rèn)為null。默認(rèn)值適用于多數(shù)情況躬翁,但如果你想在另一個項目中使用原jar作為依賴焦蘑,最好使用一個擴(kuò)展來定義該可執(zhí)行jar |
withJarTask | Jar任務(wù)的名稱或值,用于定位要被repackage的存檔 |
customConfiguration | 自定義配置的名稱盒发,用于填充內(nèi)嵌的lib目錄(不指定該屬性例嘱,你將獲取所有編譯和運(yùn)行時依賴) |
8.2.8 使用Gradle自定義配置進(jìn)行Repackage
有時候不打包解析自compile,runtime和provided作用域的默認(rèn)依賴可能更合適些宁舰。如果創(chuàng)建的可執(zhí)行jar被原樣運(yùn)行拼卵,你需要將所有的依賴內(nèi)嵌進(jìn)該jar中;然而明吩,如果目的是explode一個jar文件间学,并手動運(yùn)行main類殷费,你可能在CLASSPATH下已經(jīng)有一些可用的庫了印荔。在這種情況下,你可以使用不同的依賴集重新打包(repackage)你的jar详羡。
使用自定義的配置將自動禁用來自compile仍律,runtime和provided作用域的依賴解析。自定義配置即可以定義為全局的(處于springBoot部分內(nèi))实柠,也可以定義為任務(wù)級的水泉。
task clientJar(type: Jar) {
appendix = 'client'
from sourceSets.main.output
exclude('**/*Something*')
}
task clientBoot(type: BootRepackage, dependsOn: clientJar) {
withJarTask = clientJar
customConfiguration = "mycustomconfiguration"
}
在以上示例中,我們創(chuàng)建了一個新的clientJar Jar任務(wù)從你編譯后的源中打包一個自定義文件集窒盐。然后我們創(chuàng)建一個新的clientBoot BootRepackage任務(wù)草则,并讓它使用clientJar任務(wù)和mycustomconfiguration。
configurations {
mycustomconfiguration.exclude group: 'log4j'
}
dependencies {
mycustomconfiguration configurations.runtime
}
在BootRepackage中引用的配置是一個正常的Gradle配置蟹漓。在上面的示例中炕横,我們創(chuàng)建了一個新的名叫mycustomconfiguration的配置,指示它來自一個runtime葡粒,并排除對log4j的依賴份殿。如果clientBoot任務(wù)被執(zhí)行,重新打包的jar將含有所有來自runtime作用域的依賴嗽交,除了log4j jars卿嘲。
8.2.8.1 配置選項
可用的配置選項如下:
名稱 | 描述 |
---|---|
mainClass | 可執(zhí)行jar運(yùn)行的main類 |
providedConfiguration | provided配置的名稱(默認(rèn)為providedRuntime) |
backupSource | 在重新打包之前,原先的存檔是否備份(默認(rèn)為true) |
customConfiguration | 自定義配置的名稱 |
layout | 存檔類型夫壁,對應(yīng)于內(nèi)部依賴是如何制定的(默認(rèn)基于存檔類型進(jìn)行推測) |
requiresUnpack | 一個依賴列表(格式為"groupId:artifactId"拾枣,為了運(yùn)行,它們需要從fat jars中解壓出來盒让。)所有節(jié)點被打包進(jìn)胖jar放前,但運(yùn)行的時候它們將被自動解壓 |
8.2.9 理解Gradle插件是如何工作的
當(dāng)spring-boot被應(yīng)用到你的Gradle項目忿磅,一個默認(rèn)的名叫bootRepackage的任務(wù)被自動創(chuàng)建。bootRepackage任務(wù)依賴于Gradle assemble任務(wù)凭语,當(dāng)執(zhí)行時葱她,它會嘗試找到所有限定符為空的jar artifacts(也就是說,tests和sources jars被自動跳過)似扔。
由于bootRepackage查找'所有'創(chuàng)建jar artifacts的事實吨些,Gradle任務(wù)執(zhí)行的順序就非常重要了。多數(shù)項目只創(chuàng)建一個單一的jar文件炒辉,所以通常這不是一個問題豪墅。然而,如果你正打算創(chuàng)建一個更復(fù)雜的黔寇,使用自定義jar和BootRepackage任務(wù)的項目setup偶器,有幾個方面需要考慮沥潭。
如果'僅僅'從項目創(chuàng)建自定義jar文件腥泥,你可以簡單地禁用默認(rèn)的jar和bootRepackage任務(wù):
jar.enabled = false
bootRepackage.enabled = false
另一個選項是指示默認(rèn)的bootRepackage任務(wù)只能使用一個默認(rèn)的jar任務(wù):
bootRepackage.withJarTask = jar
如果你有一個默認(rèn)的項目setup岸夯,在該項目中眶诈,主(main)jar文件被創(chuàng)建和重新打包财岔。并且敏弃,你仍舊想創(chuàng)建額外的自定義jars循狰,你可以將自定義的repackage任務(wù)結(jié)合起來已艰,然后使用dependsOn榛做,這樣bootJars任務(wù)就會在默認(rèn)的bootRepackage任務(wù)執(zhí)行以后運(yùn)行:
task bootJars
bootJars.dependsOn = [clientBoot1,clientBoot2,clientBoot3]
build.dependsOn(bootJars)
上面所有方面經(jīng)常用于避免一個已經(jīng)創(chuàng)建的boot jar又被重新打包的情況唁盏。重新打包一個存在的boot jar不是什么大問題,但你可能會發(fā)現(xiàn)它包含不必要的依賴检眯。
8.3 對其他構(gòu)建系統(tǒng)的支持
如果想使用除了Maven和Gradle之外的構(gòu)建工具厘擂,你可能需要開發(fā)自己的插件∶倘常可執(zhí)行jars需要遵循一個特定格式刽严,并且一些實體需要以不壓縮的方式寫入(詳情查看附錄中的可執(zhí)行jar格式章節(jié))。
Spring Boot Maven和Gradle插件都利用spring-boot-loader-tools來實際地產(chǎn)生jars获茬。如果需要港庄,你也可以自由地直接使用該庫。
8.3.1 重新打包存檔
使用org.springframework.boot.loader.tools.Repackager可以將一個存在的存檔重新打包恕曲,這樣它就變成一個自包含的可執(zhí)行存檔鹏氧。Repackager類需要提供單一的構(gòu)造器參數(shù),它引用一個存在的jar或war包佩谣。使用兩個可用的repackage()方法中的一個來替換原始的文件或?qū)懭胍粋€新的目標(biāo)把还。在repackager運(yùn)行前還可以設(shè)置各種配置。
8.3.2 內(nèi)嵌的庫
當(dāng)重新打包一個存檔時,你可以使用org.springframework.boot.loader.tools.Libraries接口來包含對依賴文件的引用吊履。在這里我們不提供任何該Libraries接口的具體實現(xiàn)安皱,因為它們通常跟具體的構(gòu)建系統(tǒng)相關(guān)。
如果你的存檔已經(jīng)包含libraries艇炎,你可以使用Libraries.NONE酌伊。
8.3.3 查找main類
如果你沒有使用Repackager.setMainClass()指定一個main類,該repackager將使用ASM去讀取class文件缀踪,然后嘗試查找一個合適的居砖,具有public static void main(String[] args)方法的類。如果發(fā)現(xiàn)多個候選者驴娃,將會拋出異常奏候。
8.3.4 repackage實現(xiàn)示例
這里是一個傳統(tǒng)的repackage示例:
Repackager repackager = new Repackager(sourceJarFile);
repackager.setBackupSource(false);
repackager.repackage(new Libraries() {
@Override
public void doWithLibraries(LibraryCallback callback) throws IOException {
// Build system specific implementation, callback for each dependency
// callback.library(new Library(nestedFile, LibraryScope.COMPILE));
}
});
How-to指南
本章節(jié)將回答一些常見的"我該怎么做"類型的問題,這些問題在我們使用Spring Boot時經(jīng)常遇到唇敞。這絕不是一個詳盡的列表蔗草,但它覆蓋了很多方面。
如果遇到一個特殊的我們沒有覆蓋的問題疆柔,你可能想去查看stackoverflow.com咒精,看是否有人已經(jīng)給出了答案;這也是一個很好的提新問題的地方(請使用spring-boot標(biāo)簽)。
我們也樂意擴(kuò)展本章節(jié);如果想添加一個'how-to'婆硬,你可以給我們發(fā)一個pull請求狠轻。
9.1 Spring Boot應(yīng)用
9.1.1 解決自動配置問題
Spring Boot自動配置總是嘗試盡最大努力去做正確的事奸例,但有時候會失敗并且很難說出失敗原因彬犯。
在每個Spring Boot ApplicationContext中都存在一個相當(dāng)有用的ConditionEvaluationReport。如果開啟DEBUG日志輸出查吊,你將會看到它谐区。如果你使用spring-boot-actuator,則會有一個autoconfig的端點逻卖,它將以JSON形式渲染該報告宋列。可以使用它調(diào)試應(yīng)用程序评也,并能查看Spring Boot運(yùn)行時都添加了哪些特性(及哪些沒添加)炼杖。
通過查看源碼和javadoc可以獲取更多問題的答案。以下是一些經(jīng)驗:
- 查找名為* AutoConfiguration的類并閱讀源碼盗迟,特別是@Conditional*注解坤邪,這可以幫你找出它們啟用哪些特性及何時啟用。 將--debug添加到命令行或添加系統(tǒng)屬性-Ddebug可以在控制臺查看日志罚缕,該日志會記錄你的應(yīng)用中所有自動配置的決策艇纺。在一個運(yùn)行的Actuator app中,通過查看autoconfig端點(/autoconfig或等效的JMX)可以獲取相同信息。
- 查找是@ConfigurationProperties的類(比如ServerProperties)并看下有哪些可用的外部配置選項黔衡。@ConfigurationProperties類有一個用于充當(dāng)外部配置前綴的name屬性蚓聘,因此ServerProperties的值為prefix="server",它的配置屬性有server.port盟劫,server.address等夜牡。在運(yùn)行的Actuator應(yīng)用中可以查看configprops端點。
- 查看使用RelaxedEnvironment明確地將配置從Environment暴露出去侣签。它經(jīng)常會使用一個前綴氯材。
- 查看@Value注解,它直接綁定到Environment硝岗。相比RelaxedEnvironment氢哮,這種方式稍微缺乏靈活性,但它也允許松散的綁定型檀,特別是OS環(huán)境變量(所以CAPITALS_AND_UNDERSCORES是period.separated的同義詞)冗尤。
- 查看@ConditionalOnExpression注解,它根據(jù)SpEL表達(dá)式的結(jié)果來開啟或關(guān)閉特性胀溺,通常使用解析自Environment的占位符進(jìn)行計算裂七。
9.1.2 啟動前自定義Environment或ApplicationContext
每個SpringApplication都有ApplicationListeners和ApplicationContextInitializers,用于自定義上下文(context)或環(huán)境(environment)仓坞。Spring Boot從META-INF/spring.factories下加載很多這樣的內(nèi)部使用的自定義背零。有很多方法可以注冊其他的自定義:
- 以編程方式為每個應(yīng)用注冊自定義,通過在SpringApplication運(yùn)行前調(diào)用它的addListeners和addInitializers方法來實現(xiàn)无埃。
- 以聲明方式為每個應(yīng)用注冊自定義徙瓶,通過設(shè)置context.initializer.classes或context.listener.classes來實現(xiàn)。
- 以聲明方式為所有應(yīng)用注冊自定義嫉称,通過添加一個META-INF/spring.factories并打包成一個jar文件(該應(yīng)用將它作為一個庫)來實現(xiàn)侦镇。
SpringApplication會給監(jiān)聽器(即使是在上下文被創(chuàng)建之前就存在的)發(fā)送一些特定的ApplicationEvents,然后也會注冊監(jiān)聽ApplicationContext發(fā)布的事件的監(jiān)聽器织阅。查看Spring Boot特性章節(jié)中的Section 22.4, “Application events and listeners”
可以獲取一個完整列表壳繁。
9.1.4 創(chuàng)建一個非web(non-web)應(yīng)用
不是所有的Spring應(yīng)用都必須是web應(yīng)用(或web服務(wù))。如果你想在main方法中執(zhí)行一些代碼荔棉,但需要啟動一個Spring應(yīng)用去設(shè)置需要的底層設(shè)施闹炉,那使用Spring Boot的SpringApplication特性可以很容易實現(xiàn)。SpringApplication會根據(jù)它是否需要一個web應(yīng)用來改變它的ApplicationContext類润樱。首先你需要做的是去掉servlet API依賴渣触,如果不能這樣做(比如,基于相同的代碼運(yùn)行兩個應(yīng)用)祥国,那你可以明確地調(diào)用SpringApplication.setWebEnvironment(false)或設(shè)置applicationContextClass屬性(通過Java API或使用外部配置)昵观。你想運(yùn)行的晾腔,作為業(yè)務(wù)邏輯的應(yīng)用代碼可以實現(xiàn)為一個CommandLineRunner,并將上下文降級為一個@Bean定義啊犬。
9.2 屬性&配置
9.2.1 外部化SpringApplication配置
SpringApplication已經(jīng)被屬性化(主要是setters)灼擂,所以你可以在創(chuàng)建應(yīng)用時使用它的Java API修改它的行為【踔粒或者你可以使用properties文件中的spring.main.*來外部化(在應(yīng)用代碼外配置)這些配置剔应。比如,在application.properties中可能會有以下內(nèi)容:
spring.main.web_environment=false
spring.main.show_banner=false
然后Spring Boot在啟動時將不會顯示banner语御,并且該應(yīng)用也不是一個web應(yīng)用峻贮。
9.2.2 改變應(yīng)用程序外部配置文件的位置
默認(rèn)情況下,來自不同源的屬性以一個定義好的順序添加到Spring的Environment中(查看'Sprin Boot特性'章節(jié)的Chapter 23, Externalized Configuration
獲取精確的順序)应闯。
為應(yīng)用程序源添加@PropertySource注解是一種很好的添加和修改源順序的方法纤控。傳遞給SpringApplication靜態(tài)便利設(shè)施(convenience)方法的類和使用setSources()添加的類都會被檢查,以查看它們是否有@PropertySources碉纺,如果有船万,這些屬性會被盡可能早的添加到Environment里,以確保ApplicationContext生命周期的所有階段都能使用骨田。以這種方式添加的屬性優(yōu)先于任何使用默認(rèn)位置添加的屬性耿导,但低于系統(tǒng)屬性,環(huán)境變量或命令行參數(shù)态贤。
你也可以提供系統(tǒng)屬性(或環(huán)境變量)來改變該行為:
- spring.config.name(SPRING_CONFIG_NAME)是根文件名舱呻,默認(rèn)為application。
- spring.config.location(SPRING_CONFIG_LOCATION)是要加載的文件(例如悠汽,一個classpath資源或一個URL)箱吕。Spring Boot為該文檔設(shè)置一個單獨的Environment屬性,它可以被系統(tǒng)屬性介粘,環(huán)境變量或命令行參數(shù)覆蓋殖氏。
不管你在environment設(shè)置什么晚树,Spring Boot都將加載上面討論過的application.properties姻采。如果使用YAML,那具有'.yml'擴(kuò)展的文件默認(rèn)也會被添加到該列表爵憎。
詳情參考ConfigFileApplicationListener
9.2.3 使用'short'命令行參數(shù)
有些人喜歡使用(例如)--port=9000代替--server.port=9000來設(shè)置命令行配置屬性慨亲。你可以通過在application.properties中使用占位符來啟用該功能,比如:
server.port=${port:8080}
注:如果你繼承自spring-boot-starter-parent POM宝鼓,為了防止和Spring-style的占位符產(chǎn)生沖突刑棵,maven-resources-plugins默認(rèn)的過濾令牌(filter token)已經(jīng)從${*}變?yōu)锧(即@maven.token@代替了${maven.token})。如果已經(jīng)直接啟用maven對application.properties的過濾愚铡,你可能也想使用其他的分隔符替換默認(rèn)的過濾令牌蛉签。
注:在這種特殊的情況下胡陪,端口綁定能夠在一個PaaS環(huán)境下工作,比如Heroku和Cloud Foundry碍舍,因為在這兩個平臺中PORT環(huán)境變量是自動設(shè)置的柠座,并且Spring能夠綁定Environment屬性的大寫同義詞。
9.2.4 使用YAML配置外部屬性
YAML是JSON的一個超集片橡,可以非常方便的將外部配置以層次結(jié)構(gòu)形式存儲起來妈经。比如:
spring:
application:
name: cruncher
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/test
server:
port: 9000
創(chuàng)建一個application.yml文件掩蛤,將它放到classpath的根目錄下慢洋,并添加snakeyaml依賴(Maven坐標(biāo)為org.yaml:snakeyaml,如果你使用spring-boot-starter那就已經(jīng)被包含了)器瘪。一個YAML文件會被解析為一個Java Map<String,Object>(和一個JSON對象類似)经瓷,Spring Boot會平伸該map爆哑,這樣它就只有1級深度,并且有period-separated的keys舆吮,跟人們在Java中經(jīng)常使用的Properties文件非常類似泪漂。 上面的YAML示例對應(yīng)于下面的application.properties文件:
spring.application.name=cruncher
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000
查看'Spring Boot特性'章節(jié)的Section 23.6, “Using YAML instead of Properties”可以獲取更多關(guān)于YAML的信息。
9.2.5 設(shè)置生效的Spring profiles
Spring Environment有一個API可以設(shè)置生效的profiles歪泳,但通常你會設(shè)置一個系統(tǒng)profile(spring.profiles.active)或一個OS環(huán)境變量(SPRING_PROFILES_ACTIVE)萝勤。比如,使用一個-D參數(shù)啟動應(yīng)用程序(記著把它放到main類或jar文件之前):
$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar
在Spring Boot中呐伞,你也可以在application.properties里設(shè)置生效的profile敌卓,例如:
spring.profiles.active=production
通過這種方式設(shè)置的值會被系統(tǒng)屬性或環(huán)境變量替換,但不會被SpringApplicationBuilder.profiles()方法替換伶氢。因此趟径,后面的Java API可用來在不改變默認(rèn)設(shè)置的情況下增加profiles。
想要獲取更多信息可查看'Spring Boot特性'章節(jié)的Chapter 24, Profiles
癣防。
9.2.6 根據(jù)環(huán)境改變配置
一個YAML文件實際上是一系列以---線分割的文檔蜗巧,每個文檔都被單獨解析為一個平坦的(flattened)map。
如果一個YAML文檔包含一個spring.profiles關(guān)鍵字蕾盯,那profiles的值(以逗號分割的profiles列表)將被傳入Spring的Environment.acceptsProfiles()方法幕屹,并且如果這些profiles的任何一個被激活,對應(yīng)的文檔被包含到最終的合并中(否則不會)级遭。
示例:
server:
port: 9000
---
spring:
profiles: development
server:
port: 9001
---
spring:
profiles: production
server:
port: 0
在這個示例中望拖,默認(rèn)的端口是9000,但如果Spring profile 'development'生效則該端口是9001挫鸽,如果'production'生效則它是0说敏。
YAML文檔以它們遇到的順序合并(所以后面的值會覆蓋前面的值)。
想要使用profiles文件完成同樣的操作丢郊,你可以使用application-${profile}.properties指定特殊的盔沫,profile相關(guān)的值医咨。
9.2.7 發(fā)現(xiàn)外部屬性的內(nèi)置選項
Spring Boot在運(yùn)行時將來自application.properties(或.yml)的外部屬性綁定進(jìn)一個應(yīng)用中。在一個地方不可能存在詳盡的所有支持屬性的列表(技術(shù)上也是不可能的)架诞,因為你的classpath下的其他jar文件也能夠貢獻(xiàn)腋逆。
每個運(yùn)行中且有Actuator特性的應(yīng)用都會有一個configprops端點,它能夠展示所有邊界和可通過@ConfigurationProperties綁定的屬性侈贷。
附錄中包含一個application.properties示例惩歉,它列舉了Spring Boot支持的大多數(shù)常用屬性。獲取權(quán)威列表可搜索@ConfigurationProperties和@Value的源碼俏蛮,還有不經(jīng)常使用的RelaxedEnvironment撑蚌。
9.3 內(nèi)嵌的servlet容器
9.3.1 為應(yīng)用添加Servlet,F(xiàn)ilter或ServletContextListener
Servlet規(guī)范支持的Servlet搏屑,F(xiàn)ilter争涌,ServletContextListener和其他監(jiān)聽器可以作為@Bean定義添加到你的應(yīng)用中。需要格外小心的是辣恋,它們不會引起太多的其他beans的熱初始化亮垫,因為在應(yīng)用生命周期的早期它們已經(jīng)被安裝到容器里了(比如,讓它們依賴你的DataSource或JPA配置就不是一個好主意)伟骨。你可以通過延遲初始化它們到第一次使用而不是初始化時來突破該限制饮潦。
在Filters和Servlets的情況下,你也可以通過添加一個FilterRegistrationBean或ServletRegistrationBean代替或以及底層的組件來添加映射(mappings)和初始化參數(shù)携狭。
9.3.2 改變HTTP端口
在一個單獨的應(yīng)用中继蜡,主HTTP端口默認(rèn)為8080,但可以使用server.port設(shè)置(比如逛腿,在application.properties中或作為一個系統(tǒng)屬性)稀并。由于Environment值的寬松綁定,你也可以使用SERVER_PORT(比如单默,作為一個OS環(huán)境變)碘举。
為了完全關(guān)閉HTTP端點,但仍創(chuàng)建一個WebApplicationContext搁廓,你可以設(shè)置server.port=-1(測試時可能有用)引颈。
想獲取更多詳情可查看'Spring Boot特性'章節(jié)的Section 26.3.3, “Customizing embedded servlet containers”
,或ServerProperties
源碼枚抵。
9.3.3 使用隨機(jī)未分配的HTTP端口
想掃描一個未使用的端口(為了防止沖突使用OS本地端口)可以使用server.port=0线欲。
9.3.4 發(fā)現(xiàn)運(yùn)行時的HTTP端口
你可以通過日志輸出或它的EmbeddedServletContainer的EmbeddedWebApplicationContext獲取服務(wù)器正在運(yùn)行的端口。獲取和確認(rèn)服務(wù)器已經(jīng)初始化的最好方式是添加一個ApplicationListener<EmbeddedServletContainerInitializedEvent>
類型的@Bean汽摹,然后當(dāng)事件發(fā)布時將容器pull出來。
使用@WebIntegrationTests的一個有用實踐是設(shè)置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;
// ...
}
9.3.5 配置SSL
SSL能夠以聲明方式進(jìn)行配置趴泌,一般通過在application.properties或application.yml設(shè)置各種各樣的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存儲(如果你正在使用一個可信存儲)能夠直接在文件系統(tǒng)上訪問嗜憔,即它不能從一個jar文件內(nèi)讀取。Jetty和Undertow沒有該限制氏仗。
使用類似于以上示例的配置意味著該應(yīng)用將不在支持端口為8080的普通HTTP連接吉捶。Spring Boot不支持通過application.properties同時配置HTTP連接器和HTTPS連接器。如果你兩個都想要皆尔,那就需要以編程的方式配置它們中的一個呐舔。推薦使用application.properties配置HTTPS,因為HTTP連接器是兩個中最容易以編程方式進(jìn)行配置的慷蠕。獲取示例可查看spring-boot-sample-tomcat-multi-connectors示例項目珊拼。
9.3.6 配置Tomcat
通常你可以遵循Section 63.7, “Discover built-in options for external properties”
關(guān)于@ConfigurationProperties(這里主要的是ServerProperties)的建議,但也看下EmbeddedServletContainerCustomizer和各種你可以添加的Tomcat-specific的*Customizers流炕。
Tomcat APIs相當(dāng)豐富澎现,一旦獲取到TomcatEmbeddedServletContainerFactory,你就能夠以多種方式修改它每辟〗1瑁或核心選擇是添加你自己的TomcatEmbeddedServletContainerFactory。
9.3.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);
}
}
9.3.8 在前端代理服務(wù)器后使用Tomcat
Spring Boot將自動配置Tomcat的RemoteIpValve,如果你啟用它的話峻堰。這允許你透明地使用標(biāo)準(zhǔn)的x-forwarded-for和x-forwarded-proto頭讹开,很多前端代理服務(wù)器都會添加這些頭信息(headers)。通過將這些屬性中的一個或全部設(shè)置為非空的內(nèi)容來開啟該功能(它們是大多數(shù)代理約定的值捐名,如果你只設(shè)置其中的一個旦万,則另一個也會被自動設(shè)置)。
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
該值也可以配置為一個默認(rèn)的,能夠匹配信任的內(nèi)部代理的正則表達(dá)式贺归。默認(rèn)情況下淆两,受信任的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虽另,你就可以完全控制它的設(shè)置了暂刘。
9.3.9 使用Jetty替代Tomcat
Spring Boot starters(特別是spring-boot-starter-web)默認(rèn)都是使用Tomcat作為內(nèi)嵌容器的。你需要排除那些Tomcat的依賴并包含Jetty的依賴捂刺。為了讓這種處理盡可能簡單谣拣,Spring Boot將Tomcat和Jetty的依賴?yán)壴谝黄穑缓筇峁﹩为毜膕tarters族展。
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")
// ...
}
9.3.10 配置jetty
通常你可以遵循Section 63.7, “Discover built-in options for external properties”關(guān)于@ConfigurationProperties(此處主要是ServerProperties)的建議森缠,但也要看下EmbeddedServletContainerCustomizer。Jetty API相當(dāng)豐富苛谷,一旦獲取到JettyEmbeddedServletContainerFactory辅鲸,你就可以使用很多方式修改它「沟睿或更徹底地就是添加你自己的JettyEmbeddedServletContainerFactory独悴。
9.3.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")
// ...
}
9.3.12 配置Undertow
通常你可以遵循Section 63.7, “Discover built-in options for external properties”關(guān)于@ConfigurationProperties(此處主要是ServerProperties和ServerProperties.Undertow),但也要看下EmbeddedServletContainerCustomizer自沧。一旦獲取到UndertowEmbeddedServletContainerFactory坟奥,你就可以使用一個UndertowBuilderCustomizer修改Undertow的配置以滿足你的需求∧聪幔或更徹底地就是添加你自己的UndertowEmbeddedServletContainerFactory爱谁。
9.3.13 啟用Undertow的多監(jiān)聽器(Multiple Listeners)
往UndertowEmbeddedServletContainerFactory
添加一個UndertowBuilderCustomizer
,然后添加一個監(jiān)聽者到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;
}
9.3.14 使用Tomcat7
Tomcat7可用于Spring Boot孝偎,但默認(rèn)使用的是Tomcat8访敌。如果不能使用Tomcat8(例如,你使用的是Java1.6)衣盾,你需要改變classpath去引用Tomcat7寺旺。
9.3.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>
9.3.14.2 通過Gradle使用Tomcat7
你可以通過設(shè)置tomcat.version屬性改變Tomcat的版本:
ext['tomcat.version'] = '7.0.59'
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
}
9.3.15 使用Jetty8
Jetty8可用于Spring Boot,但默認(rèn)使用的是Jetty9果复。如果不能使用Jetty9(例如陈莽,因為你使用的是Java1.6),你只需改變classpath去引用Jetty8。你也需要排除Jetty的WebSocket相關(guān)的依賴传透。
9.3.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>
9.3.15.2 通過Gradle使用Jetty8
你可以設(shè)置jetty.version屬性并排除相關(guān)的WebSocket依賴兵琳,比如對于一個簡單的webapp或service:
ext['jetty.version'] = '8.1.15.v20140411'
dependencies {
compile ('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
compile ('org.springframework.boot:spring-boot-starter-jetty') {
exclude group: 'org.eclipse.jetty.websocket'
}
}
9.3.16 使用@ServerEndpoint創(chuàng)建WebSocket端點
如果想在一個使用內(nèi)嵌容器的Spring Boot應(yīng)用中使用@ServerEndpoint,你需要聲明一個單獨的ServerEndpointExporter @Bean:
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
該bean將用底層的WebSocket容器注冊任何的被@ServerEndpoint注解的beans骇径。當(dāng)部署到一個單獨的servlet容器時躯肌,該角色將被一個servlet容器初始化方法履行,ServerEndpointExporter bean也就不是必需的了破衔。
9.3.17 啟用HTTP響應(yīng)壓縮
Spring Boot提供兩種啟用HTTP壓縮的機(jī)制;一種是Tomcat特有的清女,另一種是使用一個filter,可以配合Jetty晰筛,Tomcat和Undertow嫡丙。
9.3.17.1 啟用Tomcat的HTTP響應(yīng)壓縮
Tomcat對HTTP響應(yīng)壓縮提供內(nèi)建支持。默認(rèn)是禁用的读第,但可以通過application.properties輕松的啟用:
server.tomcat.compression: on
當(dāng)設(shè)置為on時曙博,Tomcat將壓縮響應(yīng)的長度至少為2048字節(jié)。你可以配置一個整型值來設(shè)置該限制而不只是on怜瞒,比如:
server.tomcat.compression: 4096
默認(rèn)情況下父泳,Tomcat只壓縮某些MIME類型的響應(yīng)(text/html,text/xml和text/plain)吴汪。你可以使用server.tomcat.compressableMimeTypes屬性進(jìn)行自定義惠窄,比如:
server.tomcat.compressableMimeTypes=application/json,application/xml
9.3.17.2 使用GzipFilter開啟HTTP響應(yīng)壓縮
如果你正在使用Jetty或Undertow,或想要更精確的控制HTTP響應(yīng)壓縮漾橙,Spring Boot為Jetty的GzipFilter提供自動配置杆融。雖然該過濾器是Jetty的一部分,但它也兼容Tomcat和Undertow近刘。想要啟用該過濾器擒贸,只需簡單的為你的應(yīng)用添加org.eclipse.jetty:jetty-servlets依賴。
GzipFilter可以使用spring.http.gzip.*屬性進(jìn)行配置觉渴。具體參考GzipFilterProperties介劫。
9.4 Spring MVC
9.4.1 編寫一個JSON REST服務(wù)
在Spring Boot應(yīng)用中,任何Spring @RestController默認(rèn)應(yīng)該渲染為JSON響應(yīng)案淋,只要classpath下存在Jackson2座韵。例如:
@RestController
public class MyController {
@RequestMapping("/thing")
public MyThing thing() {
return new MyThing();
}
}
只要MyThing能夠通過Jackson2序列化(比如,一個標(biāo)準(zhǔn)的POJO或Groovy對象),localhost:8080/thing默認(rèn)響應(yīng)一個JSON表示誉碴。有時在一個瀏覽器中你可能看到XML響應(yīng)因為瀏覽器傾向于發(fā)送XML 響應(yīng)頭宦棺。
9.4.2 編寫一個XML REST服務(wù)
如果classpath下存在Jackson XML擴(kuò)展(jackson-dataformat-xml),它會被用來渲染XML響應(yīng)黔帕,示例和JSON的非常相似代咸。想要使用它,只需為你的項目添加以下的依賴:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
你可能也想添加對Woodstox的依賴成黄。它比JDK提供的默認(rèn)Stax實現(xiàn)快很多呐芥,并且支持良好的格式化輸出,提高了namespace處理能力:
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
</dependency>
如果Jackson的XML擴(kuò)展不可用奋岁,Spring Boot將使用JAXB(JDK默認(rèn)提供)思瘟,不過你需要為MyThing添加額外的注解@XmlRootElement:
@XmlRootElement
public class MyThing {
private String name;
// .. getters and setters
}
想要服務(wù)器渲染XML而不是JSON,你可能需要發(fā)送一個Accept: text/xml頭部(或使用瀏覽器)闻伶。
9.4.3 自定義Jackson ObjectMapper
在一個HTTP交互中滨攻,Spring MVC(客戶端和服務(wù)端)使用HttpMessageConverters協(xié)商內(nèi)容轉(zhuǎn)換。如果classpath下存在Jackson蓝翰,你就已經(jīng)獲取到Jackson2ObjectMapperBuilder提供的默認(rèn)轉(zhuǎn)換器光绕。
創(chuàng)建的ObjectMapper(或用于Jackson XML轉(zhuǎn)換的XmlMapper)實例默認(rèn)有以下自定義屬性:
- MapperFeature.DEFAULT_VIEW_INCLUSION禁用
- DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES禁用
Spring Boot也有一些簡化自定義該行為的特性。
你可以使用當(dāng)前的environment配置ObjectMapper和XmlMapper實例霎箍。Jackson提供一個擴(kuò)展套件奇钞,可以用來簡單的關(guān)閉或開啟一些特性,你可以用它們配置Jackson處理的不同方面漂坏。這些特性在Jackson中使用5個枚舉進(jìn)行描述的景埃,并被映射到environment的屬性上:
Jackson枚舉 | Environment屬性 | |
---|---|---|
com.fasterxml.jackson.databind.DeserializationFeature | `spring.jackson.deserialization.=true | false` |
com.fasterxml.jackson.core.JsonGenerator.Feature | `spring.jackson.generator.=true | false` |
com.fasterxml.jackson.databind.MapperFeature | `spring.jackson.mapper.=true | false` |
com.fasterxml.jackson.core.JsonParser.Feature | `spring.jackson.parser.=true | false` |
com.fasterxml.jackson.databind.SerializationFeature | `spring.jackson.serialization.=true | false` |
例如,設(shè)置spring.jackson.serialization.indent_output=true可以開啟漂亮打印顶别。注意谷徙,由于松綁定的使用,indent_output不必匹配對應(yīng)的枚舉常量INDENT_OUTPUT驯绎。
如果想徹底替換默認(rèn)的ObjectMapper完慧,你需要定義一個該類型的@Bean并將它標(biāo)記為@Primary。
定義一個Jackson2ObjectMapperBuilder類型的@Bean將允許你自定義默認(rèn)的ObjectMapper和XmlMapper(分別用于MappingJackson2HttpMessageConverter和MappingJackson2XmlHttpMessageConverter)剩失。
另一種自定義Jackson的方法是向你的上下文添加com.fasterxml.jackson.databind.Module類型的beans屈尼。它們會被注冊入每個ObjectMapper類型的bean,當(dāng)為你的應(yīng)用添加新特性時拴孤,這就提供了一種全局機(jī)制來貢獻(xiàn)自定義模塊脾歧。
最后,如果你提供任何MappingJackson2HttpMessageConverter類型的@Beans演熟,那它們將替換MVC配置中的默認(rèn)值鞭执。同時司顿,也提供一個HttpMessageConverters類型的bean,它有一些有用的方法可以獲取默認(rèn)的和用戶增強(qiáng)的message轉(zhuǎn)換器兄纺。
想要獲取更多細(xì)節(jié)可查看Section 65.4, “Customize the @ResponseBody rendering”和WebMvcAutoConfiguration源碼大溜。
9.4.4 自定義@ResponseBody渲染
Spring使用HttpMessageConverters渲染@ResponseBody(或來自@RestController的響應(yīng))。你可以通過在Spring Boot上下文中添加該類型的beans來貢獻(xiàn)其他的轉(zhuǎn)換器估脆。如果你添加的bean類型默認(rèn)已經(jīng)包含了(像用于JSON轉(zhuǎn)換的MappingJackson2HttpMessageConverter)钦奋,那它將替換默認(rèn)的。Spring Boot提供一個方便的HttpMessageConverters類型的bean旁蔼,它有一些有用的方法可以訪問默認(rèn)的和用戶增強(qiáng)的message轉(zhuǎn)換器(有用锨苏,比如你想要手動將它們注入到一個自定義的RestTemplate)疙教。
在通常的MVC用例中棺聊,任何你提供的WebMvcConfigurerAdapter beans通過覆蓋configureMessageConverters方法也能貢獻(xiàn)轉(zhuǎn)換器,但不同于通常的MVC贞谓,你可以只提供你需要的轉(zhuǎn)換器(因為Spring Boot使用相同的機(jī)制來貢獻(xiàn)它默認(rèn)的轉(zhuǎn)換器)限佩。最終,如果你通過提供自己的@EnableWebMvc注解覆蓋Spring Boot默認(rèn)的MVC配置裸弦,那你就可以完全控制祟同,并使用來自WebMvcConfigurationSupport的getMessageConverters手動做任何事。
具體參考WebMvcAutoConfiguration源碼理疙。
9.4.5 處理Multipart文件上傳
Spring Boot采用Servlet 3 javax.servlet.http.Part API來支持文件上傳晕城。默認(rèn)情況下,Spring Boot配置Spring MVC在單個請求中每個文件最大1Mb窖贤,最多10Mb的文件數(shù)據(jù)砖顷。你可以覆蓋那些值,也可以設(shè)置臨時文件存儲的位置(比如赃梧,存儲到/tmp文件夾下)及傳遞數(shù)據(jù)刷新到磁盤的閥值(通過使用MultipartProperties類暴露的屬性)滤蝠。如果你需要設(shè)置文件不受限制,例如授嘀,可以設(shè)置multipart.maxFileSize屬性值為-1物咳。
當(dāng)你想要接收部分(multipart)編碼文件數(shù)據(jù)作為Spring MVC控制器(controller)處理方法中被@RequestParam注解的MultipartFile類型的參數(shù)時,multipart支持就非常有用了蹄皱。
具體參考MultipartAutoConfiguration源碼览闰。
9.4.6 關(guān)閉Spring MVC DispatcherServlet
Spring Boot想要服務(wù)來自應(yīng)用程序root /下的所有內(nèi)容。如果你想將自己的servlet映射到該目錄下也是可以的巷折,但當(dāng)然你可能失去一些Boot MVC特性压鉴。為了添加你自己的servlet,并將它映射到root資源盔几,你只需聲明一個Servlet類型的@Bean晴弃,并給它特定的bean名稱dispatcherServlet(如果只想關(guān)閉但不替換它,你可以使用該名稱創(chuàng)建不同類型的bean)。
9.4.7 關(guān)閉默認(rèn)的MVC配置
完全控制MVC配置的最簡單方式是提供你自己的被@EnableWebMvc注解的@Configuration上鞠。這樣所有的MVC配置都逃不出你的掌心际邻。
9.4.8 自定義ViewResolvers
ViewResolver是Spring MVC的核心組件,它負(fù)責(zé)轉(zhuǎn)換@Controller中的視圖名稱到實際的View實現(xiàn)芍阎。注意ViewResolvers主要用在UI應(yīng)用中世曾,而不是REST風(fēng)格的服務(wù)(View不是用來渲染@ResponseBody的)。Spring有很多你可以選擇的ViewResolver實現(xiàn)谴咸,并且Spring自己對如何選擇相應(yīng)實現(xiàn)也沒發(fā)表意見轮听。另一方面,Spring Boot會根據(jù)classpath上的依賴和應(yīng)用上下文為你安裝一或兩個ViewResolver實現(xiàn)岭佳。DispatcherServlet使用所有在應(yīng)用上下文中找到的解析器(resolvers)血巍,并依次嘗試每一個直到它獲取到結(jié)果,所以如果你正在添加自己的解析器珊随,那就要小心順序和你的解析器添加的位置述寡。
WebMvcAutoConfiguration將會為你的上下文添加以下ViewResolvers:
- bean id為defaultViewResolver的InternalResourceViewResolver。這個會定位可以使用DefaultServlet渲染的物理資源(比如叶洞,靜態(tài)資源和JSP頁面)鲫凶。它在視圖(view name)上應(yīng)用了一個前綴和后綴(默認(rèn)都為空,但你可以通過spring.view.prefix和spring.view.suffix外部配置設(shè)置)衩辟,然后查找在servlet上下文中具有該路徑的物理資源螟炫。可以通過提供相同類型的bean覆蓋它艺晴。
- id為beanNameViewResolver的BeanNameViewResolver昼钻。這是視圖解析器鏈的一個非常有用的成員,它可以在View被解析時收集任何具有相同名稱的beans财饥。
- id為viewResolver的ContentNegotiatingViewResolver只會在實際View類型的beans出現(xiàn)時添加换吧。這是一個'主'解析器,它的職責(zé)會代理給其他解析器钥星,它會嘗試找到客戶端發(fā)送的一個匹配'Accept'的HTTP頭部沾瓦。這有一篇有用的,關(guān)于你需要更多了解的ContentNegotiatingViewResolver的博客谦炒,也要具體查看下源碼贯莺。通過定義一個名叫'viewResolver'的bean,你可以關(guān)閉自動配置的ContentNegotiatingViewResolver宁改。
- 如果使用Thymeleaf缕探,你將有一個id為thymeleafViewResolver的ThymeleafViewResolver。它會通過加前綴和后綴的視圖名來查找資源(外部配置為spring.thymeleaf.prefix和spring.thymeleaf.suffix还蹲,對應(yīng)的默認(rèn)為'classpath:/templates/'和'.html')爹耗。你可以通過提供相同名稱的bean來覆蓋它耙考。
- 如果使用FreeMarker,你將有一個id為freeMarkerViewResolver的FreeMarkerViewResolver潭兽。它會使用加前綴和后綴(外部配置為spring.freemarker.prefix和spring.freemarker.suffix倦始,對應(yīng)的默認(rèn)值為空和'.ftl')的視圖名從加載路徑(外部配置為spring.freemarker.templateLoaderPath,默認(rèn)為'classpath:/templates/')下查找資源山卦。你可以通過提供一個相同名稱的bean來覆蓋它鞋邑。
- 如果使用Groovy模板(實際上只要你把groovy-templates添加到classpath下)枷邪,你將有一個id為groovyTemplateViewResolver的Groovy TemplateViewResolver守伸。它會使用加前綴和后綴(外部屬性為spring.groovy.template.prefix和spring.groovy.template.suffix宵蕉,對應(yīng)的默認(rèn)值為'classpath:/templates/'和'.tpl')的視圖名從加載路徑下查找資源培漏。你可以通過提供一個相同名稱的bean來覆蓋它。
- 如果使用Velocity悴务,你將有一個id為velocityViewResolver的VelocityViewResolver渴析。它會使用加前綴和后綴(外部屬性為spring.velocity.prefix和spring.velocity.suffix入蛆,對應(yīng)的默認(rèn)值為空和'.vm')的視圖名從加載路徑(外部屬性為spring.velocity.resourceLoaderPath归敬,默認(rèn)為'classpath:/templates/')下查找資源酷含。你可以通過提供一個相同名稱的bean來覆蓋它。
具體參考: WebMvcAutoConfiguration汪茧,ThymeleafAutoConfiguration,FreeMarkerAutoConfiguration限番,GroovyTemplateAutoConfiguration舱污,VelocityAutoConfiguration。
9.5 日志
Spring Boot除了commons-logging API外沒有其他強(qiáng)制性的日志依賴弥虐,你有很多可選的日志實現(xiàn)扩灯。想要使用Logback,你需要包含它霜瘪,及一些對classpath下commons-logging的綁定珠插。最簡單的方式是通過依賴spring-boot-starter-logging的starter pom。對于一個web應(yīng)用程序颖对,你只需添加spring-boot-starter-web依賴捻撑,因為它依賴于logging starter。例如缤底,使用Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Spring Boot有一個LoggingSystem抽象顾患,用于嘗試通過classpath上下文配置日志系統(tǒng)。如果Logback可用个唧,則首選它江解。如果你唯一需要做的就是設(shè)置不同日志的級別,那可以通過在application.properties中使用logging.level前綴實現(xiàn)徙歼,比如:
logging.level.org.springframework.web: DEBUG
logging.level.org.hibernate: ERROR
你也可以使用logging.file
設(shè)置日志文件的位置(除控制臺之外犁河,默認(rèn)會輸出到控制臺)鳖枕。
想要對日志系統(tǒng)進(jìn)行更細(xì)粒度的配置,你需要使用正在說的LoggingSystem支持的原生配置格式桨螺。默認(rèn)情況下耕魄,Spring Boot從系統(tǒng)的默認(rèn)位置加載原生配置(比如對于Logback為classpath:logback.xml),但你可以使用logging.config
屬性設(shè)置配置文件的位置彭谁。
9.5.1 配置Logback
如果你將一個logback.xml放到classpath根目錄下吸奴,那它將會被從這加載。Spring Boot提供一個默認(rèn)的基本配置缠局,如果你只是設(shè)置日志級別则奥,那你可以包含它,比如:
<?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包中的默認(rèn)logback.xml狭园,你將會看到LoggingSystem為你創(chuàng)建的很多有用的系統(tǒng)屬性读处,比如:
- ${PID},當(dāng)前進(jìn)程id
- ${LOG_FILE}唱矛,如果在Boot外部配置中設(shè)置了logging.file
- ${LOG_PATH}罚舱,如果設(shè)置了logging.path(表示日志文件產(chǎn)生的目錄)
Spring Boot也提供使用自定義的Logback轉(zhuǎn)換器在控制臺上輸出一些漂亮的彩色ANSI日志信息(不是日志文件)。具體參考默認(rèn)的base.xml配置绎谦。
如果Groovy在classpath下管闷,你也可以使用logback.groovy配置Logback。
9.5.2 配置Log4j
Spring Boot也支持Log4j或Log4j 2作為日志配置窃肠,但只有在它們中的某個在classpath下存在的情況包个。如果你正在使用starter poms進(jìn)行依賴裝配,這意味著你需要排除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的示例吴叶,了解如何將它用于實戰(zhàn)阐虚。
9.5.2.1 使用YAML或JSON配置Log4j2
除了它的默認(rèn)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的配置文件
9.6 數(shù)據(jù)訪問
9.6.1 配置一個數(shù)據(jù)源
想要覆蓋默認(rèn)的設(shè)置只需要定義一個你自己的DataSource類型的@Bean悼瘾。Spring Boot提供一個工具構(gòu)建類DataSourceBuilder,可用來創(chuàng)建一個標(biāo)準(zhǔn)的DataSource(如果它處于classpath下)审胸,或者僅創(chuàng)建你自己的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特性'章節(jié)中的·Section 28.1, “Configure a DataSource”·和DataSourceAutoConfiguration類源碼砂沛。
9.6.2 配置兩個數(shù)據(jù)源
創(chuàng)建多個數(shù)據(jù)源和創(chuàng)建第一個工作都是一樣的烫扼。如果使用針對JDBC或JPA的默認(rèn)自動配置,你可能想要將其中一個設(shè)置為@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();
}
9.6.3 使用Spring Data倉庫
Spring Data可以為你的@Repository接口創(chuàng)建各種風(fēng)格的實現(xiàn)。Spring Boot會為你處理所有事情静浴,只要那些@Repositories接口跟你的@EnableAutoConfiguration類處于相同的包(或子包)堰氓。
對于很多應(yīng)用來說,你需要做的就是將正確的Spring Data依賴添加到classpath下(對于JPA有一個spring-boot-starter-data-jpa马绝,對于Mongodb有一個spring-boot-starter-data-mongodb)豆赏,創(chuàng)建一些repository接口來處理@Entity對象。具體參考JPA sample或Mongodb sample富稻。
Spring Boot會基于它找到的@EnableAutoConfiguration來嘗試猜測你的@Repository定義的位置。想要獲取更多控制白胀,可以使用@EnableJpaRepositories注解(來自Spring Data JPA)椭赋。
9.6.4 從Spring配置分離@Entity定義
Spring Boot會基于它找到的@EnableAutoConfiguration來嘗試猜測你的@Entity定義的位置。想要獲取更多控制或杠,你可以使用@EntityScan注解哪怔,比如:
@Configuration
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
public class Application {
//...
}
9.6.5 配置JPA屬性
Spring Data JPA已經(jīng)提供了一些獨立的配置選項(比如,針對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
(由于寬松的數(shù)據(jù)綁定策略挟鸠,連字符或下劃線作為屬性keys作用應(yīng)該是等效的)ddl-auto配置是個特殊情況叉信,它有不同的默認(rèn)設(shè)置,這取決于你是否使用一個內(nèi)嵌數(shù)據(jù)庫(create-drop)艘希。當(dāng)本地EntityManagerFactory被創(chuàng)建時硼身,所有spring.jpa.properties.*屬性都被作為正常的JPA屬性(去掉前綴)傳遞進(jìn)去了硅急。
具體參考HibernateJpaAutoConfiguration和JpaBaseConfiguration。
9.6.6 使用自定義的EntityManagerFactory
為了完全控制EntityManagerFactory的配置佳遂,你需要添加一個名為entityManagerFactory的@Bean营袜。Spring Boot自動配置會根據(jù)是否存在該類型的bean來關(guān)閉它的實體管理器(entity manager)。
9.6.7 使用兩個EntityManagers
即使默認(rèn)的EntityManagerFactory工作的很好丑罪,你也需要定義一個新的EntityManagerFactory荚板,因為一旦出現(xiàn)第二個該類型的bean,默認(rèn)的將會被關(guān)閉吩屹。為了輕松的實現(xiàn)該操作跪另,你可以使用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();
}
上面的配置靠自己基本可以運(yùn)行罚斗。想要完成作品你也需要為兩個EntityManagers配置TransactionManagers。其中的一個會被Spring Boot默認(rèn)的JpaTransactionManager獲取宅楞,如果你將它標(biāo)記為@Primary针姿。另一個需要顯式注入到一個新實例⊙嵫茫或你可以使用一個JTA事物管理器生成它兩個距淫。
9.6.8 使用普通的persistence.xml
Spring不要求使用XML配置JPA提供者(provider),并且Spring Boot假定你想要充分利用該特性婶希。如果你傾向于使用persistence.xml榕暇,那你需要定義你自己的id為'entityManagerFactory'的LocalEntityManagerFactoryBean類型的@Bean,并在那設(shè)置持久化單元的名稱喻杈。
默認(rèn)設(shè)置可查看JpaBaseConfiguration
9.6.9 使用Spring Data JPA和Mongo倉庫
Spring Data JPA和Spring Data Mongo都能自動為你創(chuàng)建Repository實現(xiàn)彤枢。如果它們同時出現(xiàn)在classpath下,你可能需要添加額外的配置來告訴Spring Boot你想要哪個(或兩個)為你創(chuàng)建倉庫筒饰。最明確地方式是使用標(biāo)準(zhǔn)的Spring Data @Enable* Repositories缴啡,然后告訴它你的Repository接口的位置(此處*即可以是Jpa,也可以是Mongo瓷们,或者兩者都是)业栅。
這里也有spring.data.*.repositories.enabled標(biāo)志,可用來在外部配置中開啟或關(guān)閉倉庫的自動配置谬晕。這在你想關(guān)閉Mongo倉庫碘裕,但仍舊使用自動配置的MongoTemplate時非常有用。
相同的障礙和特性也存在于其他自動配置的Spring Data倉庫類型(Elasticsearch, Solr)攒钳。只需要改變對應(yīng)注解的名稱和標(biāo)志帮孔。
9.6.10 將Spring Data倉庫暴露為REST端點
Spring Data REST能夠?qū)epository的實現(xiàn)暴露為REST端點,只要該應(yīng)用啟用Spring MVC夕玩。
Spring Boot暴露一系列來自spring.data.rest命名空間的有用屬性來定制化RepositoryRestConfiguration你弦。如果需要提供其他定制惊豺,你可以創(chuàng)建一個繼承自SpringBootRepositoryRestMvcConfiguration的@Configuration類。該類功能和RepositoryRestMvcConfiguration相同禽作,但允許你繼續(xù)使用spring.data.rest.*屬性尸昧。
9.7 數(shù)據(jù)庫初始化
一個數(shù)據(jù)庫可以使用不同的方式進(jìn)行初始化,這取決于你的技術(shù)棧旷偿∨胨祝或者你可以手動完成該任務(wù),只要數(shù)據(jù)庫是單獨的過程萍程。
9.7.1 使用JPA初始化數(shù)據(jù)庫
JPA有個生成DDL的特性幢妄,這些可以設(shè)置為在數(shù)據(jù)庫啟動時運(yùn)行。這可以通過兩個外部屬性進(jìn)行控制:
- spring.jpa.generate-ddl(boolean)控制該特性的關(guān)閉和開啟,跟實現(xiàn)者沒關(guān)系
- spring.jpa.hibernate.ddl-auto(enum)是一個Hibernate特性,用于更細(xì)力度的控制該行為映砖。更多詳情參考以下內(nèi)容。
9.7.2 使用Hibernate初始化數(shù)據(jù)庫
你可以顯式設(shè)置spring.jpa.hibernate.ddl-auto潮尝,標(biāo)準(zhǔn)的Hibernate屬性值有none,validate饿序,update勉失,create,create-drop原探。Spring Boot根據(jù)你的數(shù)據(jù)庫是否為內(nèi)嵌數(shù)據(jù)庫來選擇相應(yīng)的默認(rèn)值乱凿,如果是內(nèi)嵌型的則默認(rèn)值為create-drop,否則為none咽弦。通過查看Connection類型可以檢查是否為內(nèi)嵌型數(shù)據(jù)庫徒蟆,hsqldb,h2和derby是內(nèi)嵌的型型,其他都不是后专。當(dāng)從內(nèi)存數(shù)據(jù)庫遷移到一個真正的數(shù)據(jù)庫時,你需要當(dāng)心输莺,在新的平臺中不能對數(shù)據(jù)庫表和數(shù)據(jù)是否存在進(jìn)行臆斷。你也需要顯式設(shè)置ddl-auto裸诽,或使用其他機(jī)制初始化數(shù)據(jù)庫嫂用。
此外,啟動時處于classpath根目錄下的import.sql文件會被執(zhí)行丈冬。這在demos或測試時很有用嘱函,但在生產(chǎn)環(huán)境中你可能不期望這樣。這是Hibernate的特性埂蕊,和Spring沒有一點關(guān)系往弓。
9.7.3 使用Spring JDBC初始化數(shù)據(jù)庫
Spring JDBC有一個DataSource初始化特性疏唾。Spring Boot默認(rèn)啟用了該特性,并從標(biāo)準(zhǔn)的位置schema.sql和data.sql(位于classpath根目錄)加載SQL函似。此外槐脏,Spring Boot將加載schema-${platform}.sql和data-${platform}.sql文件(如果存在),在這里platform是spring.datasource.platform的值撇寞,比如顿天,你可以將它設(shè)置為數(shù)據(jù)庫的供應(yīng)商名稱(hsqldb, h2, oracle, mysql, postgresql等)。Spring Boot默認(rèn)啟用Spring JDBC初始化快速失敗特性蔑担,所以如果腳本導(dǎo)致異常產(chǎn)生牌废,那應(yīng)用程序?qū)邮 D_本的位置可以通過設(shè)置spring.datasource.schema和spring.datasource.data來改變啤握,如果設(shè)置spring.datasource.initialize=false則哪個位置都不會被處理鸟缕。
你可以設(shè)置spring.datasource.continueOnError=true禁用快速失敗特性。一旦應(yīng)用程序成熟并被部署了很多次排抬,那該設(shè)置就很有用懂从,因為腳本可以充當(dāng)"可憐人的遷移"-例如,插入失敗時意味著數(shù)據(jù)已經(jīng)存在畜埋,也就沒必要阻止應(yīng)用繼續(xù)運(yùn)行莫绣。
如果你想要在一個JPA應(yīng)用中使用schema.sql,那如果Hibernate試圖創(chuàng)建相同的表悠鞍,ddl-auto=create-drop將導(dǎo)致錯誤產(chǎn)生对室。為了避免那些錯誤,可以將ddl-auto設(shè)置為“”(推薦)或“none”咖祭。不管是否使用ddl-auto=create-drop掩宜,你總可以使用data.sql初始化新數(shù)據(jù)。
9.7.4 初始化Spring Batch數(shù)據(jù)庫
如果你正在使用Spring Batch么翰,那么它會為大多數(shù)的流行數(shù)據(jù)庫平臺預(yù)裝SQL初始化腳本牺汤。Spring Boot會檢測你的數(shù)據(jù)庫類型,并默認(rèn)執(zhí)行那些腳本浩嫌,在這種情況下將關(guān)閉快速失敗特性(錯誤被記錄但不會阻止應(yīng)用啟動)檐迟。這是因為那些腳本是可信任的,通常不會包含bugs码耐,所以錯誤會被忽略掉追迟,并且對錯誤的忽略可以讓腳本具有冪等性。你可以使用spring.batch.initializer.enabled=false顯式關(guān)閉初始化功能骚腥。
9.7.5 使用一個高級別的數(shù)據(jù)遷移工具
Spring Boot跟高級別的數(shù)據(jù)遷移工具Flyway(基于SQL)和Liquibase(XML)工作的很好敦间。通常我們傾向于Flyway,因為它一眼看去好像很容易,另外它通常不需要平臺獨立:一般一個或至多需要兩個平臺廓块。
9.7.5.1 啟動時執(zhí)行Flyway數(shù)據(jù)庫遷移
想要在啟動時自動運(yùn)行Flyway數(shù)據(jù)庫遷移厢绝,需要將org.flywaydb:flyway-core添加到你的classpath下。
遷移是一些V<VERSION>__<NAME>.sql格式的腳本(<VERSION>是一個下劃線分割的版本號带猴,比如'1'或'2_1')昔汉。默認(rèn)情況下,它們存放在一個classpath:db/migration的文件夾中浓利,但你可以使用flyway.locations(一個列表)來改變它挤庇。詳情可參考flyway-core中的Flyway類,查看一些可用的配置贷掖,比如schemas嫡秕。Spring Boot在FlywayProperties中提供了一個小的屬性集,可用于禁止遷移苹威,或關(guān)閉位置檢測昆咽。
默認(rèn)情況下,F(xiàn)lyway將自動注入(@Primary)DataSource到你的上下文牙甫,并用它進(jìn)行數(shù)據(jù)遷移掷酗。如果你想使用一個不同的DataSource,你可以創(chuàng)建一個窟哺,并將它標(biāo)記為@FlywayDataSource的@Bean-如果你這樣做了泻轰,且想要兩個數(shù)據(jù)源,記得創(chuàng)建另一個并將它標(biāo)記為@Primary且轨「∩或者你可以通過在外部配置文件中設(shè)置flyway.[url,user,password]來使用Flyway的原生DataSource。
這是一個Flyway示例旋奢,你可以作為參考泳挥。
9.7.5.2 啟動時執(zhí)行Liquibase數(shù)據(jù)庫遷移
想要在啟動時自動運(yùn)行Liquibase數(shù)據(jù)庫遷移,你需要將org.liquibase:liquibase-core添加到classpath下至朗。
主改變?nèi)罩荆╩aster change log)默認(rèn)從db/changelog/db.changelog-master.yaml讀取屉符,但你可以使用liquibase.change-log進(jìn)行設(shè)置。詳情查看LiquibaseProperties以獲取可用設(shè)置锹引,比如上下文矗钟,默認(rèn)的schema等。
這里有個Liquibase示例可作為參考嫌变。
9.8 批處理應(yīng)用
9.8.1 在啟動時執(zhí)行Spring Batch作業(yè)
你可以在上下文的某個地方添加@EnableBatchProcessing來啟用Spring Batch的自動配置功能真仲。
默認(rèn)情況下,在啟動時它會執(zhí)行應(yīng)用的所有作業(yè)(Jobs)初澎,具體查看JobLauncherCommandLineRunner。你可以通過指定spring.batch.job.names(多個作業(yè)名以逗號分割)來縮小到一個特定的作業(yè)或多個作業(yè)。
如果應(yīng)用上下文包含一個JobRegistry碑宴,那么處于spring.batch.job.names中的作業(yè)將會從registry中查找软啼,而不是從上下文中自動裝配。這是復(fù)雜系統(tǒng)中常見的一個模式延柠,在這些系統(tǒng)中多個作業(yè)被定義在子上下文和注冊中心祸挪。
具體參考BatchAutoConfiguration和@EnableBatchProcessing。
9.9 執(zhí)行器
9.9.1 改變HTTP端口或執(zhí)行器端點的地址
在一個單獨的應(yīng)用中贞间,執(zhí)行器的HTTP端口默認(rèn)和主HTTP端口相同贿条。想要讓應(yīng)用監(jiān)聽不同的端口,你可以設(shè)置外部屬性management.port增热。為了監(jiān)聽一個完全不同的網(wǎng)絡(luò)地址(比如整以,你有一個用于管理的內(nèi)部網(wǎng)絡(luò)和一個用于用戶應(yīng)用程序的外部網(wǎng)絡(luò)),你可以將management.address設(shè)置為一個可用的IP地址峻仇,然后將服務(wù)器綁定到該地址公黑。
查看ManagementServerProperties源碼和'Production-ready特性'章節(jié)中的Section 41.3, “Customizing the management server port”
來獲取更多詳情。
9.9.2 自定義'白標(biāo)'(whitelabel摄咆,可以了解下相關(guān)理念)錯誤頁面
Spring Boot安裝了一個'whitelabel'錯誤頁面凡蚜,如果你遇到一個服務(wù)器錯誤(機(jī)器客戶端消費的是JSON,其他媒體類型則會看到一個具有正確錯誤碼的合乎情理的響應(yīng))吭从,那就能在客戶端瀏覽器中看到該頁面朝蜘。你可以設(shè)置error.whitelabel.enabled=false來關(guān)閉該功能,但通常你想要添加自己的錯誤頁面來取代whitelabel涩金。確切地說谱醇,如何實現(xiàn)取決于你使用的模板技術(shù)。例如鸭廷,你正在使用Thymeleaf枣抱,你將添加一個error.html模板。如果你正在使用FreeMarker辆床,那你將添加一個error.ftl模板佳晶。通常,你需要的只是一個名稱為error的View讼载,和/或一個處理/error路徑的@Controller轿秧。除非你替換了一些默認(rèn)配置,否則你將在你的ApplicationContext中找到一個BeanNameViewResolver咨堤,所以一個id為error的@Bean可能是完成該操作的一個簡單方式菇篡。詳情參考ErrorMvcAutoConfiguration。
查看Error Handling章節(jié)一喘,了解下如何將處理器(handlers)注冊到servlet容器中驱还。
9.10 安全
9.10.1 關(guān)閉Spring Boot安全配置
不管你在應(yīng)用的什么地方定義了一個使用@EnableWebSecurity注解的@Configuration嗜暴,它將會關(guān)閉Spring Boot中的默認(rèn)webapp安全設(shè)置。想要調(diào)整默認(rèn)值议蟆,你可以嘗試設(shè)置security.*屬性(具體查看SecurityProperties和常見應(yīng)用屬性的SECURITY章節(jié))闷沥。
9.10.2 改變AuthenticationManager并添加用戶賬號
如果你提供了一個AuthenticationManager類型的@Bean,那么默認(rèn)的就不會被創(chuàng)建了咐容,所以你可以獲得Spring Security可用的全部特性(比如舆逃,不同的認(rèn)證選項)。
Spring Security也提供了一個方便的AuthenticationManagerBuilder戳粒,可用于構(gòu)建具有常見選項的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
}
如果把它放到一個內(nèi)部類或一個單獨的類中奄妨,你將得到最好的結(jié)果(也就是不跟很多其他@Beans混合在一起將允許你改變實例化的順序)。secure web sample是一個有用的參考模板炊琉。
如果你遇到了實例化問題(比如展蒂,使用JDBC或JPA進(jìn)行用戶詳細(xì)信息的存儲),那將AuthenticationManagerBuilder回調(diào)提取到一個GlobalAuthenticationConfigurerAdapter(放到init()方法內(nèi)以防其他地方也需要authentication manager)可能是個不錯的選擇苔咪,比如:
@Configuration
public class AuthenticationManagerConfiguration extends
GlobalAuthenticationConfigurerAdapter {
@Override
public void init(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication() // ... etc.
}
}
9.10.3 當(dāng)前端使用代理服務(wù)器時锰悼,啟用HTTPS
對于任何應(yīng)用來說,確保所有的主端點(URL)都只在HTTPS下可用是個重要的苦差事团赏。如果你使用Tomcat作為servlet容器箕般,那Spring Boot如果發(fā)現(xiàn)一些環(huán)境設(shè)置的話,它將自動添加Tomcat自己的RemoteIpValve舔清,你也可以依賴于HttpServletRequest來報告是否請求是安全的(即使代理服務(wù)器的downstream處理真實的SSL終端)丝里。這個標(biāo)準(zhǔn)行為取決于某些請求頭是否出現(xiàn)(x-forwarded-for和x-forwarded-proto),這些請求頭的名稱都是約定好的体谒,所以對于大多數(shù)前端和代理都是有效的蒲牧。
你可以向application.properties添加以下設(shè)置里開啟該功能秽之,比如:
server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto
(這些屬性出現(xiàn)一個就會開啟該功能,或者你可以通過添加一個TomcatEmbeddedServletContainerFactory bean自己添加RemoteIpValve)
Spring Security也可以配置成針對所以或某些請求需要一個安全渠道(channel)。想要在一個Spring Boot應(yīng)用中開啟它尽超,你只需將application.properties中的security.require_ssl設(shè)置為true即可席里。
9.11 熱交換
9.11.1 重新加載靜態(tài)內(nèi)容
Spring Boot有很多用于熱加載的選項宏蛉。使用IDE開發(fā)是一個不錯的方式肯污,特別是需要調(diào)試的時候(所有的現(xiàn)代IDEs都允許重新加載靜態(tài)資源,通常也支持對變更的Java類進(jìn)行熱交換)彩届。Maven和Gradle插件也支持命令行下的靜態(tài)文件熱加載伪冰。如果你使用其他高級工具編寫css/js,并使用外部的css/js編譯器樟蠕,那你就可以充分利用該功能贮聂。
9.11.2 在不重啟容器的情況下重新加載Thymeleaf模板
如果你正在使用Thymeleaf靠柑,那就將spring.thymeleaf.cache設(shè)置為false。查看ThymeleafAutoConfiguration可以獲取其他Thymeleaf自定義選項寂汇。
9.11.3 在不重啟容器的情況下重新加載FreeMarker模板
如果你正在使用FreeMarker病往,那就將spring.freemarker.cache設(shè)置為false。查看FreeMarkerAutoConfiguration 可以獲取其他FreeMarker自定義選項骄瓣。
9.11.4 在不重啟容器的情況下重新加載Groovy模板
如果你正在使用Groovy模板,那就將spring.groovy.template.cache設(shè)置為false耍攘。查看GroovyTemplateAutoConfiguration可以獲取其他Groovy自定義選項榕栏。
9.11.5 在不重啟容器的情況下重新加載Velocity模板
如果你正在使用Velocity,那就將spring.velocity.cache設(shè)置為false蕾各。查看VelocityAutoConfiguration可以獲取其他Velocity自定義選項扒磁。
9.11.6 在不重啟容器的情況下重新加載Java類
現(xiàn)代IDEs(Eclipse, IDEA等)都支持字節(jié)碼的熱交換,所以如果你做了一個沒有影響類或方法簽名的改變式曲,它會利索地重新加載并沒有任何影響妨托。
Spring Loaded在這方面走的更遠(yuǎn),它能夠重新加載方法簽名改變的類定義吝羞。如果對它進(jìn)行一些自定義配置可以強(qiáng)制ApplicationContext刷新自己(但沒有通用的機(jī)制來確保這對一個運(yùn)行中的應(yīng)用總是安全的兰伤,所以它可能只是一個開發(fā)時間的技巧)。
9.11.6.1 使用Maven配置Spring Loaded
為了在Maven命令行下使用Spring Loaded钧排,你只需將它作為一個依賴添加到Spring Boot插件聲明中即可敦腔,比如:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
</dependencies>
</plugin>
正常情況下,這在Eclipse和IntelliJ中工作的相當(dāng)漂亮恨溜,只要它們有相應(yīng)的符衔,和Maven默認(rèn)一致的構(gòu)建配置(Eclipse m2e對此支持的更好,開箱即用)糟袁。
9.11.6.2 使用Gradle和IntelliJ配置Spring Loaded
如果想將Spring Loaded和Gradle判族,IntelliJ結(jié)合起來,那你需要付出代價项戴。默認(rèn)情況下形帮,IntelliJ將類編譯到一個跟Gradle不同的位置,這會導(dǎo)致Spring Loaded監(jiān)控失敗肯尺。
為了正確配置IntelliJ沃缘,你可以使用idea Gradle插件:
buildscript {
repositories { jcenter() }
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:1.3.0.BUILD-SNAPSHOT"
classpath 'org.springframework:springloaded:1.2.0.RELEASE'
}
}
apply plugin: 'idea'
idea {
module {
inheritOutputDirs = false
outputDir = file("$buildDir/classes/main/")
}
}
// ...
注:IntelliJ必須配置跟命令行Gradle任務(wù)相同的Java版本,并且springloaded必須作為一個buildscript依賴被包含進(jìn)去则吟。
此外槐臀,你也可以啟用Intellij內(nèi)部的Make Project Automatically,這樣不管什么時候只要文件被保存都會自動編譯你的代碼氓仲。
9.12 構(gòu)建
9.12.1 使用Maven自定義依賴版本
如果你使用Maven進(jìn)行一個直接或間接繼承spring-boot-dependencies(比如spring-boot-starter-parent)的構(gòu)建水慨,并想覆蓋一個特定的第三方依賴得糜,那你可以添加合適的<properties>元素。瀏覽spring-boot-dependencies POM可以獲取一個全面的屬性列表晰洒。例如朝抖,想要選擇一個不同的slf4j版本,你可以添加以下內(nèi)容:
<properties>
<slf4j.version>1.7.5<slf4j.version>
</properties>
注:這只在你的Maven項目繼承(直接或間接)自spring-boot-dependencies才有用谍珊。如果你使用<scope>import</scope>治宣,將spring-boot-dependencies添加到自己的dependencyManagement片段,那你必須自己重新定義artifact而不是覆蓋屬性砌滞。
注:每個Spring Boot發(fā)布都是基于一些特定的第三方依賴集進(jìn)行設(shè)計和測試的侮邀,覆蓋版本可能導(dǎo)致兼容性問題。
9.12.2 使用Maven創(chuàng)建可執(zhí)行JAR
spring-boot-maven-plugin能夠用來創(chuàng)建可執(zhí)行的'胖'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打掘,你仍舊可以使用該插件华畏。不過,你需要另外添加一個<executions>片段:
<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>
查看插件文檔獲取詳細(xì)的用例尊蚁。
9.12.3 創(chuàng)建其他的可執(zhí)行JAR
如果你想將自己的項目以library jar的形式被其他項目依賴亡笑,并且需要它是一個可執(zhí)行版本(例如demo),你需要使用略微不同的方式來配置該構(gòu)建枝誊。
對于Maven來說况芒,正常的JAR插件和Spring Boot插件都有一個'classifier',你可以添加它來創(chuàng)建另外的JAR叶撒。示例如下(使用Spring Boot Starter Parent管理插件版本绝骚,其他配置采用默認(rèn)設(shè)置):
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
上述配置會產(chǎn)生兩個jars,默認(rèn)的一個和使用帶有classifier 'exec'的Boot插件構(gòu)建的可執(zhí)行的一個祠够。
對于Gradle用戶來說压汪,步驟類似。示例如下:
bootRepackage {
classifier = 'exec'
}
9.12.4 在可執(zhí)行jar運(yùn)行時提取特定的版本
在一個可執(zhí)行jar中古瓤,為了運(yùn)行止剖,多數(shù)內(nèi)嵌的庫不需要拆包(unpacked),然而有一些庫可能會遇到問題落君。例如穿香,JRuby包含它自己的內(nèi)嵌jar,它假定jruby-complete.jar本身總是能夠直接作為文件訪問的绎速。
為了處理任何有問題的庫皮获,你可以標(biāo)記那些特定的內(nèi)嵌jars,讓它們在可執(zhí)行jar第一次運(yùn)行時自動解壓到一個臨時文件夾中纹冤。例如洒宝,為了將JRuby標(biāo)記為使用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']
}
9.12.6 遠(yuǎn)程調(diào)試一個使用Maven啟動的Spring Boot項目
想要為使用Maven啟動的Spring Boot應(yīng)用添加一個遠(yuǎn)程調(diào)試器,你可以使用mave插件的jvmArguments屬性雁歌。詳情參考示例宏浩。
9.12.7 遠(yuǎn)程調(diào)試一個使用Gradle啟動的Spring Boot項目
想要為使用Gradle啟動的Spring Boot應(yīng)用添加一個遠(yuǎn)程調(diào)試器,你可以使用build.gradle的applicationDefaultJvmArgs屬性或--debug-jvm命令行選項靠瞎。
build.gradle:
applicationDefaultJvmArgs = [
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
]
命令行:
$ gradle run --debug-jvm
詳情查看Gradle應(yīng)用插件比庄。
9.12.8 使用Ant構(gòu)建可執(zhí)行存檔(archive)
想要使用Ant進(jìn)行構(gòu)建,你需要抓取依賴乏盐,編譯印蔗,然后像通常那樣創(chuàng)建一個jar或war存檔。為了讓它可以執(zhí)行:
- 使用合適的啟動器配置Main-Class丑勤,比如對于jar文件使用JarLauncher,然后將其他需要的屬性以manifest實體指定吧趣,主要是一個Start-Class法竞。
- 將運(yùn)行時依賴添加到一個內(nèi)嵌的'lib'目錄(對于jar),provided(內(nèi)嵌容器)依賴添加到一個內(nèi)嵌的lib-provided目錄强挫。記住不要壓縮存檔中的實體岔霸。
- 在存檔的根目錄添加spring-boot-loader類(這樣Main-Class就可用了)。
示例:
<target name="build" depends="compile">
<copy todir="target/classes/lib">
<fileset dir="lib/runtime" />
</copy>
<jar destfile="target/spring-boot-sample-actuator-${spring-boot.version}.jar" compress="false">
<fileset dir="target/classes" />
<fileset dir="src/main/resources" />
<zipfileset src="lib/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
<manifest>
<attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
</manifest>
</jar>
</target>
該Actuator示例中有一個build.xml文件俯渤,可以使用以下命令來運(yùn)行:
$ ant -lib /ivy-2.2.jar
在上述操作之后呆细,你可以使用以下命令運(yùn)行該應(yīng)用:
$ java -jar target/*.jar
9.12.9 如何使用Java6
如果想在Java6環(huán)境中使用Spring Boot,你需要改變一些配置八匠。具體的變化取決于你應(yīng)用的功能絮爷。
9.12.9.1 內(nèi)嵌Servlet容器兼容性
如果你在使用Boot的內(nèi)嵌Servlet容器,你需要使用一個兼容Java6的容器梨树。Tomcat 7和Jetty 8都是Java 6兼容的坑夯。具體參考Section 63.15, “Use Tomcat 7”和Section 63.16, “Use Jetty 8”。
9.12.9.2 JTA API兼容性
Java事務(wù)API自身并不要求Java 7抡四,而是官方的API jar包含的已構(gòu)建類要求Java 7柜蜈。如果你正在使用JTA,那么你需要使用能夠在Java 6工作的構(gòu)建版本替換官方的JTA 1.2 API jar指巡。為了完成該操作淑履,你需要排除任何對javax.transaction:javax.transaction-api的傳遞依賴,并使用org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Final依賴替換它們藻雪。
9.13 傳統(tǒng)部署
9.13.1 創(chuàng)建一個可部署的war文件
產(chǎn)生一個可部署war包的第一步是提供一個SpringBootServletInitializer子類秘噪,并覆蓋它的configure方法。這充分利用了Spring框架對Servlet 3.0的支持阔涉,并允許你在應(yīng)用通過servlet容器啟動時配置它缆娃。通常捷绒,你只需把應(yīng)用的主類改為繼承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);
}
}
下一步是更新你的構(gòu)建配置,這樣你的項目將產(chǎn)生一個war包而不是jar包贯要。如果你使用Maven暖侨,并使用spring-boot-starter-parent(為了配置Maven的war插件),所有你需要做的就是更改pom.xml的packaging為war:
<packaging>war</packaging>
如果你使用Gradle崇渗,你需要修改build.gradle來將war插件應(yīng)用到項目上:
apply plugin: 'war'
該過程最后的一步是確保內(nèi)嵌的servlet容器不能干擾war包將部署的servlet容器字逗。為了達(dá)到這個目的,你需要將內(nèi)嵌容器的依賴標(biāo)記為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構(gòu)建工具葫掉,將內(nèi)嵌容器依賴標(biāo)記為provided將產(chǎn)生一個可執(zhí)行war包,在lib-provided目錄有該war包的provided依賴跟狱。這意味著俭厚,除了部署到servlet容器,你還可以通過使用命令行java -jar命令來運(yùn)行應(yīng)用驶臊。
注:查看Spring Boot基于以上配置的一個Maven示例應(yīng)用挪挤。
9.13.2 為老的servlet容器創(chuàng)建一個可部署的war文件
老的Servlet容器不支持在Servlet 3.0中使用的ServletContextInitializer啟動處理。你仍舊可以在這些容器使用Spring和Spring Boot关翎,但你需要為應(yīng)用添加一個web.xml扛门,并將它配置為通過一個DispatcherServlet加載一個ApplicationContext。
9.13.3 將現(xiàn)有的應(yīng)用轉(zhuǎn)換為Spring Boot
對于一個非web項目纵寝,轉(zhuǎn)換為Spring Boot應(yīng)用很容易(拋棄創(chuàng)建ApplicationContext的代碼论寨,取而代之的是調(diào)用SpringApplication或SpringApplicationBuilder)。Spring MVC web應(yīng)用通常先創(chuàng)建一個可部署的war應(yīng)用爽茴,然后將它遷移為一個可執(zhí)行的war或jar葬凳。建議閱讀Getting Started Guide on Converting a jar to a war.。
通過繼承SpringBootServletInitializer創(chuàng)建一個可執(zhí)行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提供它的默認(rèn)實現(xiàn),不過有可能需要先完成一些事情窖逗。
靜態(tài)資源可以移到classpath根目錄下的/public(或/static址否,/resources,/META-INF/resources)。同樣的方式也適合于messages.properties(Spring Boot在classpath根目錄下自動發(fā)現(xiàn)這些配置)佑附。
美妙的(Vanilla usage of)Spring DispatcherServlet和Spring Security不需要改變樊诺。如果你的應(yīng)用有其他特性匣砖,比如使用其他servlets或filters蕴轨,那你可能需要添加一些配置到你的Application上下文中,按以下操作替換web.xml的那些元素:
- 在容器中安裝一個Servlet或ServletRegistrationBean類型的@Bean骆捧,就好像web.xml中的<servlet/>和<servlet-mapping/>权均。
- 同樣的添加一個Filter或FilterRegistrationBean類型的@Bean(類似于<filter/>和<filter-mapping/>)顿膨。
- 在XML文件中的ApplicationContext可以通過@Import添加到你的Application中。簡單的情況下叽赊,大量使用注解配置可以在幾行內(nèi)定義@Bean定義恋沃。
一旦war可以使用,我們就通過添加一個main方法到Application來讓它可以執(zhí)行必指,比如:
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
應(yīng)用可以劃分為多個類別:
- 沒有web.xml的Servlet 3.0+應(yīng)用
- 有web.xml的應(yīng)用
- 有上下文層次的應(yīng)用
- 沒有上下文層次的應(yīng)用
所有這些都可以進(jìn)行適當(dāng)?shù)霓D(zhuǎn)化囊咏,但每個可能需要稍微不同的技巧。
Servlet 3.0+的應(yīng)用轉(zhuǎn)化的相當(dāng)簡單塔橡,如果它們已經(jīng)使用Spring Servlet 3.0+初始化器輔助類匆笤。通常所有來自一個存在的WebApplicationInitializer的代碼可以移到一個SpringBootServletInitializer中。如果一個存在的應(yīng)用有多個ApplicationContext(比如谱邪,如果它使用AbstractDispatcherServletInitializer),那你可以將所有上下文源放進(jìn)一個單一的SpringApplication庶诡。你遇到的主要難題可能是如果那樣不能工作惦银,那你就要維護(hù)上下文層次。參考示例entry on building a hierarchy末誓。一個存在的包含web相關(guān)特性的父上下文通常需要分解扯俱,這樣所有的ServletContextAware組件都處于子上下文中。
對于還不是Spring應(yīng)用的應(yīng)用來說喇澡,上面的指南有助于你把應(yīng)用轉(zhuǎn)換為一個Spring Boot應(yīng)用迅栅,但你也可以選擇其他方式。
9.13.4 部署WAR到Weblogic
想要將Spring Boot應(yīng)用部署到Weblogic晴玖,你需要確保你的servlet初始化器直接實現(xiàn)WebApplicationInitializer(即使你繼承的基類已經(jīng)實現(xiàn)了它)读存。
一個傳統(tǒng)的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你傾向使用的打包版本而不是服務(wù)器預(yù)裝的版本呕屎。你可以通過添加一個具有如下內(nèi)容的WEB-INF/weblogic.xml實現(xiàn)該操作:
<?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>
轉(zhuǎn)載自:https://www.gitbook.com/book/qbgbook/spring-boot-reference-guide-zh/details