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的支持有一些限制。