天天看點

Spring Boot特性1. SpringApplication2. 外化配置3. Profiles4. 日志5. 開發Web應用

springapplication 類是啟動 spring boot 應用的入口類,你可以建立一個包含 <code>main()</code> 方法的類,來運作 <code>springapplication.run</code> 這個靜态方法:

運作該類會有如下輸出:

通過在classpath下添加一個banner.txt或設定banner.location來指定相應的檔案可以改變啟動過程中列印的banner。如果這個檔案有特殊的編碼,你可以使用banner.encoding設定它(預設為utf-8)。

在banner.txt中可以使用如下的變量:

<code>${application.version}</code>:manifest.mf 檔案中的應用版本号

<code>${application.formatted-version}</code>

<code>${spring-boot.version}</code>:你正在使用的 spring boot 版本号

<code>${spring-boot.formatted-version}</code>

上面這些變量也可以通過 application.properties 來設定,後面再作介紹。

注:如果想以程式設計的方式産生一個banner,可以使用springbootapplication.setbanner(…)方法。使用org.springframework.boot.banner接口,實作你自己的printbanner()方法。

如果預設的springapplication不符合你的口味,你可以建立一個本地的執行個體并自定義它。例如,關閉banner你可以這樣寫:

如果你需要建立一個分層的applicationcontext(多個具有父子關系的上下文),或你隻是喜歡使用流暢的建構api,你可以使用springapplicationbuilder。springapplicationbuilder允許你以鍊式方式調用多個方法,包括可以建立層次結構的parent和child方法。

springapplication 啟動過程會觸發一些事件,你可以針對這些事件通過 <code>springapplication.addlisteners(…​)</code> 添加一些監聽器:

applicationstartedevent

applicationenvironmentpreparedevent

applicationpreparedevent

applicationfailedevent

springapplication 會注冊一個 shutdown hook 以便在應用退出的時候能夠保證 <code>applicationcontext</code> 優雅地關閉,這樣能夠保證所有 spring lifecycle 的回調都會被執行,包括 disposablebean 接口的實作類以及 <code>@predestroy</code> 注解。

另外,你也可以實作 <code>org.springframework.boot.exitcodegenerator</code> 接口來定義你自己的退出時候的邏輯。

一個<code>springapplication</code>将嘗試為你建立正确類型的<code>applicationcontext</code>。在預設情況下,使用<code>annotationconfigapplicationcontext</code>或<code>annotationconfigembeddedwebapplicationcontext</code>取決于你正在開發的是否是web應用。

用于确定一個web環境的算法相當簡單(基于是否存在某些類)。如果需要覆寫預設行為,你可以使用<code>setwebenvironment(boolean webenvironment)</code>。通過調用<code>setapplicationcontextclass(…)</code>,你可以完全控制applicationcontext的類型。

注:當junit測試裡使用springapplication時,調用<code>setwebenvironment(false)</code>是可取的。

如果你想擷取應用程式傳遞給<code>springapplication.run(…​)</code>的參數,你可以注入一個<code>org.springframework.boot.applicationarguments</code>bean,applicationarguments這個接口提供了方法擷取可選的和非可選的string[]類型的參數。

spring boot也會在<code>environment</code>中注入一個<code>commandlinepropertysource</code>,這允許你使用<code>@value</code>注解注入一個應用參數。

如果一些commandlinerunner或者applicationrunner beans被定義必須以特定的次序調用,你可以額外實作<code>org.springframework.core.ordered</code>接口或使用<code>@order</code>注解。

<code>springapplication</code>會在jvm上注冊一個關閉的hook已确認applicationcontext是否優雅的關閉。所有的标準的spring生命周期回調(例如,<code>disposablebean</code>接口,或者<code>@predestroy</code>注解)都可以使用。

另外,beans可以實作org.springframework.boot.exitcodegenerator接口在應用程式結束的時候傳回一個錯誤碼。

通過<code>spring.application.admin.enabled</code>開啟。

spring boot允許你針對不同的環境配置不同的配置參數,你可以使用 properties檔案、yaml 檔案、環境變量或者指令行參數來修改應用的配置。你可以在代碼中使用@value注解來擷取配置參數的值。

spring boot使用一個特别的<code>propertysource</code>來按順序加載配置,加載順序如下:

指令行參數

來自<code>spring_application_json</code>的屬性

<code>java:comp/env</code> 中的 jndi 屬性

java系統環境變量

作業系統環境變量

<code>randomvaluepropertysource</code>,随機值,使用 <code>random.*</code> 來定義

jar 包外的 profile 配置檔案,如 application-{profile}.properties 和 yaml 檔案

jar 包内的 profile 配置檔案,如 application-{profile}.properties 和 yaml 檔案

jar 包外的 application 配置,如 application.properties 和 application.yml 檔案

jar 包内的 application 配置,如 application.properties 和 application.yml 檔案

在标有 @configuration 注解的類标有@propertysource注解的

預設值,使用 <code>springapplication.setdefaultproperties</code> 設定的

示例代碼:

你可以在 <code>application.properties</code> 中定義一個 name 變量,或者在運作該 jar 時候,指定一個指令行參數(以 <code>--</code> 辨別),例如:<code>java -jar app.jar --name="spring"</code>

也可以使用<code>spring_application_json</code>屬性:

在這個例子中,你可以在spring的<code>environment</code>中通過foo.bar來引用變量。你可以在系統變量中定義<code>pring.application.json</code>:

或者使用指令行參數:

或者使用jndi變量:

randomvaluepropertysource 類型變量的示例如下:

springapplication 會在以下路徑查找 <code>application.properties</code> 并加載該檔案:

<code>/config</code> 目錄下

目前目錄

classpath 中 <code>/config</code> 包下

classpath 根路徑下

另外,你也可以通過 <code>spring.config.location</code> 來指定 <code>application.properties</code> 檔案的存放路徑,或者通過 <code>spring.config.name</code> 指定該檔案的名稱,例如:

或者:

即<code>application-{profile}.properties</code>配置檔案。

在<code>application.properties</code>檔案中可以引用<code>environment</code>中已經存在的變量。

你可以使用 <code>@profile</code> 注解來标注應用使用的環境

可以使用 <code>spring.profiles.active</code> 變量來定義應用激活的 profile:

還可以通過 springapplication 來設定,調用 <code>springapplication.setadditionalprofiles(…​)</code> 代碼即可。

spring boot 使用 commons logging 作為内部記錄日志,你也可以使用 java util logging, log4j, log4j2 和 logback 來記錄日志。

預設情況下,如果你使用了 starter poms ,則會使用 logback 來記錄日志。

預設情況,是輸出 info 類型的日志,你可以通過設定指令行參數<code>--debug</code>來設定:

如果你的終端支援 ansi ,則日志支援彩色輸出,這個可以通過 <code>spring.output.ansi.enabled</code> 設定,可配置的值有:<code>always</code>、<code>detect</code>、<code>never</code>。

可選的顔色有:

blue

cyan

faint

green

magenta

red

yellow

可以通過 <code>logging.file</code> 和 <code>logging.path</code> 設定日志輸出檔案名稱和路徑。

日志級别使用 <code>logging.level.*=level</code> 來定義,例如:

spring boot 通過 <code>logging.config</code> 來定義日志的配置檔案存放路徑,對于不同的日志系統,配置檔案的名稱不同:

logging

system customization

logback

logback-spring.xml、logback-spring.groovy、logback.xml 、 logback.groovy

log4j

log4j-spring.properties、log4j-spring.xml、log4j.properties 、log4j.xml

log4j2

log4j2-spring.xml、log4j2.xml

jdk (java util logging)

logging.properties

對于<code>logback-spring.xml</code>這類的配置,建議使用<code>-spring</code>變量來加載配置檔案。

environment中可以自定義一些屬性:

spring environment

system property

comments

<code>logging.exception-conversion-word</code>

<code>log_exception_conversion_word</code>

<code>logging.file</code>

<code>log_file</code>

<code>logging.path</code>

<code>log_path</code>

<code>logging.pattern.console</code>

<code>console_log_pattern</code>

<code>logging.pattern.file</code>

<code>file_log_pattern</code>

<code>logging.pattern.level</code>

<code>log_level_pattern</code>

<code>pid</code>

一個标準的<code>@restcontroller</code>例子傳回json資料:

spring boot為spring mvc提供适用于多數應用的自動配置功能。在spring預設基礎上,自動配置添加了以下特性:

引入<code>contentnegotiatingviewresolver</code><code>和beannameviewresolver</code> beans。

對靜态資源的支援,包括對webjars的支援。

自動注冊<code>converter</code>,<code>genericconverter</code>,<code>formatter</code> beans。

對<code>httpmessageconverters</code>的支援。

自動注冊<code>messagecoderesolver</code>。

對靜态<code>index.html</code>的支援。

對自定義<code>favicon</code>的支援。

字段使用 <code>configurablewebbindinginitializer</code> bean

如果想全面控制spring mvc,你可以添加自己的<code>@configuration</code>,并使用<code>@enablewebmvc</code>對其注解。如果想保留spring boot mvc的特性,并隻是添加其他的mvc配置(攔截器,formatters,視圖控制器等),你可以添加自己的<code>webmvcconfigureradapter</code>類型的<code>@bean</code>(不使用<code>@enablewebmvc</code>注解)。

spring mvc使用<code>httpmessageconverter</code>接口轉換http請求和響應。合理的預設值被包含的恰到好處(out of the box),例如對象可以自動轉換為json(使用jackson庫)或xml(如果jackson xml擴充可用則使用它,否則使用jaxb)。字元串預設使用<code>utf-8</code>編碼。

如果需要添加或自定義轉換器,你可以使用spring boot的<code>httpmessageconverters</code>類:

任何在上下文中出現的<code>httpmessageconverter</code> bean将會添加到converters清單,你可以通過這種方式覆寫預設的轉換器(converters)。

spring mvc有一個政策,用于從綁定的errors産生用來渲染錯誤資訊的錯誤碼:messagecodesresolver。如果設定<code>spring.mvc.message-codes-resolver.format</code>屬性為<code>prefix_error_code</code>或<code>postfix_error_code</code>(具體檢視<code>defaultmessagecodesresolver.format</code>枚舉值),spring boot會為你建立一個messagecodesresolver。

預設情況下,spring boot從classpath下一個叫<code>/static</code>(<code>/public</code>,<code>/resources</code>或<code>/meta-inf/resources</code>)的檔案夾或從<code>servletcontext</code>根目錄提供靜态内容。這使用了spring mvc的<code>resourcehttprequesthandler</code>,是以你可以通過添加自己的<code>webmvcconfigureradapter</code>并覆寫<code>addresourcehandlers</code>方法來改變這個行為(加載靜态檔案)。

在一個單獨的web應用中,容器預設的servlet是開啟的,如果spring決定不處理某些請求,預設的servlet作為一個回退(降級)将從servletcontext根目錄加載内容。大多數時候,這不會發生(除非你修改預設的mvc配置),因為spring總能夠通過<code>dispatcherservlet</code>處理請求。

此外,上述标準的靜态資源位置有個例外情況是webjars内容。任何在<code>/webjars/**</code>路徑下的資源都将從jar檔案中提供,隻要它們以webjars的格式打包。

注:如果你的應用将被打包成jar,那就不要使用<code>src/main/webapp</code>檔案夾。盡管該檔案夾是一個共同的标準,但它僅在打包成war的情況下起作用,并且如果産生一個jar,多數建構工具都會靜悄悄的忽略它。

如果你想重新整理靜态資源的緩存,你可以定義一個使用hash結尾的url,例如:<code>&lt;link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/&gt;</code>。

為此,需要使用以下配置:

這裡使用了<code>resourceurlencodingfilter</code>過濾器,對于thymeleaf和velocity,該過濾器已經自動配置。其他的模闆引擎,可以通過<code>resourceurlprovider</code>來定義。

當資源檔案自動加載的時候,javascript子產品加載器會重命名靜态檔案。還有一種“固定”的政策來修改檔案名稱。

使用了上面的配置之後,當javascript加載<code>"/js/lib/"</code>目錄下的檔案時,将會使用一個固定的版本<code>"/v12/js/lib/mymodule.js"</code>,而其他的靜态資源仍然使用<code>&lt;link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/&gt;</code>。

spring mvc使用<code>webbindinginitializer</code>來為一個特定的請求初始化<code>webdatabinder</code>。如果你自帶一個了一個<code>configurablewebbindinginitializer</code> <code>@bean</code>,spring boot會自動配置spring mvc來使用它。

正如rest web服務,你也可以使用spring mvc提供動态html内容。spring mvc支援各種各樣的模闆技術,包括velocity,freemarker和jsps。很多其他的模闆引擎也提供它們自己的spring mvc內建。

spring boot為以下的模闆引擎提供自動配置支援:

freemarker

groovy

thymeleaf

velocity

mustache

注:如果可能的話,應該忽略jsps,因為在内嵌的servlet容器使用它們時存在一些已知的限制。

當你使用這些引擎的任何一種,并采用預設的配置,你的模闆将會從<code>src/main/resources/templates</code>目錄下自動加載。

注:intellij idea根據你運作應用的方式會對classpath進行不同的整理。在ide裡通過main方法運作你的應用跟從maven或gradle或打包好的jar中運作相比會導緻不同的順序。這可能導緻spring boot不能從classpath下成功地找到模闆。如果遇到這個問題,你可以在ide裡重新對classpath進行排序,将子產品的類和資源放到第一位。或者,你可以配置子產品的字首為<code>classpath*:/templates/</code>,這樣會查找classpath下的所有模闆目錄。

spring boot預設提供一個<code>/error</code>映射用來以合适的方式處理所有的錯誤,并且它在servlet容器中注冊了一個全局的 錯誤頁面。對于機器用戶端(相對于浏覽器而言,浏覽器偏重于人的行為),它會産生一個具有詳細錯誤,http狀态,異常資訊的json響應。對于浏覽器用戶端,它會産生一個白色标簽樣式(whitelabel)的錯誤視圖,該視圖将以html格式顯示同樣的資料(可以添加一個解析為erro的view來自定義它)。為了完全替換預設的行為,你可以實作<code>errorcontroller</code>,并注冊一個該類型的bean定義,或簡單地添加一個<code>errorattributes</code>類型的bean以使用現存的機制,隻是替換顯示的内容。

如果在某些條件下需要比較多的錯誤頁面,内嵌的servlet容器提供了一個統一的java dsl(領域特定語言)來自定義錯誤處理。 示例:

你也可以使用正常的spring mvc特性來處理錯誤,比如<code>@exceptionhandler</code>方法和<code>@controlleradvice</code>。<code>errorcontroller</code>将會撿起任何沒有處理的異常。

n.b. 如果你為一個路徑注冊一個<code>errorpage</code>,最終被一個過濾器(filter)處理(對于一些非spring web架構,像jersey和wicket這很常見),然後過濾器需要顯式注冊為一個<code>error</code>分發器(dispatcher)。

注:預設的filterregistrationbean沒有包含error分發器類型。

如果你正在開發一個使用超媒體的restful api,spring boot将為spring hateoas提供自動配置,這在多數應用中都工作良好。自動配置替換了對使用<code>@enablehypermediasupport</code>的需求,并注冊一定數量的beans來簡化建構基于超媒體的應用,這些beans包括一個<code>linkdiscoverer</code>和配置好的用于将響應正确編排為想要的表示的<code>objectmapper</code>。objectmapper可以根據<code>spring.jackson.*</code>屬性或一個存在的<code>jackson2objectmapperbuilder</code> bean進行自定義。

通過使用<code>@enablehypermediasupport</code>,你可以控制spring hateoas的配置。注意這會禁用上述的對<code>objectmapper</code>的自定義。

你可以在方法上使用<code>@crossorigin</code>注解,或者配置一個全局的設定:

如果喜歡jax-rs為rest端點提供的程式設計模型,你可以使用可用的實作替代spring mvc。如果在你的應用上下文中将jersey 1.x和apache celtix的servlet或filter注冊為一個@bean,那它們工作的相當好。jersey 2.x有一些原生的spring支援,是以我們會在spring boot為它提供自動配置支援,連同一個啟動器(starter)。

想要開始使用jersey 2.x隻需要加入spring-boot-starter-jersey依賴,然後你需要一個resourceconfig類型的@bean,用于注冊所有的端點(endpoints)。

所有注冊的端點都應該被@components和http資源annotations(比如@get)注解。

由于endpoint是一個spring元件(@component),是以它的生命周期受spring管理,并且你可以使用@autowired添加依賴及使用@value注入外部配置。jersey servlet将被注冊,并預設映射到/*。你可以将@applicationpath添加到resourceconfig來改變該映射。

預設情況下,jersey将在一個servletregistrationbean類型的@bean中被設定成名稱為jerseyservletregistration的servlet。通過建立自己的相同名稱的bean,你可以禁止或覆寫這個bean。你也可以通過設定<code>spring.jersey.type=filter</code>來使用一個filter代替servlet(在這種情況下,被覆寫或替換的@bean是jerseyfilterregistration)。該servlet有@order屬性,你可以通過<code>spring.jersey.filter.order</code>進行設定。不管是servlet還是filter注冊都可以使用<code>spring.jersey.init.*</code>定義一個屬性集合作為初始化參數傳遞過去。

當使用内嵌的servlet容器時,你可以直接将servlet和filter注冊為spring的beans。在配置期間,如果你想引用來自application.properties的值,這是非常友善的。預設情況下,如果上下文隻包含單一的servlet,那它将被映射到根路徑(/)。在多servlet beans的情況下,bean的名稱将被用作路徑的字首。過濾器會被映射到/*。

如果基于約定(convention-based)的映射不夠靈活,你可以使用servletregistrationbean和filterregistrationbean類實作完全的控制。如果你的bean實作了servletcontextinitializer接口,也可以直接注冊它們。

spring boot底層使用了一個新的applicationcontext類型,用于對内嵌servlet容器的支援。embeddedwebapplicationcontext是一個特殊類型的webapplicationcontext,它通過搜尋一個單一的embeddedservletcontainerfactory bean來啟動自己。通常,tomcatembeddedservletcontainerfactory,jettyembeddedservletcontainerfactory或undertowembeddedservletcontainerfactory将被自動配置。

注:你通常不需要知道這些實作類。大多數應用将被自動配置,并根據你的行為建立合适的applicationcontext和embeddedservletcontainerfactory。

常見的servlet容器設定可以通過spring environment屬性進行配置。通常,你會把這些屬性定義到application.properties檔案中。 常見的伺服器設定包括:

server.port - 進來的http請求的監聽端口号

server.address - 綁定的接口位址

server.sessiontimeout - session逾時時間

如果需要以程式設計的方式配置内嵌的servlet容器,你可以注冊一個實作embeddedservletcontainercustomizer接口的spring bean。embeddedservletcontainercustomizer提供對configurableembeddedservletcontainer的通路,configurableembeddedservletcontainer包含很多自定義的setter方法。

如果上面的自定義手法過于受限,你可以自己注冊tomcatembeddedservletcontainerfactory,jettyembeddedservletcontainerfactory或undertowembeddedservletcontainerfactory。

很多可選的配置都提供了setter方法,也提供了一些受保護的鈎子方法以滿足你的某些特殊需求。具體參考相關文檔。

在内嵌的servlet容器中運作一個spring boot應用時(并打包成一個可執行的存檔archive),容器對jsp的支援有一些限制。

tomcat隻支援war的打包方式,不支援可執行的jar。

内嵌的jetty目前不支援jsps。

undertow不支援jsps。