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><link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/></code>。
为此,需要使用以下配置:
这里使用了<code>resourceurlencodingfilter</code>过滤器,对于thymeleaf和velocity,该过滤器已经自动配置。其他的模板引擎,可以通过<code>resourceurlprovider</code>来定义。
当资源文件自动加载的时候,javascript模块加载器会重命名静态文件。还有一种“固定”的策略来修改文件名称。
使用了上面的配置之后,当javascript加载<code>"/js/lib/"</code>目录下的文件时,将会使用一个固定的版本<code>"/v12/js/lib/mymodule.js"</code>,而其他的静态资源仍然使用<code><link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/></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。