Spring Boot技術指南--第四部分 Spring Boot特性
這一章我們將更深入的學習Spring Boot,學習如何使用和定製它的特性。
23 SpringApplication
SpringApplication
從main
啟動來引導Spring Boot。
public static void main(String[] args){
SpringApplication.run(MySpringConfiguration.class,args);
}
應用啟動:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: v1.5.16.RELEASE 2013-07-31 00:08:16.117 INFO 56603 --- [ main] o.s.b.s.app.SampleApplication : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb) 2013-07-31 00:08:16.166 INFO 56603 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot
[email protected]6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy 2014-03-04 13:09:54.912 INFO 41370 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080 2014-03-04 13:09:56.501 INFO 41370 --- [ main] o.s.b.s.app.SampleApplication : Started SampleApplication in 2.992 seconds (JVM running for 3.658)
23.1 啟動失敗
如果應用啟動失敗,FailureAnalyzers
會提供錯誤資訊和修復建議,例子:
*************************** APPLICATION FAILED TO START *************************** Description: Embedded servlet container failed to start. Port 8080 was already in use. Action: Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
如果沒有能處理異常的分析器,你可以通過設定debug
屬性或者允許DEBUG
日誌(org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
)來顯示完整的錯誤日誌
使用debug模式啟動:
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
23.2 定製Banner
在classpath中banner.txt
檔案,或者使用banner.location
來自定義banner檔案的地址,也可以使用classpath中的banner.gif
、banner.jpg
或者banner.png
檔案,或者設定banner.image.location
屬性來設定它,圖片會轉換為ASCII
顯示出來
在banner.txt
中可以使用的預製值:
變數 | 描述 |
---|---|
${application.version} |
MANIFEST.MF 的版本號,例如:Implementation-Version:1.0 中的1.0 |
${application.formatted-version} |
MANIFEST.MF 中版本號的顯示格式,例如v1.0 |
${spring-boot.version} |
使用的Spring Boot版本,例如:1.5.16.RELEASE |
${spring-boot-formatted-version} |
Spring Boot版本格式,例如:v1.5.16.RELEASE |
${Ansi.Name} 或者${AnsiColor.NAME} 或者${AnsiBackground.NAME} 或者${AnsiStyle.NAME} |
NAME 的ANSI轉義碼位置 |
${application.title} |
宣告在MANIFEST.MF 中的應用頭,例如Implementation-Title:MyApp ,會顯示MyApp |
注意:SpringApplication.setBanner(...)
也可以用來硬編碼的方式設定banner,使用org.springframework.boot.Banner
介面和實現自己的printBanner()
你也可以使用spring.main.banner-mode
屬性來設定是否顯示banner,或者顯示在哪裡(System.out
或者Console
),設定的值是:log
、off
springBootBanner
是一個單例項的類,用來列印banner
YAML設定off
spring:
main:
banner-mode:"off"
23.3 定製SpringApplication
例如:
public static void main(String[] args){
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
SpringApplication
構造器的引數是配置類,一般是@Configuration
註解的類
Spring Boot也提供了使用application.properties
來配置SpringApplication
,完整的配置選項,參考SpringApplicatoin Javadoc
23.4 流式API風格
如果你想構建多層ApplicationContext
,或者使用“fluent”API風格,那你就可以使用SpringApplicationBuilder
例如:
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
ApplicationContext
的限制條件:Web元件必須使一個子上下文,而且相同的Environment
使用相同的父和子上下文,參考SpringApplicationBuilder
Javadoc
23.5 應用事件和監聽
除了常見的Spring框架的事件外,比如:ContextRefreshedEvent
,SpringApplication
會觸發一些額外的應用事件。
有一些事件是在ApplicationContext
建立前就被觸發了,因此你不能在宣告的@Bean
上給它們註冊監聽,你可以使用SpringApplication.addListeners(...)
或者SpringApplicationBuilder.listeners(...)
方法給它們註冊監聽
如果你想要自動的方式註冊監聽,你可以在專案中建立META-INF/spring.factories
檔案,然後使用org.springframework.context.ApplicationListener
鍵引用你定義的監聽例如:
org.springframework.context.ApplicationListener=com.example.project.MyListener
應用事件觸發順序:
ApplicationStartingEvent
在應用開始執行時,除了註冊和例項化監聽器之外的所有處理之前觸發ApplicationEnvironmentPreparedEvent
在載入Environment
時,建立上下文之前觸發ApplicationPreparedEvent
在重新整理啟動,bean載入完成後觸發ApplicationReadyEvent
在重新整理啟動後,所有的回撥都執行完畢,通知應用準備好接受請求的時候觸發ApplicationFailedEvent
在啟動失敗有異常時觸發 一般不需要關注應用事件,但是需要知道它的存在,Spring Boot使用事件機制處理各種任務 應用事件使用的是Spring框架的釋出機制。它是確認機制的一部分,它監聽釋出到子上下文和父上下文之中的事件。這樣的結果就是,如果你的應用使用了SpringApplication
的層級結構,你的監聽器可能會收到多重的事件訊息。 如果要區分事件是本身層級的還是子層級的,就應該要求事件標明它的層級。通過實現ApplicationContextAware
或者使用@Autowired
23.6 Web環境
SpringApplication
依賴你是否是web開發環境來建立ApplicationContext
,AnnotationConfigApplicationContext
是非web環境的,AnnotationConfigEmbeddedWebApplicationContext
是web環境的。
你可以使用setWebEnvironment(boolean webEnvironment)
來指定是否是web環境,從而來控制生成的ApplicationContext
也可以使用ApplicationContext
的setApplicationContextClass(...)
來控制
一般在單元測試時使用SpringApplication
的setWebEnvironment(false)
來禁用web環境
23.7 訪問應用引數
可以使用SpringApplication.run(...)
注入org.springframework.boot.ApplicationArguments
來訪問應用的引數。ApplicationArguments
這個介面提供了String[]
有引數和無引數的解析方式訪問
import org.springframework.boot.*
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*
@Component
public class MyBean {
@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}
}
Spring Boot會給Environment
註冊CommandLinePropertySource
,也可以使用@Value
註解來注入引數
23.8 使用ApplicationRunner或者CommandLineRunner
如果你需要在SpringApplication
啟動時就執行一些指定的程式碼,你可以通過實現ApplicationRunner
或者CommandLineRunner
介面來實現,這兩個介面的工作方式一樣,都是提供一個run
方法在SpringApplication.run(...)
完成之前呼叫。
CommandLineRunner
介面提供字串陣列的方式訪問應用引數的方法,而ApplicationRunner
則是使用ApplicationArguments
介面的方式訪問應用引數
import org.springframework.boot.*
import org.springframework.stereotype.*
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
可以使用實現org.springframework.core.Ordered
介面或者使用org.springframework.core.annotation.Order
註解的方式來定義CommandLineRunnber
或者ApplicationRunner
的執行順序
23.9 應用退出
每一個SpringApplication
都會基於JVM註冊一個應用關閉鉤子程式來保證ApplicationContext
被完全關閉。所有的標準Spring 生命週期回撥,例如DisposableBean
介面、@PreDestroy
註解都可以用來實現這個目的。
另外,beans可以實現org.springframework.boot.ExitCodeGenerator
介面定製在執行SpringApplication.exit()
時執行特殊的動作,這些程式碼可以通過System.exit()
返回它的執行狀態碼
@SpringBootApplication
public class ExitCodeApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return new ExitCodeGenerator() {
@Override
public int getExitCode() {
return 42;
}
};
}
public static void main(String[] args) {
System.exit(SpringApplication
.exit(SpringApplication.run(ExitCodeApplication.class, args)));
}
}
ExitCodeGenerator
介面的實現可能會出現異常,當出現時,Spring Boot會通過getExitCode()
方法返回它的狀態碼
23.10 管理特性
通過設定spring.application.admin.enabled
屬性來開通應用的管理特性。這些暴露MBeanServer
平臺下的[SpringApplicationAdminMXBean](https://github.com/spring-projects/spring-boot/tree/v1.5.16.RELEASE/spring-boot/src/main/java/org/springframework/boot/admin/SpringApplicationAdminMXBean.java)
,可以使用這個特性遠端管理Spring Boot應用。
使用local.server.port
獲取應用的埠號
要小心使用MBean暴露的方法關閉應用
24 外部化配置
Spring Boot允許把配置外部化,這樣就可以實現同一套程式碼使用多套不同的環境配置了,你可以使用Properties檔案、YAML檔案、環境變數、命令列引數等外部化配置資訊,屬性值使用@Value
註解注入到beans,也可以使用Environment
抽象類或者使用@ConfigurationProperties
註解將值繫結到物件上
Spring Boot使用獨有PropertySource
順序的設計來繫結值,它的順序是:
~/.spring-boot-devtools.properties
中的Devtools global settings properties,如果devtools被啟用時- 在測試中的
@[TestPropertySource](https://docs.spring.io/spring/docs/4.3.19.RELEASE/javadoc-api/org/springframework/test/context/TestPropertySource.html)
註解 - 命令列引數
SPRING_APPLICATION_JSON
檔案中的屬性ServletConfig
初始化引數ServletContext
初始化引數java:comp/env
中的JNDI屬性System.getProperties()
獲取的Java系統引數- 作業系統環境變數
- 僅包含
random.*
的RandomValuePropertySource
中的引數 - 包內部的引數
- jar包外部的
application.properties
引數 - jar包內部的
application.properties
引數 @Configuration
註解的類中的@PropertySource
- 預設的配置屬性檔案(通過
SpringApplication.setDefaultProperties
指定預設配置)
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
在classpath下的application.properties
提供預設的設定,當執行一個新環境時,提供一個外部的application.properties
覆蓋預設的設定;可以使用java -jar app.jar --name="Spring"
來指定引數
SPRING_APPLICATION_JSON
可以提供命令列引數,例如:
$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar
也可以使用spring.application.json
來指定命令列引數:
$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar
或者
$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'
或者使用JNDI變數
java:com/env/spring.application.json
24.1 配置隨機值
RandomValuePropertySource
用來注入隨機值,可提供integers、longs、uuids、strings等等型別
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
random.*
的語法:OPEN value (,max) CLOSE
,OPEN,CLOSE
可以是任何的字元,value,max
是integers
24.2 應用屬性檔案
SpringApplication
從application.properties
中載入配置資訊,把它們載入到Environment
,載入路徑:
/config
目錄和子目錄- 當前目錄
- classpath下的
/config
包 - classpath根目錄
按照1,2,3,4的優先順序載入
可以使用YAML(.yml)檔案代替.properties檔案
如果不想使用application.properties
作為配置檔案,可以使用spring.config.name
指定配置檔案的名稱,也可以使用spring.config.location
指定配置檔案的路徑
$ java -jar myproject.jar --spring.config.name=myproject
或者
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
如果spring.config.location
包含有目錄,應該使用/
結束,而且是在spring.config.name
之前載入
下面是配置檔案載入順序:
file:./config/
file:./
classpath:/config/
classpath:/
配置了配置檔案路徑,它會被自動新增到預設配置檔案路徑。自定義的路徑在預設路徑之前搜尋,例如:
如果你定義了路徑classpath:/custom-config/,file:./custom-config/
,那麼搜尋順序就變成了:
file:./custom-config/
classpath:custom-config/
file:./config/
file:./
classpath:/config/
classpath:/
你可以通過在其中一個配置檔案中設定值來覆蓋載入順序。你可以在application.properties
中指定或者使用spring.config.name
指定,這些預設值可以在執行時被覆蓋
如果你使用的是環境變數,而不是系統變數,大部分的作業系統會禁止一些鍵名,但是你可以使用下劃線代替.,例如:使用SPRING_CONFIG_NAME
代替spring.config.name
24.4 定製化配置檔案
除了application.properties
之外,可以定製化配置檔案,例如application-{profile}.properties
,Environment
有一個預設的環境(default),例如:application-default.properties
定製化配置檔案和標準配置檔案application.properties
一樣被載入,定製化的配置檔案會覆蓋非定製化的值,不管它是在jar內部還是外部
24.5 佔位符
application.properties
中可以使用佔位符,例如:
app.name=MyApp
app.description=${app.name} is a Spring Boot application
24.6使用YAML代替Properties
YAML是JSON的超集,而且有非常好的層級結構,SpringApplication
支援使用YAML代替Properties,前提是要SnakeYAML包在classpath下
24.6.1 載入YAML
Spring框架提供兩個方便的類可以用來載入YAML文件,YamlPropertiesFactoryBean
會把YAML載入為Properties
,而YamlMapFactoryBean
會把YAML載入為Map
例如:
environments:
dev:
url: http://dev.bar.com
name: Devloper Setup
prod:
url: http://foo.bar.com
name: My Cool App
被翻譯成Properties:
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]
格式:
my:
servers:
- dev.bar.com
- foo.bar.com
被翻譯成Properties:
my.servers[0] = dev.bar.com
my.servers[1] = foo.bar.com
使用java.util.List
或者Set
來繫結資料,繫結到的bean需要提供setter方法:
@ConfigurationProperties(prefix="my")
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}
}
需要注意下格式:
my:
servers: dev.bar.com,foo.bar.com
是不能正常解析的
24.6.2 暴露YAML屬性
YamlPropertySourceLoader
類暴露YAML屬性到PropertySource
,可以使用@Value
來訪問它的屬性的值
24.6.3 多賬號YAML文件
例:
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
servers:
address: 192.168.1.120
上面的例子中,如果使用spring.profiles
設定了development
,則server.address
的屬性為12.0.0.1
,如果是production
,則server.address
的屬性為192.168.1.120
如果沒有明確指定定製環境,則預設的環境被啟用
server:
port: 8000
---
spring:
profiles: default
security:
user:
password: weak
24.6.4 YAML不足
YAML檔案不能通過@PropertySource
註解載入
24.6.4 YAML檔案合併
YAML最終都會被翻譯成Properties,這個過程中可能會出現重寫list屬性出錯的問題
假設MyPojo
有兩個屬性name
和description
,預設值是null
@ConfigurationProperties("foo")
public class FooProperties {
private final List<MyPojo> list = new ArrayList<>();
public List<MyPojo> getList() {
return this.list;
}
}
下面是配置:
foo:
list:
- name: my name
description: my description
---
spring:
profiles: dev
foo:
list:
- name: my another name
假如dev
未被啟用,則FooProperties.list
中包含一個MyPojo
實體,假如dev
被啟用,則list
中還是包含一個實體(nam=“my another name”,description=null)這個配置不會載入第二個MyPojo
實體,而且不會修改它們
一個多配置的集合中,只有最高優先順序的一個被使用,而且是隻有這一個
foo:
list:
- name: my name
description: my description
- name: another name
description: another description
---
spring:
profiles: dev
foo:
list:
- name: my another name
上面的例子中,假設dev
被啟用,FooProperties.list
只包含一個MyPojo
實體,name=my another name,description=null
24.7 型別安全配置屬性
使用@Value("${property}")
註解來注入配置的值有時候難於處理,尤其是有多個配置檔案或者資料有多層級的時候,Spring Boot提供強型別beans的方法來獲取和校驗配置資訊
package com.example;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("foo")
public class FooProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
public boolean isEnabled() { ... }
public void setEnabled(boolean enabled) { ... }
public InetAddress getRemoteAddress() { ... }
public void setRemoteAddress(InetAddress remoteAddress) { ... }
public Security getSecurity() { ... }
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
public String getUsername() { ... }
public void setUsername(String username) { ... }
public String getPassword() { ... }
public void setPassword(String password) { ... }
public List<String> getRoles() { ... }
public void setRoles(List<String> roles) { ... }
}
}
上面的類定義了下列屬性:
foo.enabled
,預設值false
foo.remote-address
,可以由String
強轉而來foo.security.username
,內部類security
foo.security.password
foo.security.roles
,String
的集合型別
也可以使用@EnableConfigurationProperties
註解來註冊配置資訊
@Configuration
@EnableConfigurationProperties(FooProperties.class)
public class MyConfiguration{
}
當使用@ConfigurationProperties
bean註冊這種方式時,這個bean使用的名稱類似<prefix>-<fqn>
,<prefix>
代表環境,<fqn>
是bean的全限定名,如果沒有指定<prefix>
,則全限定名被使用,例如
foo-com.example.FooProperties
儘管配置檔案載入會自動建立一個FooProperties
bean,但是建議自己建立它,使用@ConfigurationProperties
註解標註,
@Component
@ConfigurationProperties(prefix="foo")
public class FooProperties {
// ... see above
}
# application.yml
foo:
remote-address: 192.168.1.1
security:
username: foo
roles:
- USER
- ADMIN
# additional configuration as required
@Service
public class MyService {
private final FooProperties properties;
@Autowired
public MyService(FooProperties properties) {
this.properties = properties;
}
//...
@PostConstruct
public void openConnection() {
Server server = new Server(this.properties.getRemoteAddress());
// ...
}
}
24.7.1第三方配置
使用@ConfigurationProperties
在public型別有@Bean
註解的方法上,在繫結配置值給第三方元件上非常有用
@ConfigurationProperties(prefix = "bar")
@Bean
public BarComponent barComponent() {
...
}
24.7.2非嚴格的資料繫結
Spring Boot使用一些非嚴格的策略繫結Environment
屬性值到@ConfigurationProperties
bean中,因此在Environment
的屬性名和bean的屬性名之間保持精確的匹配,通常使用中劃線轉換為駝峰命名方式,例如context-path
對應contextPath
,或者使用PORT
對應port
,這些都是可以的
例如:@ConfigurationProperties
類:
@ConfigurationProperties(prefix="person")
public class OwnerProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
下面的這些屬性名都可以被使用:
屬性 | 描述 |
---|---|
person.firstName |
標準的駝峰命名法 |
person.first-name |
中劃線方式,在.properties 和.yml 檔案都推薦使用 |
person.first_name |
下劃線方法 |
PERSON_FIRST_NAME |
全大寫方式,系統環境變數建議使用 |
24.7.3 屬性轉換
Spring會嘗試強制轉換屬性值到@ConfigurationProperties
bean中定義的型別,你可以提供ConversionService
bean或者定義屬性編輯器CustomEditorConfigurer
或者定義Converters
(@ConfigurationPropertiesBinding
)來自定義型別轉換方式
24.7.4 @ConfigurationProperties
校驗
Spring Boot使用@Validated
註解嘗試校驗@ConfigurationProperties
,你可以在配置類上使用JSR-303的javax.validation
約束註解,例如:
@ConfigurationProperties(prefix="foo")
@Validated
public class FooProperties {
@NotNull
private InetAddress remoteAddress;
// ... getters and setters
}
為了校驗屬性,你必須在需要校驗的欄位上新增@Valid
來觸發校驗,例如:
@ConfigurationProperties(prefix="connection")
@Validated
public class FooProperties {
@NotNull
private InetAddress remoteAddress;
@Valid
private final Security security = new Security();
// ... getters and setters
public static class Security {
@NotEmpty
public String username;
// ... getters and setters
}
}
建立一個bean呼叫configuratonPropertiesValidator
來自定義校驗邏輯,@Bean
的方法應該是static
的,
配置屬性的校驗發生在應用生命週期的早期,@Bean
的靜態方法允許bean不例項化@Configuration
類而建立,這會避免一些安裝問題。
24.7.5 @ConfigurationProperties vs @Value
@Value
是容器的核心特性,而且它不提供安全型別配置屬性。下表是@ConfigurationProperties
和@Value
的對比
如果在你自己的元件內定義了一組配置屬性,建議使用@ConfigurationProperties
註解的POJO來組織它們,請注意因為@Value
不支援寬鬆資料繫結,所以不建議使用它來提供系統環境變數。
當你在@Value
中使用SpEL
表示式,這些表示式不會在配置檔案中被處理。
25 環境配置檔案
Spring Profiles提供分離配置檔案的方法,使得在某一環境只有一個生效,任何使用@Component
或者@Configuration
都可以使用@Profile
來限制它載入的環境
@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
也可以使用application.properties
中spring.profiles.active
屬性配置它
spring.profiles.active=dev,hsqldb
或者通過命令列指定
--spring.profiles.active=dev,hsqldb
25.1 新增活動配置
spring.profiles.active
和其他的屬性配置一樣有相關的順序,PropertySource
越高載入越早,意思是你在application.properties
中配置了啟用的配置,但是可以使用命令列來替換它
有時候給啟用的配置新增一些特殊的配置屬性比直接替換已啟用的配置更好,spring.profiles.include
可以達到此目的,SpringApplication
也提供了操作的API,setAdditionalProfiles()
例如,--spring.profiles.active=prod
,proddb
和prodmq
也會被啟用
---
my.property: fromyamlfile
---
spring.profiles: prod
spring.profiles.include:
- proddb
- prodmq
25.2 編碼設定啟用配置
可以使用SpringApplication.setAdditionalProfiles(...)
來設定啟用的配置,也可以使用ConfigurableEnvironment
介面來啟用配置
25.3 啟用的配置
啟用的配置可以是application.properties
、application.yml
或者使用@ConfigurationProperties
註解的檔案
26 日誌
Spring Boot 使用Commons Logging
作為內嵌的日誌元件,但是也留有自定義實現的介面。預設使用Java Util Logging
、Log4J2
、Logback
等配置,日誌可以配置為控制檯輸出或者檔案輸出。
預設情況下,如果你使用Starters
,Logback會被預設使用
Java有很多的日誌元件,不過不用擔心,通常不用特殊設定,Spring Boot都可以工作的很好
26.1 日誌格式化
Spring Boot預設的日誌:
2014-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
它包含的內容:
- Date and Time日期和時間 – 可分類和毫秒精度
- Log Level日誌級別 –
ERROR
、WARN
、INFO
、TRACE
- Process ID 程序ID
---
分隔符,分隔日誌訊息- Thread name 執行緒名稱 – 方括號括起來的
- Logger name 日誌元件名稱–通常是一個類名
- log message 日誌訊息
Logback沒有FATAL
級別,使用ERROR
替代
26.2 控制檯輸出
日誌預設是輸出到控制檯的,預設級別是ERROR
、WARN
、INFO
,使用--debug
開啟"debug"除錯模式
$ java -jar myapp.jar --debug
也可以在application.properties
中指定debug=true
來開啟除錯模式
當開啟除錯模式時,會輸出內嵌容器、Hibernate和SpringBoot本身的日誌。
使用--trace
或者application.properties
中設定trace=true
設定"trace"跟蹤模式,它會列印內嵌容器、Hibernate的元資料和Spring的全部資訊
26.2.1 日誌程式碼顏色
如果你的控制檯支援ANSI,則輸出程式碼顏色使日誌更易讀。設定spring.output.ansi.enabled
來開啟顏色支援
程式碼顏色使用%clr
設定,例如:
%clr(%5p)
顏色對應列表:
級別 | 顏色 |
---|---|
FATAL |
Red(紅色) |
ERROR |
Red(紅色) |
WARN |
Yellow(黃色) |
INFO |
Green(綠色) |
DEBUG |
Green(綠色) |
TRACE |
Green(綠色) |
使用自定義配置覆蓋預設:
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}
顏色和樣式支援列表:
blue
cyan
faint
green
magenta
red
yellow
26.3 輸出到檔案
預設Spring Boot僅僅將日誌輸出到控制檯,在application.properties
中設定logging.file
或者logging.path
屬性使日誌寫入到檔案中
可以使用的logging.*
屬性列表:
logging.file |
logging.path |
例子 | 描述 |
---|---|---|---|
(none) | (none) | 只輸出到控制檯 | |
Specific file指定檔案 | (none) | my.log |
寫入到指定檔案,可以是內部路徑或外部路徑檔案 |
(none) | Specific directory 指定目錄 | /var/log |
寫入到指定目錄下的spring.log 檔案中 |
預設情況下日誌檔案單個最大10MB,預設輸出ERROR
、WARN
、INFO
訊息
26.4 日誌級別
所有支援的日誌元件都可以通過在application.properties
中設定logging.level.*=LEVEL
來設定日誌級別,LEVEL支援TRACE
、DEBUG
、INFO
、WARN
、ERROR
、FATAL
、OFF
,root
日誌可以通過logging.level.root
配置,例如application.properties
中配置如下:
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
26.5 自定義日誌配置
增加日誌元件的依賴,在classpath的根目錄下增加對應的配置檔案,或者指定logging.config
指定位置,就可以實現自定義日誌元件配置
可以通過設定org.springframework.boot.logging.LoggingSystem
強迫使用某一個日誌元件,這個屬性的值是一個完整的LoggingSystem
實現類,也可以使用none
來禁用日誌
不同日誌元件載入的不同配置:
日誌元件 | 定義檔案 |
---|---|
Logback | logback-spring.xml ,logback-spring.groovy ,logback.xml ,logback.groovy |
Log4j2 | log4j2-spring.xml 或者log4j2.xml |
JDK(Java Util Logging) | logging.properties |
Spring環境變數屬性與系統屬性對應列表
Spring環境變數 | 系統屬性 | 備註 |
---|---|---|
logging.exception-conversion-word |
LOG_EXCEPTION_CONVERSION_WORD |
單詞轉換異常 |
logging.file |
LOG_FILE |
預設配置檔案定義 |
logging.path |
LOG_PATH |
預設配置檔案路徑定義 |
logging.pattern.console |
CONSOLE_LOG_PATTERN |
控制檯輸出設定,(僅 logback支援) |
logging.pattern.file |
FILE_LOG_PATTERN |
檔案輸出設定,(僅logback支援) |
logging.pattern.level |
LOG_LEVEL_PATTERN |
日誌輸出級別,預設%5p ,(僅logback支援) |
PID |
PID |
當前程序ID |
26.6 Logback擴充套件
Spring Boot支援一系列的Logback擴充套件,可以在logback-spring.xml
配置檔案中配置
不能在logback.xml
中配置它,因為它載入的太早,你需要使用logback-spring.xml
或者在logging.config
中定義的檔案中定義
不能使用Logback的掃描配置,如果你這樣做,就會報錯
ERROR in [email protected]:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in [email protected]:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]
26.6.1 特殊配置
<springProfile>
用來配置特殊的配置
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>
<springProfile name="dev, staging">
<!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>
<springProfile name="!production">
<!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>
26.6.2 環境屬性
<springProperty>
配置環境屬性
<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
<remoteHost>${fluentHost}</remoteHost>
...
</appender>
未完待續。。。