https://yq.aliyun.com/articles/25530javascript
摘要: 1. SpringApplication SpringApplication 類是啓動 Spring Boot 應用的入口類,你能夠建立一個包含 main() 方法的類,來運行 SpringApplication.css
SpringApplication 類是啓動 Spring Boot 應用的入口類,你能夠建立一個包含 main()
方法的類,來運行 SpringApplication.run
這個靜態方法:html
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}
運行該類會有以下輸出:java
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v1.2.2.RELEASE
經過在classpath下添加一個banner.txt或設置banner.location來指定相應的文件能夠改變啓動過程當中打印的banner。若是這個文件有特殊的編碼,你可使用banner.encoding設置它(默認爲UTF-8)。git
在banner.txt中可使用以下的變量:github
${application.version}
:MANIFEST.MF 文件中的應用版本號${application.formatted-version}
${spring-boot.version}
:你正在使用的 Spring Boot 版本號${spring-boot.formatted-version}
上面這些變量也能夠經過 application.properties 來設置,後面再做介紹。web
注:若是想以編程的方式產生一個banner,可使用SpringBootApplication.setBanner(…)方法。使用org.springframework.boot.Banner接口,實現你本身的printBanner()方法。算法
若是默認的SpringApplication不符合你的口味,你能夠建立一個本地的實例並自定義它。例如,關閉banner你能夠這樣寫:spring
public static void main(String[] args) { SpringApplication app = new SpringApplication(MySpringConfiguration.class); app.setShowBanner(false); app.run(args); }
若是你須要建立一個分層的ApplicationContext(多個具備父子關係的上下文),或你只是喜歡使用流暢的構建API,你可使用SpringApplicationBuilder。SpringApplicationBuilder容許你以鏈式方式調用多個方法,包括能夠建立層次結構的parent和child方法。sql
new SpringApplicationBuilder() .showBanner(false) .sources(Parent.class) .child(Application.class) .run(args);
SpringApplication 啓動過程會觸發一些事件,你能夠針對這些事件經過 SpringApplication.addListeners(…)
添加一些監聽器:
SpringApplication 會註冊一個 shutdown hook 以便在應用退出的時候可以保證 ApplicationContext
優雅地關閉,這樣可以保證全部 Spring lifecycle 的回調都會被執行,包括 DisposableBean 接口的實現類以及 @PreDestroy
註解。
另外,你也能夠實現 org.springframework.boot.ExitCodeGenerator
接口來定義你本身的退出時候的邏輯。
一個SpringApplication
將嘗試爲你建立正確類型的ApplicationContext
。在默認狀況下,使用AnnotationConfigApplicationContext
或AnnotationConfigEmbeddedWebApplicationContext
取決於你正在開發的是不是web應用。
用於肯定一個web環境的算法至關簡單(基因而否存在某些類)。若是須要覆蓋默認行爲,你可使用setWebEnvironment(boolean webEnvironment)
。經過調用setApplicationContextClass(…)
,你能夠徹底控制ApplicationContext的類型。
注:當JUnit測試裏使用SpringApplication時,調用setWebEnvironment(false)
是可取的。
若是你想獲取應用程序傳遞給SpringApplication.run(…)
的參數,你能夠注入一個org.springframework.boot.ApplicationArguments
bean,ApplicationArguments這個接口提供了方法獲取可選的和非可選的String[]類型的參數。
import org.springframework.boot.* import org.springframework.beans.factory.annotation.* import org.springframework.stereotype.* @Component public class MyBean { @Autowired public MyBean(ApplicationArguments args) { boolean debug = args.containsOption("debug"); List<String> files = args.getNonOptionArgs(); // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"] } }
Spring Boot也會在
Environment
中注入一個CommandLinePropertySource
,這容許你使用@Value
註解注入一個應用參數。
import org.springframework.boot.* import org.springframework.stereotype.* @Component public class MyBean implements CommandLineRunner { public void run(String... args) { // Do something... } }
若是一些CommandLineRunner或者ApplicationRunner beans被定義必須以特定的次序調用,你能夠額外實現org.springframework.core.Ordered
接口或使用@Order
註解。
SpringApplication
會在JVM上註冊一個關閉的hook已確認ApplicationContext是否優雅的關閉。全部的標準的Spring生命週期回調(例如,DisposableBean
接口,或者@PreDestroy
註解)均可以使用。
另外,beans能夠實現org.springframework.boot.ExitCodeGenerator接口在應用程序結束的時候返回一個錯誤碼。
經過spring.application.admin.enabled
開啓。
Spring Boot容許你針對不一樣的環境配置不一樣的配置參數,你可使用 properties文件、YAML 文件、環境變量或者命令行參數來修改應用的配置。你能夠在代碼中使用@Value註解來獲取配置參數的值。
Spring Boot使用一個特別的PropertySource
來按順序加載配置,加載順序以下:
SPRING_APPLICATION_JSON
的屬性java:comp/env
中的 JNDI 屬性RandomValuePropertySource
,隨機值,使用 random.*
來定義SpringApplication.setDefaultProperties
設置的示例代碼:
import org.springframework.stereotype.* import org.springframework.beans.factory.annotation.* @Component public class MyBean { @Value("${name}") private String name; // ... }
你能夠在 application.properties
中定義一個 name 變量,或者在運行該 jar 時候,指定一個命令行參數(以 --
標識),例如:java -jar app.jar --name="Spring"
也可使用SPRING_APPLICATION_JSON
屬性:
$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' $ java -jar myapp.jar
在這個例子中,你能夠在Spring的Environment
中經過foo.bar來引用變量。你能夠在系統變量中定義pring.application.json
:
$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar
或者使用命令行參數:
$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'
或者使用JNDI變量:
java:comp/env/spring.application.json
RandomValuePropertySource 類型變量的示例以下:
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]}
SpringApplication 會在如下路徑查找 application.properties
並加載該文件:
/config
目錄下/config
包下另外,你也能夠經過 spring.config.location
來指定 application.properties
文件的存放路徑,或者經過 spring.config.name
指定該文件的名稱,例如:
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
或者:
$ java -jar myproject.jar --spring.config.name=myproject
即application-{profile}.properties
配置文件。
在application.properties
文件中能夠引用Environment
中已經存在的變量。
app.name=MyApp app.description=${app.name} is a Spring Boot application
你可使用 @Profile
註解來標註應用使用的環境
@Configuration @Profile("production") public class ProductionConfiguration { // ... }
可使用 spring.profiles.active
變量來定義應用激活的 profile:
spring.profiles.active=dev,hsqldb
還能夠經過 SpringApplication 來設置,調用 SpringApplication.setAdditionalProfiles(…)
代碼便可。
Spring Boot 使用 Commons Logging 做爲內部記錄日誌,你也可使用 Java Util Logging, Log4J, Log4J2 和 Logback 來記錄日誌。
默認狀況下,若是你使用了 Starter POMs ,則會使用 Logback 來記錄日誌。
默認狀況,是輸出 INFO 類型的日誌,你能夠經過設置命令行參數--debug
來設置:
$ java -jar myapp.jar --debug
若是你的終端支持 ANSI ,則日誌支持彩色輸出,這個能夠經過 spring.output.ansi.enabled
設置,可配置的值有:ALWAYS
、DETECT
、NEVER
。
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}
可選的顏色有:
能夠經過 logging.file
和 logging.path
設置日誌輸出文件名稱和路徑。
日誌級別使用 logging.level.*=LEVEL
來定義,例如:
logging.level.org.springframework.web: DEBUG logging.level.org.hibernate: ERROR
Spring Boot 經過 logging.config
來定義日誌的配置文件存放路徑,對於不一樣的日誌系統,配置文件的名稱不一樣:
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 |
對於logback-spring.xml
這類的配置,建議使用-spring
變量來加載配置文件。
Environment中能夠自定義一些屬性:
Spring Environment | System Property | Comments |
---|---|---|
logging.exception-conversion-word |
LOG_EXCEPTION_CONVERSION_WORD |
|
logging.file |
LOG_FILE |
|
logging.path |
LOG_PATH |
|
logging.pattern.console |
CONSOLE_LOG_PATTERN |
|
logging.pattern.file |
FILE_LOG_PATTERN |
|
logging.pattern.level |
LOG_LEVEL_PATTERN |
|
PID |
PID |
一個標準的@RestController
例子返回JSON數據:
@RestController @RequestMapping(value="/users") public class MyRestController { @RequestMapping(value="/{user}", method=RequestMethod.GET) public User getUser(@PathVariable Long user) { // ... } @RequestMapping(value="/{user}/customers", method=RequestMethod.GET) List<Customer> getUserCustomers(@PathVariable Long user) { // ... } @RequestMapping(value="/{user}", method=RequestMethod.DELETE) public User deleteUser(@PathVariable Long user) { // ... } }
Spring Boot爲Spring MVC提供適用於多數應用的自動配置功能。在Spring默認基礎上,自動配置添加了如下特性:
ContentNegotiatingViewResolver
和BeanNameViewResolver
beans。Converter
,GenericConverter
,Formatter
beans。HttpMessageConverters
的支持。MessageCodeResolver
。index.html
的支持。Favicon
的支持。ConfigurableWebBindingInitializer
bean若是想全面控制Spring MVC,你能夠添加本身的@Configuration
,並使用@EnableWebMvc
對其註解。若是想保留Spring Boot MVC的特性,並只是添加其餘的MVC配置(攔截器,formatters,視圖控制器等),你能夠添加本身的WebMvcConfigurerAdapter
類型的@Bean
(不使用@EnableWebMvc
註解)。
Spring MVC使用HttpMessageConverter
接口轉換HTTP請求和響應。合理的缺省值被包含的恰到好處(out of the box),例如對象能夠自動轉換爲JSON(使用Jackson庫)或XML(若是Jackson XML擴展可用則使用它,不然使用JAXB)。字符串默認使用UTF-8
編碼。
若是須要添加或自定義轉換器,你可使用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); } }
任何在上下文中出現的HttpMessageConverter
bean將會添加到converters列表,你能夠經過這種方式覆蓋默認的轉換器(converters)。
Spring MVC有一個策略,用於從綁定的errors產生用來渲染錯誤信息的錯誤碼:MessageCodesResolver。若是設置spring.mvc.message-codes-resolver.format
屬性爲PREFIX_ERROR_CODE
或POSTFIX_ERROR_CODE
(具體查看DefaultMessageCodesResolver.Format
枚舉值),Spring Boot會爲你建立一個MessageCodesResolver。
默認狀況下,Spring Boot從classpath下一個叫/static
(/public
,/resources
或/META-INF/resources
)的文件夾或從ServletContext
根目錄提供靜態內容。這使用了Spring MVC的ResourceHttpRequestHandler
,因此你能夠經過添加本身的WebMvcConfigurerAdapter
並覆寫addResourceHandlers
方法來改變這個行爲(加載靜態文件)。
@Configuration class ClientResourcesConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**") .addResourceLocations("/WEB-INF/resources/") .setCachePeriod(0); } }
在一個單獨的web應用中,容器默認的servlet是開啓的,若是Spring決定不處理某些請求,默認的servlet做爲一個回退(降級)將從ServletContext根目錄加載內容。大多數時候,這不會發生(除非你修改默認的MVC配置),由於Spring總可以經過DispatcherServlet
處理請求。
此外,上述標準的靜態資源位置有個例外狀況是Webjars內容。任何在/webjars/**
路徑下的資源都將從jar文件中提供,只要它們以Webjars的格式打包。
注:若是你的應用將被打包成jar,那就不要使用src/main/webapp
文件夾。儘管該文件夾是一個共同的標準,但它僅在打包成war的狀況下起做用,而且若是產生一個jar,多數構建工具都會靜悄悄的忽略它。
若是你想刷新靜態資源的緩存,你能夠定義一個使用HASH結尾的URL,例如:<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
。
爲此,須要使用如下配置:
spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/**
這裏使用了
ResourceUrlEncodingFilter
過濾器,對於Thymeleaf和Velocity,該過濾器已經自動配置。其餘的模板引擎,能夠經過ResourceUrlProvider
來定義。
當資源文件自動加載的時候,javascript模塊加載器會重命名靜態文件。還有一種「固定」的策略來修改文件名稱。
spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/** spring.resources.chain.strategy.fixed.enabled=true spring.resources.chain.strategy.fixed.paths=/js/lib/ spring.resources.chain.strategy.fixed.version=v12
使用了上面的配置以後,當javascript加載"/js/lib/"
目錄下的文件時,將會使用一個固定的版本"/v12/js/lib/mymodule.js"
,而其餘的靜態資源仍然使用<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
。
更多說明,參考ResourceProperties,或者閱讀該偏文章。
Spring MVC使用WebBindingInitializer
來爲一個特定的請求初始化WebDataBinder
。若是你自帶一個了一個ConfigurableWebBindingInitializer
@Bean
,Spring Boot會自動配置Spring MVC來使用它。
正如REST web服務,你也可使用Spring MVC提供動態HTML內容。Spring MVC支持各類各樣的模板技術,包括Velocity,FreeMarker和JSPs。不少其餘的模板引擎也提供它們本身的Spring MVC集成。
Spring Boot爲如下的模板引擎提供自動配置支持:
注:若是可能的話,應該忽略JSPs,由於在內嵌的servlet容器使用它們時存在一些已知的限制。
當你使用這些引擎的任何一種,並採用默認的配置,你的模板將會從src/main/resources/templates
目錄下自動加載。
注:IntelliJ IDEA根據你運行應用的方式會對classpath進行不一樣的整理。在IDE裏經過main方法運行你的應用跟從Maven或Gradle或打包好的jar中運行相比會致使不一樣的順序。這可能致使Spring Boot不能從classpath下成功地找到模板。若是遇到這個問題,你能夠在IDE裏從新對classpath進行排序,將模塊的類和資源放到第一位。或者,你能夠配置模塊的前綴爲
classpath*:/templates/
,這樣會查找classpath下的全部模板目錄。
Spring Boot默認提供一個/error
映射用來以合適的方式處理全部的錯誤,而且它在servlet容器中註冊了一個全局的 錯誤頁面。對於機器客戶端(相對於瀏覽器而言,瀏覽器偏重於人的行爲),它會產生一個具備詳細錯誤,HTTP狀態,異常信息的JSON響應。對於瀏覽器客戶端,它會產生一個白色標籤樣式(whitelabel)的錯誤視圖,該視圖將以HTML格式顯示一樣的數據(能夠添加一個解析爲erro的View來自定義它)。爲了徹底替換默認的行爲,你能夠實現ErrorController
,並註冊一個該類型的bean定義,或簡單地添加一個ErrorAttributes
類型的bean以使用現存的機制,只是替換顯示的內容。
若是在某些條件下須要比較多的錯誤頁面,內嵌的servlet容器提供了一個統一的Java DSL(領域特定語言)來自定義錯誤處理。 示例:
@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")); container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404")); container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500")); } } }
你也可使用常規的Spring MVC特性來處理錯誤,好比@ExceptionHandler
方法和@ControllerAdvice
。ErrorController
將會撿起任何沒有處理的異常。
N.B. 若是你爲一個路徑註冊一個ErrorPage
,最終被一個過濾器(Filter)處理(對於一些非Spring web框架,像Jersey和Wicket這很常見),而後過濾器須要顯式註冊爲一個ERROR
分發器(dispatcher)。
@Bean public FilterRegistrationBean myFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); ... registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); return registration; }
注:默認的FilterRegistrationBean沒有包含ERROR分發器類型。
若是你正在開發一個使用超媒體的RESTful API,Spring Boot將爲Spring HATEOAS提供自動配置,這在多數應用中都工做良好。自動配置替換了對使用@EnableHypermediaSupport
的需求,並註冊必定數量的beans來簡化構建基於超媒體的應用,這些beans包括一個LinkDiscoverer
和配置好的用於將響應正確編排爲想要的表示的ObjectMapper
。ObjectMapper能夠根據spring.jackson.*
屬性或一個存在的Jackson2ObjectMapperBuilder
bean進行自定義。
經過使用@EnableHypermediaSupport
,你能夠控制Spring HATEOAS的配置。注意這會禁用上述的對ObjectMapper
的自定義。
你能夠在方法上使用@CrossOrigin
註解,或者配置一個全局的設置:
@Configuration public class MyConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**"); } }; } }
若是喜歡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)。
@Component public class JerseyConfig extends ResourceConfig { public JerseyConfig() { register(Endpoint.class); } }
全部註冊的端點都應該被@Components和HTTP資源annotations(好比@GET)註解。
@Component @Path("/hello") public class Endpoint { @GET public String message() { return "Hello"; } }
因爲Endpoint是一個Spring組件(@Component),因此它的生命週期受Spring管理,而且你可使用@Autowired添加依賴及使用@Value注入外部配置。Jersey servlet將被註冊,並默認映射到/*。你能夠將@ApplicationPath添加到ResourceConfig來改變該映射。
默認狀況下,Jersey將在一個ServletRegistrationBean類型的@Bean中被設置成名稱爲jerseyServletRegistration的Servlet。經過建立本身的相同名稱的bean,你能夠禁止或覆蓋這個bean。你也能夠經過設置spring.jersey.type=filter
來使用一個Filter代替Servlet(在這種狀況下,被覆蓋或替換的@Bean是jerseyFilterRegistration)。該servlet有@Order屬性,你能夠經過spring.jersey.filter.order
進行設置。不論是Servlet仍是Filter註冊均可以使用spring.jersey.init.*
定義一個屬性集合做爲初始化參數傳遞過去。
這裏有一個Jersey示例,你能夠查看如何設置相關事項。
當使用內嵌的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文件中。 常見的服務器設置包括:
具體參考ServerProperties。
若是須要以編程的方式配置內嵌的servlet容器,你能夠註冊一個實現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); } }
若是上面的自定義手法過於受限,你能夠本身註冊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方法,也提供了一些受保護的鉤子方法以知足你的某些特殊需求。具體參考相關文檔。
在內嵌的servlet容器中運行一個Spring Boot應用時(並打包成一個可執行的存檔archive),容器對JSP的支持有一些限制。