第5章 Spring Boot 功能

Spring Boot 功能

      本节将会介绍Spring Boot的一些细节。 在这里,您能够了解您将要使用和自定义的主要功能。 若是尚未准备好,您可能须要阅读第二部分“入门指南”和第三部分“使用 Spring Boot”部分,以使您有基础的良好基础。css

23. SpringApplication

SpringApplication类提供了一种方便的方法来引导将从main()方法启动的Spring应用程序。 在许多状况下,您只需委派静态SpringApplication.run()方法:html

public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}

当您的应用程序启动时,您应该看到相似于如下内容:java

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v1.5.2.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.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@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)

默认状况下,将显示INFO 级别log消息,包括用户启动应用程序一些相关的启动细节。mysql

23.1 启动失败

若是您的应用程序没法启动,则注册的FailureAnalyzers会提供专门的错误消息和具体操做来解决问题。 例如,若是您在端口8080上启动Web应用程序,而且该端口已在使用中,则应该会看到相似于如下内容的内容:jquery

***************************
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.

Spring Boot提供了众多的FailureAnalyzer实现,您能够很是容易地添加本身的实现git

若是没有故障分析器(analyzers)可以处理异常,您仍然能够显示完整的自动配置报告,以更好地了解出现的问题。 为此,您须要启用debug属性或启用org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer的DEBUG日志github

例如,若是使用java -jar运行应用程序,则能够按以下方式启用 debug:web

$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

23.2 自定义Banner

能够经过在您的类路径中添加一个 banner.txt 文件,或者将banner.location设置到banner文件的位置来更改启动时打印的banner。 若是文件有一些不经常使用的编码,你能够设置banner.charset(默认为UTF-8)。除了文本文件,您还能够将banner.gif,banner.jpg或banner.png图像文件添加到您的类路径中,或者设置一个banner.image.location属性。 图像将被转换成ASCII艺术表现,并打印在任何文字banner上方。redis

您能够在banner.txt文件中使用如下占位符:算法

表23.1. banner变量

变量名 描述
${application.version} 在MANIFEST.MF中声明的应用程序的版本号。例如, Implementation-Version: 1.0 被打印为 1.0.
${application.formatted-version} 在MANIFEST.MF中声明的应用程序版本号的格式化显示(用括号括起来,以v为前缀)。 例如 (v1.0)。
${spring-boot.version} 您正在使用的Spring Boot版本。 例如1.5.2.RELEASE。
${spring-boot.formatted-version} 您正在使用格式化显示的Spring Boot版本(用括号括起来,以v为前缀)。 例如(v1.5.2.RELEASE)。
Ansi.NAME(or

{AnsiColor.NAME}, AnsiBackground.NAME,

{AnsiStyle.NAME}) 其中NAME是ANSI转义码的名称。 有关详细信息,请参阅 AnsiPropertySource
${application.title} 您的应用程序的标题在MANIFEST.MF中声明。 例如Implementation-Title:MyApp打印为MyApp。

若是要以编程方式生成banner,则可使用SpringApplication.setBanner()方法。 使用org.springframework.boot.Banner 如接口,并实现本身的printBanner() 方法。

您还可使用spring.main.banner-mode属性来决定是否必须在System.out(控制台)上打印banner,使用配置的logger(log)或不打印(off)。

23.3 定制SpringApplication

若是SpringApplication默认值不符合您的想法,您能够建立本地实例并进行自定义。 例如,关闭banner:

public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}

传递给SpringApplication的构造函数参数是spring bean的配置源。 在大多数状况下,这些将引用@Configuration类,但它们也能够引用XML配置或应扫描的包。

也可使用application.properties文件配置SpringApplication。 有关详细信息,请参见第24章“外部配置”

有关配置选项的完整列表,请参阅SpringApplication Javadoc

23.4 流式构建 API

若是您须要构建一个ApplicationContext层次结构(具备父/子关系的多个上下文),或者若是您只想使用“流式(fluent)”构建器API,则可使用SpringApplicationBuilder。

SpringApplicationBuilder容许您链式调用多个方法,并包括容许您建立层次结构的父和子方法。

例如:

new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);

建立ApplicationContext层次结构时有一些限制,例如 Web组件必须包含在子上下文中,而且相同的环境将用于父和子上下文。 有关详细信息,请参阅SpringApplicationBuilder Javadoc

23.5 Application events and listeners

除了常见的Spring Framework事件(如 ContextRefreshedEvent)以外,SpringApplication还会发送一些其余应用程序事件。

在建立ApplicationContext以前,实际上触发了一些事件,所以您不能在@Bean上注册一个监听器。 您能够经过SpringApplication.addListeners(…) 或SpringApplicationBuilder.listeners(…)方法注册它们。

若是您但愿自动注册这些侦听器,不管建立应用程序的方式如何,均可以将META-INF / spring.factories文件添加到项目中,并使用org.springframework.context.ApplicationListener引用您的侦听器。
org.springframework.context.ApplicationListener=com.example.project.MyListener

当您的应用程序运行时,事件按照如下顺序发送:

  1. ApplicationStartingEvent在运行开始时发送,但在注册侦听器和注册初始化器以后。
  2. 当已经知道要使用的上下文(context)环境,并在context建立以前,将发送ApplicationEnvironmentPreparedEvent。
  3. ApplicationPreparedEvent在启动刷新(refresh)以前发送,但在加载了bean定义以后。
  4. ApplicationReadyEvent在刷新以后被发送,而且处理了任何相关的回调以指示应用程序准备好服务请求。
  5. 若是启动时发生异常,则发送ApplicationFailedEvent。

通常您不须要使用应用程序事件,但能够方便地知道它们存在。 在内部,Spring Boot使用事件来处理各类任务。

23.6 Web 环境

SpringApplication将尝试表明您建立正确类型的ApplicationContext。 默认状况下,将使用AnnotationConfigApplicationContext或AnnotationConfigEmbeddedWebApplicationContext,具体取决于您是否正在开发Web应用程序。

用于肯定“Web环境”的算法是至关简单的(基于几个类的存在)。 若是须要覆盖默认值,可使用setWebEnvironment(boolean webEnvironment)。

也能够经过调用setApplicationContextClass() 对ApplicationContext彻底控制。

在JUnit测试中使用SpringApplication时,一般须要调用setWebEnvironment()

23.7 访问应用程序参数

若是您须要访问传递给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还将向Spring Environment 注册一个CommandLinePropertySource。 这容许您也使用@Value注解注入应用程序参数。

23.8 使用ApplicationRunner或CommandLineRunner

SpringApplication启动时若是您须要运行一些特定的代码,就能够实现ApplicationRunner或CommandLineRunner接口。 两个接口都以相同的方式工做,并提供一个单独的运行方法,这将在SpringApplication.run(…)完成以前调用。

CommandLineRunner接口提供对应用程序参数的访问(简单的字符串数组),而ApplicationRunner使用上述的ApplicationArguments接口。

@Component
public class MyBean implements CommandLineRunner {

public void run(String... args) {
// Do something...
}

}

若是定义了若干CommandLineRunner或ApplicationRunner bean,这些bean必须按特定顺序调用,您能够实现org.springframework.core.Ordered接口,也可使用org.springframework.core.annotation.Order注解。

23.9 Application exit

每一个SpringApplication将注册一个JVM关闭钩子,以确保ApplicationContext在退出时正常关闭。 可使用全部标准的Spring生命周期回调(例如DisposableBean接口或@PreDestroy注释)。

另外,若是但愿在应用程序结束时返回特定的退出代码,那么bean能够实现org.springframework.boot.ExitCodeGenerator接口。

23.10 管理功能

能够经过指定spring.application.admin.enabled属性来为应用程序启用与管理相关的功能。 这会在平台MBeanServer上暴露SpringApplicationAdminMXBean。 您可使用此功能来远程管理您的Spring Boot应用程序。 这对于任何服务包装器(service wrapper)实现也是有用的。

若是您想知道应用程序在哪一个HTTP端口上运行,请使用local.server.port键获取该属性。

启用此功能时请当心,由于MBean公开了关闭应用程序的方法。

24. 外部配置

Spring Boot容许您外部化您的配置,以便您能够在不一样的环境中使用相同的应用程序代码。 您可使用properties文件,YAML文件,环境变量和命令行参数来外部化配置。 可使用@Value注释将属性值直接注入到您的bean中,该注释可经过Spring环境(Environment)抽象访问,或经过@ConfigurationProperties绑定到结构化对象

Spring Boot使用很是特别的PropertySource命令,旨在容许合理地覆盖值。属性按如下顺序选择:

  1. 在您的HOME目录设置的Devtools全局属性(~/.spring-boot-devtools.properties)。
  2. 单元测试中的 @TestPropertySource 注解。
  3. 单元测试中的 @SpringBootTest#properties 注解属性
  4. 命令行参数。
  5. SPRING_APPLICATION_JSON 中的属性值(内嵌JSON嵌入到环境变量或系统属性中)。
  6. ServletConfig 初始化参数。
  7. ServletContext 初始化参数。
  8. 来自 java:comp/env 的JNDI属性。
  9. Java系统属性(System.getProperties())。
  10. 操做系统环境变量。
  11. RandomValuePropertySource,只有随机的属性 random.* 中。
  12. jar包外面的 Profile-specific application properties (application- {profile} .properties和YAML变体)
  13. jar包内的 Profile-specific application properties (application-{profile}.properties和YAML变体)
  14. jar包外的应用属性文件(application.properties和YAML变体)。
  15. jar包内的应用属性文件(application.properties和YAML变体)。
  16. 在@Configuration上的@PropertySource注解。
  17. 默认属性(使用SpringApplication.setDefaultProperties设置)。

一个具体的例子,假设你开发一个使用name属性的@Component:

import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {

@Value("${name}")
private String name;

// ...

}

在应用程序类路径(例如,您的jar中)中,您能够拥有一个application.properties,它为 name 属性提供了默认属性值。 在新环境中运行时,能够在您的jar外部提供一个application.properties来覆盖 name 属性; 对于一次性测试,您可使用特定的命令行开关启动(例如,java -jar app.jar –name=”Spring”)。

SPRING_APPLICATION_JSON属性能够在命令行中提供一个环境变量。 例如在UN*X shell中:

$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar

在本例中,您将在Spring环境中使用foo.bar = spam。 您也能够在系统变量中将JSON做为spring.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 。

24.1 配置随机值

RandomValuePropertySource可用于注入随机值(例如,进入秘密或测试用例)。 它能够产生整数,长整数,uuid或字符串,例如

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.int *语法是 OPEN value (,max) CLOSE ,其中OPEN,CLOSE是任何字符和值,max是整数。 若是提供max,则值为最小值,max为最大值(独占)。

24.2 访问命令行属性

默认状况下,SpringApplication将任何命令行选项参数(以’– ‘开头,例如–server.port=9000)转换为属性,并将其添加到Spring环境中。 如上所述,命令行属性始终优先于其余属性来源。

若是不但愿将命令行属性添加到环境中,可使用SpringApplication.setAddCommandLineProperties(false)禁用它们。

24.3 应用程序属性文件

SpringApplication将从如下位置的application.properties文件中加载属性,并将它们添加到Spring Environment中:

  1. 当前目录的/config子目录
  2. 当前目录
  3. classpath中/config包
  4. classpath root路径

该列表按优先级从高到低排序。

也能够使用YAML(’.yml’)文件替代“.properties”。

若是您不喜欢application.properties做为配置文件名,能够经过指定一个spring.config.name Spring environment属性来切换到另外一个。 您还可使用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.name和spring.config.location一开始就被用于肯定哪些文件必须被加载,所以必须将它们定义为环境属性(一般是OS env,system属性或命令行参数)。

若是spring.config.location包含的若是是目录而非文件,那么它们应该以/结尾(并将在加载以前附加从spring.config.name生成的名称,包括profile-specific的文件名)。 在spring.config.location中指定的文件按原样使用,不支持特定于配置文件的变体,而且将被任何特定于配置文件的属性覆盖。

默认的搜索路径 classpath:,classpath:/config,file:,file:config/ 始终会被搜索,无论spring.config.location的值如何。 该搜索路径从优先级排序从低到高(file:config/最高)。 若是您指定本身的位置,则它们优先于全部默认位置,并使用相同的从最低到最高优先级排序。 这样,您能够在application.properties(或使用spring.config.name选择的任何其余基础名称)中为应用程序设置默认值,并在运行时使用不一样的文件覆盖它,并保留默认值。

若是您使用环境(environment)变量而不是系统属性,大多数操做系统不容许使用句点分隔(period-separated)的键名称,但可使用下划线(例如,SPRING_CONFIG_NAME,而不是spring.config.name)

若是您运行在容器中,则可使用JNDI属性(在 java:comp/env 中)或servlet上下文初始化参数,而不是环境变量或系统属性。

24.4 指定配置(Profile-specific)的属性

除了application.properties文件外,还可使用命名约定application- {profile}.properties定义的指定配置文件。 环境具备一组默认配置文件,若是没有设置活动配置文件(即,若是没有显式激活配置文件,则加载了来自application-default.properties的属性)。

指定配置文件(Profile-specific)的属性从与标准application.properties相同的位置加载,指定配置( profile-specific)文件始终覆盖非指定文件,而无论指定配置文件是否在打包的jar内部或外部。

若是有几个指定配置文件,则应用最后一个配置。 例如,由spring.profiles.active属性指定的配置文件在经过SpringApplication API配置的配置以后添加,所以优先级高。

若是您在spring.config.location中指定了任何文件,则不会考虑这些特定配置(profile-specific)文件的变体。 若是您还想使用指定配置(profile-specific)文件的属性,请使用spring.config.location中的目录。

24.5 properties 文件中的占位符

application.properties中的值在使用时经过已有的环境进行过滤,以便您能够引用以前定义的值(例如,从系统属性)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application

您也可使用此技术建立现有Spring Boot属性的“简写“。 有关详细信息,请参见第72.4节“使用”短命令行参数“how-to”

24.6 使用YAML替代 Properties

YAML是JSON的超集,所以这是分层配置数据一种很是方便的格式,。 每当您的类路径中都有SnakeYAML库时,SpringApplication类将自动支持YAML做为 properties 的替代方法。

若是您使用“Starters”,SnakeYAML将经过spring-boot-starter自动提供。

24.6.1 加载 YAML

Spring Framework提供了两个方便的类,可用于加载YAML文档。 YamlPropertiesFactoryBean将YAML做为Properties加载,YamlMapFactoryBean将YAML做为Map加载。

例如,下面YAML文档:

environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App

将转化为属性:

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] dereferencers的属性键,例如YAML:

my:
servers:
- dev.bar.com
- foo.bar.com

将转化为属性:

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

要使用Spring DataBinder工具(@ConfigurationProperties作的)绑定到这样的属性,您须要有一个属性类型为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;
}
}

24.6.2 将YAML做为Spring环境中的属性文件

可使用YamlPropertySourceLoader类在Spring环境中将YAML做为PropertySource暴露出来。 这容许您使用熟悉的@Value注解和占位符语法来访问YAML属性。

24.6.3 多个YAML文件

您可使用spring.profiles键指定单个文件中的多个特定配置文件YAML文档,以指示文档什么时候应用。 例如:

server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
server:
address: 192.168.1.120

在上面的示例中,若是开发配置文件处于活动状态,则server.address属性将为127.0.0.1。 若是开发和生产配置文件未启用,则该属性的值将为192.168.1.100。

若是应用程序上下文启动时没有显式激活,默认配置文件将被激活。 因此在这个YAML中,咱们为security.user.password设置一个仅在“默认”配置文件中可用的值:

server:
port: 8000
---
spring:
profiles: default
security:
user:
password: weak

使用“spring.profiles”元素指定的Spring profiles 以选择使用 字符。 若是为单个文档指定了否认和非否认的配置文件,则至少有一个非否认配置文件必须匹配,没有否认配置文件可能匹配。

24.6.4 YAML的缺点

YAML文件没法经过@PropertySource注解加载。 所以,在须要以这种方式加载值的状况下,须要使用properties文件。

24.6.5 合并YAML列表

如上所述,任何YAML内容最终都会转换为属性。 当经过配置文件覆盖“列表”属性时,该过程可能比较直观。

例如,假设名称和描述属性默认为空的MyPojo对象。 让咱们从FooProperties中公开MyPojo的列表:

@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条目。 若是启用了配置文件,列表仍将包含一个条目(名称为“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条目(名称为“my another name”和description=null)。

24.7 类型安全的配置属性

使用@Value(“${property}”)注释来注入配置属性有时可能很麻烦,特别是若是您正在使用多个层次结构的属性或数据时。 Spring Boot提供了一种处理属性的替代方法,容许强类型Bean管理并验证应用程序的配置。

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) { ... }

}
}

上述POJO定义了如下属性:

  • foo.enabled,默认为false
  • foo.remote-address,具备能够从String强转的类型
  • foo.security.username,具备内置的“安全性(security)”,其名称由属性名称决定。 特别是返回类型并无被使用,多是SecurityProperties
  • foo.security.password
  • foo.security.roles,一个String集合

Getters和setter方法一般是必需要有的,由于绑定是经过标准的Java Beans属性描述符,就像在Spring MVC中同样。 在某些状况下可能会省略setter方法:

  • Map 只要它们被初始化,须要一个getter,但不必定是一个setter,由于它们能够被binder修改。
  • 集合和数组能够经过索引(一般使用YAML)或使用单个逗号分隔值(Properties中)来访问。 在后一种状况下,setter方法是强制性的。 咱们建议老是为这样的类型添加一个设置器。 若是您初始化集合,请确保它不是不可变的(如上例所示)
  • 若是已初始化嵌套POJO属性(如上例中的Security字段),则不须要setter方法。若是您但愿binder使用其默认构造函数即时建立实例,则须要一个setter。

有些人使用Project Lombok自动添加getter和setter。 确保Lombok不会为这种类型生成任何特定的构造函数,由于构造函将被容器自动用于实例化对象。

另请参阅@Value和@ConfigurationProperties之间的不一样

您还须要列出在@EnableConfigurationProperties注解中注册的属性类:

@Configuration
@EnableConfigurationProperties(FooProperties.class)
public class MyConfiguration {
}

@ConfigurationProperties bean以这种方式注册时,该bean将具备常规名称:<prefix> - <fqn>,其中是@ConfigurationProperties注解中指定的环境密钥前缀,是bean的全名(fully qualified name)。 若是注解不提供任何前缀,则仅使用该bean的全名。上面示例中的bean名称将是foo-com.example.FooProperties。

即便上述配置将为FooProperties建立一个常规bean,咱们建议@ConfigurationProperties仅处理环境,特别是不从上下文中注入其余bean。 话虽如此,@EnableConfigurationProperties注释也会自动应用于您的项目,以便使用@ConfigurationProperties注释的任何现有的bean都将从环境配置。 您能够经过确保FooProperties已是一个bean来快速上面的MyConfiguration

@Component
@ConfigurationProperties(prefix="foo")
public class FooProperties {

// ... see above

}

这种配置方式与SpringApplication外部的YAML配置至关:

# application.yml

foo:
remote-address: 192.168.1.1
security:
username: foo
roles:
- USER
- ADMIN

# additional configuration as required

要使用@ConfigurationProperties bean,您能够像其余任何bean同样注入它们。

@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());
// ...
}

}

使用@ConfigurationProperties还能够生成IDE能够为本身的密钥提供自动完成的元数据文件,有关详细信息,请参见附录B,配置元数据附录

24.7.1第三方配置

除了使用@ConfigurationProperties来注解类,还能够在public @Bean方法中使用它。 当您但愿将属性绑定到不受控制的第三方组件时,这可能特别有用。

@ConfigurationProperties(prefix = "bar")
@Bean
public BarComponent barComponent() {
...
}

使用 bar 前缀定义的任何属性将以与上述FooProperties示例相似的方式映射到该BarComponent bean。

24.7.2 宽松的绑定

Spring Boot使用一些宽松的规则将环境属性绑定到@ConfigurationProperties bean,所以不须要在Environment属性名称和bean属性名称之间进行彻底匹配。 经常使用的例子是这样有用的:虚分离(例如上下文路径绑定到contextPath)和大写(例如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;
}

}

可使用如下属性名称:

表格 24.1. relaxed binding

Property Note
person.firstName 标准骆峰命名法。
person.first-name 虚线符号,推荐用于.properties和.yml文件。
person.first_name 下划线符号,用于.properties和.yml文件的替代格式。
PERSON_FIRST_NAME 大写格式 推荐使用系统环境变量时。

24.7.3属性转换

当Spring绑定到@ConfigurationProperties bean时,Spring将尝试将外部应用程序属性强制为正确的类型。 若是须要自定义类型转换,您能够提供ConversionService bean(使用bean id conversionService)或自定义属性编辑器(经过CustomEditorConfigurer bean)或自定义转换器(使用注释为@ConfigurationPropertiesBinding的bean定义)。

因为在应用程序生命周期期间很是早请求此Bean,请确保限制ConversionService正在使用的依赖关系。 一般,您须要的任何依赖关系可能没法在建立时彻底初始化。 若是配置密钥强制不须要,只需依赖使用@ConfigurationPropertiesBinding限定的自定义转换器,就能够重命名自定义ConversionService。

24.7.4 @ConfigurationProperties验证

当Spring的@Validated注释解时,Spring Boot将尝试验证@ConfigurationProperties类。 您能够直接在配置类上使用JSR-303 javax.validation约束注释。 只需确保您的类路径中符合JSR-303实现,而后在您的字段中添加约束注释:

@ConfigurationProperties(prefix="foo")
@Validated
public class FooProperties {

@NotNull
private InetAddress remoteAddress;

// ... getters and setters

}

为了验证嵌套属性的值,您必须将关联字段注释为@Valid以触发其验证。 例如,基于上述FooProperties示例:

@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

}

}

您还能够经过建立名为configurationPropertiesValidator的bean定义来添加自定义的Spring Validator。 @Bean方法应声明为static。 配置属性验证器在应用程序的生命周期早期建立,并声明@Bean方法,由于static容许建立bean,而无需实例化@Configuration类。 这避免了早期实例化可能引发的任何问题。 这里有一个属性验证的例子,因此你能够看到如何设置。

spring-boot-actuator模块包括一个暴露全部@ConfigurationProperties bean的端点。 只需将您的Web浏览器指向/configprops 或使用等效的JMX端点。 请参阅生产就绪功能 细节。

24.7.5 @ConfigurationProperties 对比 @Value

@Value是核心容器功能,它不提供与类型安全配置属性相同的功能。 下表总结了@ConfigurationProperties和@Value支持的功能:

功能 @ConfigurationProperties @Value
Relaxed binding Yes No
Meta-data support Yes No
SpEL evaluation No Yes

若是您为本身的组件定义了一组配置密钥,咱们建议您将其分组到使用@ConfigurationProperties注释的POJO中。 还请注意,因为@Value不支持宽松的绑定,若是您须要使用环境变量提供值,那么它不是一个很好的选择。

最后,当您能够在@Value中编写一个Spel表达式时,这些表达式不会从应用程序属性文件中处理。

25. 配置文件(Profiles)

Spring 配置文件提供了将应用程序配置隔离的方法,使其仅在某些环境中可用。 任何@Component或@Configuration均可以使用@Profile进行标记,以限制其在何时加载:

@Configuration
@Profile("production")
public class ProductionConfiguration {

// ...

}

通常,您可使用spring.profiles.active Environment属性来指定哪些配置文件处于激活状态。 您能够以任何方式指定属性,例如,您能够将其包含在您的application.properties中:

spring.profiles.active=dev,hsqldb

或者使用命令行--spring.profiles.active=dev,hsqldb在命令行中指定。

25.1添加激活配置文件

spring.profiles.active属性遵循与其余属性相同的优先级规则,PropertySource最高。这意味着您能够在application.properties中指定活动配置文件,而后使用命令行开关替换它们。

有时,将特定于配置文件的属性添加到激活的配置文件而不是替换它们是有用的。 spring.profiles.include属性可用于无条件添加激活配置文件。 SpringApplication入口点还具备用于设置其余配置文件的Java API(即,在由spring.profiles.active属性激活的那些配置文件之上):请参阅setAdditionalProfiles()方法。

例如,当使用开关 -spring.profiles.active=prod 运行具备如下属性的应用程序时,proddb和prodmq配置文件也将被激活:

---
my.property: fromyamlfile
---
spring.profiles: prod
spring.profiles.include:
- proddb
- prodmq

请记住,能够在YAML文档中定义spring.profiles属性,以肯定此特定文档什么时候包含在配置中。 有关详细信息,请参见第72.7节“根据环境更改配置”

25.2 以编程方式设置配置文件

您能够经过在应用程序运行以前调用SpringApplication.setAdditionalProfiles(…)以编程方式设置激活配置文件。 也可使用Spring的ConfigurableEnvironment接口激活配置文件。

25.3 配置文件指定的配置文件

经过@ConfigurationProperties引用的application.properties(或application.yml)和文件的配置文件特定变体都被视为加载文件。 有关详细信息,请参见第24.4节指定配置(Profile-specific)的属性”

26. 日志

Spring Boot使用Commons Logging进行全部内部日志记录,但使基础日志实现开放。 默认配置提供了Java Util LoggingLog4J2Logback。 在每种状况下,记录器都预先配置为使用控制台输出和可选文件输出均可用。

默认状况下,若是使用’Starters’,将会使用Logback。 还包括适当的Logback路由,以确保使用Java Util Logging,Commons Logging,Log4J或SLF4J的依赖库都能正常工做。

有不少可用于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: [/*]

输出如下项目:

  • 日期和时间 - 毫秒精度而且容易排序。
  • 日志级别 - ERROR, WARN, INFO, DEBUG, TRACE.
  • 进程ID。
  • —分隔符来区分实际日志消息的开始。
  • 线程名称 - 括在方括号中(可能会截断控制台输出)。
  • 记录器名称 - 这一般是源类名(一般缩写)。
  • 日志消息。

Logback没有FATAL级别(对映ERROR)

26.2 控制台输出

默认的日志配置会在控制台显示消息。 默认状况下会记录ERROR,WARN和INFO级别的消息。 您还能够经过–debug启动您的应用程序来启用“debug”模式。

$ java -jar myapp.jar --debug

您还能够在application.properties中指定debug=true。

当启用debug模式时,配置核心记录器(嵌入式容器,Hibernate和Spring Boot)的选择能够输出更多信息。 启用debug 模式不会将应用程序配置为使用DEBUG级别记录全部消息。

或者,您可使用–trace启动应用程序(或在您的application.properties中为trace=true)启用“trace”模式。 这将为核心记录器(嵌入式容器,Hibernate模式生成和整个Spring组合)启用trace日志。

26.2.1 日志颜色输出

若是您的终端支持ANSI,颜色输出能够增长可读性。 您能够将spring.output.ansi.enabled设置为支持的值来覆盖自动检测。

使用%clr关键字配置颜色编码。 在最简单的形式下,转换器将根据日志级别对输出进行着色,例如:

%clr(%5p)

日志级别映射到颜色以下:

  • blue
  • cyan
  • faint
  • green
  • magenta
  • red
  • yellow

26.3 文件输出

默认状况下,Spring Boot将仅将日志输出到控制台,不会写到文件。 若是要将控制台上的日志输出到日志文件,则须要设置logging.file或logging.path属性(例如在application.properties中)。

下表显示了如何一块儿使用logging.*属性:

表26.1 Logging属性

logging.file logging.path Example Description
(none) (none)   仅控制台输出
Specific file (none) my.log 写入指定的日志文件。 名称能够是确切的位置或相对于当前目录。
(none) Specific directory /var/log 将spring.log写入指定的目录。 名称能够是确切的位置或相对于当前目录。

日志文件将在10 MB时滚动输出到文件,默认状况下会记录控制台输出,ERROR,WARN和INFO级别的消息。

日志记录系统在应用程序生命周期早期初始化,而且在经过@PropertySource注解加载的属性文件中将不会找到log属性

日志属性独立于实际的日志记录基础结构。 所以,特定配置key(如Logback的logback.configurationFile)不受Spring Boot管理。

26.4 日志级别

全部支持的日志记录系统均可以在Spring Environment 中设置log级别(例如在application.properties中),使用‘logging.level.*=LEVEL’,其中’LEVEL’是TRACE,DEBUG,INFO,WARN,ERROR,FATAL, OFF之一。 可使用logging.level.root配置根记录器。 示例application.properties:

logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

默认状况下,Spring Boot会从新启动Thymeleaf INFO消息,以便它们以DEBUG级别进行记录。 这有助于下降标准日志输出中的噪音。 有关如何在本身的配置中应用重映射的详细信息,请参阅LevelRemappingAppender

26.5 自定义日志配置

能够经过在类路径中包含适当的库来激活各类日志系统,并经过在类路径的根目录中提供合适的配置文件,或在Spring Environment属性logging.config指定的位置进一步配置。

您可使用org.springframework.boot.logging.LoggingSystem系统属性强制Spring Boot使用特定的日志记录系统。该值应该是LoggingSystem实现的全名。 您还可使用none值彻底禁用Spring Boot的日志记录配置。

因为在建立ApplicationContext以前初始化日志,所以没法在Spring @Configuration文件中控制@PropertySources的日志记录。 系统属性和常规的Spring Boot外部配置文件工做正常。

根据您的日志记录系统,将会加载如下文件:

Logging System Customization
Logback logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging) logging.properties

若是可能,咱们建议您使用-spring变体进行日志记录配置(例如使用logback-spring.xml而不是logback.xml)。 若是使用标准配置位置,则Spring没法彻底控制日志初始化。

Java Util Logging存在已知的类加载问题,从“可执行jar”运行时会致使问题。 咱们建议您尽量避免。

帮助定制一些其余属性从Spring环境转移到系统属性:

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 在控制台上使用的日志模式(stdout)。 (仅支持默认logback设置。)
logging.pattern.file FILE_LOG_PATTERN 在文件中使用的日志模式(若是LOG_FILE已启用)。 (仅支持默认logback设置。)
logging.pattern.level LOG_LEVEL_PATTERN 用于呈现日志级别的格式(默认%5p)。 (仅支持默认logback设置。)
PID PID 当前进程ID(若是可能的话,当未被定义为OS环境变量时被发现)。

支持的全部日志记录系统在分析其配置文件时能够查看系统属性。 有关示例,请参阅spring-boot.jar中的默认配置。

若是要在logging属性中使用占位符,则应使用Spring Boot的语法,而不是底层框架的语法。 值得注意的是,若是您使用Logback,您应该使用:做为属性名称与其默认值之间的分隔符,而不是:-

您能够经过覆盖LOG_LEVEL_PATTERN(或Logback的log.pattern.level)来添加MDC和其余ad-hoc内容到日志行。 例如,若是使用logging.pattern.level = user:%X {user}%5p,则默认日志格式将包含“user”的MDC条目(若是存在)。

2015-09-30 12:30:04.031 user:juergen INFO 22174 --- [  nio-8080-exec-0] demo.Controller
Handling authenticated request

26.6 Logback扩展

Spring Boot包括大量的Logback扩展,能够帮助您进行高级配置。 您能够在logback-spring.xml配置文件中使用这些扩展。

您不能在标准logback.xml配置文件中使用扩展名,由于其加载时间太早。 您须要使用logback-spring.xml或定义logging.config属性。

扩展名不能与Logback的配置扫描一块儿使用。 若是您尝试这样作,对配置文件进行更改将致使相似于如下记录之一的错误:

ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]

26.6.1 指定配置文件配置

<springProfile>标签容许您根据活动的Spring配置文件可选地包含或排除配置部分。 配置文件部分支持<configuration>元素在任何位置。 使用name属性指定哪一个配置文件接受配置。 可使用逗号分隔列表指定多个配置文件。

<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 环境属性

标签容许您从Spring环境中显示属性,以便在Logback中使用。 若是您在logback中访问application.properties文件中的值,这将很是有用。 标签的工做方式与Logback标准的标签相似,但不是指定直接值,而是指定属性的来源(来自Environment)。 若是须要将属性存储在本地范围之外的位置,则可使用scope属性。 若是在环境中未设置属性的状况下须要备用值,则可使用defaultValue属性。

<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>

RelaxedPropertyResolver用于访问Environment属性。 若是以虚线表示法(my-property-name)指定源,则将尝试全部宽松的变体(myPropertyName,MY_PROPERTY_NAME等)。

27. 开发Web应用程序

Spring Boot很是适合Web应用程序开发。 您可使用嵌入式Tomcat,Jetty或Undertow轻松建立自包含的HTTP服务器。 大多数Web应用程序将使用spring-boot-starter-web模块快速启动和运行。

若是您还没有开发Spring Boot Web应用程序,则能够按照“Hello World!”示例进行操做。 在“入门”部分中的示例。

27.1 “Spring Web MVC框架”

Spring Web MVC框架(一般简称为“Spring MVC”)是一个丰富的“模型视图控制器”Web框架。 Spring MVC容许您建立特殊的@Controller或@RestController bean来处理传入的HTTP请求。 您的控制器中的方法将使用@RequestMapping注释映射到HTTP。

如下是@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 MVC是Spring Framework的一部分,详细信息可在参考文档中找到。 Spring.io/guide中还有几个指南可供Spring MVC使用。

27.1.1 Spring MVC自动配置

Spring Boot提供了适用于大多数应用程序的Spring MVC的自动配置。

自动配置在Spring的默认值之上添加如下功能:

  • 包含ContentNegotiatingViewResolver和BeanNameViewResolver bean。
  • 支持提供静态资源,包括对WebJars的支持(见下文)。
  • Converter,GenericConverter,Formatter beans的自动注册。
  • 支持HttpMessageConverters(见下文)。
  • 自动注册MessageCodesResolver(见下文)。
  • 静态index.html支持。
  • 自定义Favicon支持(见下文)。
  • 自动使用ConfigurableWebBindingInitializer bean(见下文)。

若是要保留Spring Boot MVC功能,而且您只须要添加其余MVC配置(interceptors, formatters, view, controllers等),你能够添加本身的WebConfigurerAdapter类型的@Configuration类,但不能使用@EnableWebMvc。 若是要提供自定义的RequestMappingHandlerMapping,RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver实例,您能够声明一个提供此类组件的WebMvcRegistrationsAdapter实例。

若是要彻底控制Spring MVC,可使用@EnableWebMvc添加您本身的@Configuration注释。

27.1.2 HttpMessageConverters

Spring MVC使用HttpMessageConverter接口转换HTTP请求和响应。 包括一些开箱即用的合理配置,例如对象能够自动转换为JSON(使用Jackson库)或XML(使用Jackson XML扩展,若是可用,不然使用JAXB)。 字符串默认使用UTF-8进行编码。

若是须要添加或自定义转换器,可使用Spring Boot HttpMessageConverter类:

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将被添加到转换器列表中。 您也能够以这种方式覆盖默认转换器。

27.1.3 自定义JSON序列化器和反序列化器

若是您使用Jackson序列化和反序列化JSON数据,则可能须要编写本身的JsonSerializer和JsonDeserializer类。 自定义序列化程序一般经过一个模块注册到Jackson,可是Spring Boot提供了一个备用的@JsonComponent注释,能够更容易地直接注册Spring Bean。

您能够直接在JsonSerializer或JsonDeserializer实现中使用@JsonComponent。 您也能够将它用于包含序列化器/解串器的类做为内部类。 例如:

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

public static class Serializer extends JsonSerializer<SomeObject> {
// ...
}

public static class Deserializer extends JsonDeserializer<SomeObject> {
// ...
}

}

ApplicationContext中的全部@JsonComponent bean将自动注册到Jackson,而且因为@JsonComponent是使用@Component进行元注解的,因此常规的组件扫描规则适用。

Spring Boot还提供了JsonObjectSerializerJsonObjectDeserializer基类,它们在序列化对象时为标准的Jackson版本提供了有用的替代方法。 有关详细信息,请参阅Javadoc。

27.1.4 MessageCodesResolver

Spring MVC有一个生成错误代码的策略,用于从绑定错误中提取错误消息:MessageCodesResolver。 Spring Boot将为您建立一个错误代码,若是您设置spring.mvc.message-codes-resolver.format属性PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE(请参阅DefaultMessageCodesResolver.Format中的枚举)。

27.1.5 静态内容

默认状况下,Spring Boot将从类路径或ServletContext的根目录中的名为/static(或/ public或/resources或/META-INF/resources)的目录提供静态内容。 它使用Spring MVC中的ResourceHttpRequestHandler,所以您能够经过添加本身的WebMvcConfigurerAdapter并覆盖addResourceHandlers方法来修改该行为。

在独立的Web应用程序中,来自容器的默认servlet也被启用,而且做为后备,若是Spring决定不处理它,则从ServletContext的根目录提供内容。 大多数状况下,这不会发生(除非您修改默认的MVC配置),由于Spring将始终可以经过DispatcherServlet处理请求。

默认状况下,资源映射到/ ,但能够经过spring.mvc.static-path-pattern调整。 例如,将全部资源重定位到 /resources/能够配置以下:

spring.mvc.static-path-pattern=/resources/**

您还可使用spring.resources.static-locations(使用目录位置列表替换默认值)来自定义静态资源位置。 若是这样作,默认欢迎页面检测将切换到您的自定义位置,所以,若是在启动时任何位置都有一个index.html,它将是应用程序的主页。

除了上述“标准”静态资源位置以外,还提供了一个特殊状况,用于Webjars内容。 任何具备/ webjars / **中路径的资源都将从jar文件中提供,若是它们以Webjars格式打包。

若是您的应用程序将被打包为jar,请不要使用 src/main/webapp 目录。 虽然这个目录是一个通用的标准,但它只适用于war包,若是生成一个jar,它将被大多数构建工具忽略。

Spring Boot还支持Spring MVC提供的高级资源处理功能,容许使用例如缓存静态资源或使用Webjars的版本无关的URL。

要为Webjars使用版本无关的URL,只需添加webjars-locator依赖关系便可。而后声明您的Webjar,以jQuery为例,如“/webjars/jquery/dist/jquery.min.js”,这将产生“/webjars/jquery/xyz/dist/jquery.min.js”,其中xyz是Webjar版本 。

若是您使用JBoss,则须要声明webjars-locator-jboss-vfs依赖关系而不是webjars-locator; 不然全部Webjars都将解析为404。

要使用缓存清除功能,如下配置将为全部静态资源配置缓存清除解决方案,从而有效地在URL中添加内容哈希值,例如:

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**

连接资源在运行时在模板中被重写,这归功于自动配置为Thymeleaf和FreeMarker的ResourceUrlEncodingFilter。 使用JSP时,应手动声明此过滤器。 其余模板引擎如今不会自动支持,但可使用自定义模板宏/帮助程序和使用ResourceUrlProvider

当使用例如JavaScript模块加载器动态加载资源时,重命名文件不是一个选项。这就是为何其余策略也获得支持并能够合并的缘由。 “固定(fixed)”策略将在URL中添加静态版本字符串,而不更改文件名:

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

使用此配置,位于“/js/lib/”下的JavaScript模块将使用固定版本策略“/v12/js/lib/mymodule.js”,而其余资源仍将使用内容。

有关更多支持的选项,请参阅ResourceProperties

此功能已在专门的博客文章和Spring Framework参考文档中进行了详细描述。

27.1.6 自定义图标

Spring Boot在配置的静态内容位置和类路径的根目录(按顺序)中查找favicon.ico。 若是文件存在,它将被自动用做应用程序的图标。

27.1.7 ConfigurableWebBindingInitializer

Spring MVC使用WebBindingInitializer为特定请求初始化WebDataBinder。 若是您用@Bean建立本身的ConfigurableWebBindingInitializer @Bean,Spring Boot将自动配置Spring MVC以使用它。

27.1.8 模板引擎

除了REST Web服务,您还可使用Spring MVC来提供动态HTML内容。 Spring MVC支持各类模板技术,包括Thymeleaf,FreeMarker和JSP。 许多其余模板引擎也运行本身的Spring MVC集成。

Spring Boot包括对如下模板引擎的自动配置支持:

若是可能,应避免使用JSP,当使用嵌入式servlet容器时,JSP有几个已知的限制

当您使用默认配置的模板引擎之一时,您的模板将从 src/main/resources/templates 自动获取。

IntelliJ IDEA根据运行应用程序的方式对类路径进行不一样的排序。 经过main方法在IDE中运行应用程序将致使使用Maven或Gradle打包的jar运行应用程序时的不一样顺序。这可能会致使Spring Boot找不到类路径上的模板。 若是您受此问题的影响,您能够从新排序IDE中的类路径,以放置模块的类和资源。 或者,您能够配置模板前缀以搜索类路径上的每一个模板目录:classpath*:/templates/

27.1.9 错误处理

默认状况下,Spring Boot提供 /error 映射,以合理的方式处理全部错误,并在servlet容器中注册为“global”错误页面。 对于机器客户端,它将产生JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。 对于浏览器客户端,有一个’whitelabel’错误视图,以HTML格式呈现相同的数据(定制它只需添加一个解析“error”的视图)。 要彻底替换默认行为,您能够实现ErrorController并注册该类型的bean定义,或者简单地添加一个类型为ErrorAttributes的bean来使用现有机制,但只是替换内容。

BasicErrorController能够用做自定义ErrorController的基类。 若是要添加新内容类型的处理程序(默认状况下是专门处理text/html并为其余内容提供备选),这一点尤为有用。 要作到这一点,只需扩展BasicErrorController并添加一个带有@RequestMapping的公共方法,并建立一个新类型的bean。

您还能够定义一个@ControllerAdvice来自定义为特定控制器 and/or 异常类型返回的JSON文档。

@ControllerAdvice(basePackageClasses = FooController.class)
public class FooControllerAdvice extends ResponseEntityExceptionHandler {

@ExceptionHandler(YourException.class)
@ResponseBody
ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
}

private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}

}

在上面的示例中,若是由FooController在同一个包中定义的控件抛出了YourException,则将使用CustomerErrorType POJO的json表示法而不是ErrorAttributes表示形式。

自定义错误页面

若是要显示给定状态代码的自定义HTML错误页面,请将文件添加到/error文件夹。 错误页面能够是静态HTML(即添加在任何静态资源文件夹下)或使用模板构建。 该文件的名称应该是确切的状态代码或一个序列掩码。

例如,要将404映射到静态HTML文件,您的文件夹结构将以下所示:

src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>

要使用FreeMarker模板映射全部5xx错误,使用以下结构:

src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.ftl
+- <other templates>

对于更复杂的映射,您还能够添加实现ErrorViewResolver接口的bean。

public class MyErrorViewResolver implements ErrorViewResolver {

@Override
public ModelAndView resolveErrorView(HttpServletRequest request,
HttpStatus status, Map<String, Object> model) {
// Use the request or status to optionally return a ModelAndView
return ...
}

}

您还可使用常规的Spring MVC功能,如@ExceptionHandler方法@ControllerAdvice。 而后,ErrorController将接收任何未处理的异常。

映射Spring MVC以外的错误页面

对于不使用Spring MVC的应用程序,可使用ErrorPageRegistrar接口来直接注册ErrorPages。这个抽象直接与底层的嵌入式servlet容器一块儿工做,即便没有Spring MVC DispatcherServlet也能够工做。

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
return new MyErrorPageRegistrar();
}

// ...

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
}

}

N.B. 若是您注册一个最终由Filter过滤的路径的ErrorPage(例如,像一些非Spring Web框架,例如Jersey和Wicket同样),则必须将Filter显式注册为ERROR dispatcher,例如。

@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter());
...
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
return registration;
}

(默认的FilterRegistrationBean不包括ERROR dispatcher 类型)。

WebSphere Application Server上的错误处理

当部署到servlet容器时,Spring Boot会使用其错误页面过滤器将具备错误状态的请求转发到相应的错误页面。 若是响应还没有提交,则该请求只能转发到正确的错误页面。 默认状况下,WebSphere Application Server 8.0及更高版本在成功完成servlet的服务方法后提交响应。 您应该经过将com.ibm.ws.webcontainer.invokeFlushAfterService设置为false来禁用此行为

27.1.10 Spring HATEOAS

若是您正在开发一种利用超媒体的RESTful API,Spring Boot能够为Spring HATEOAS提供自动配置,适用于大多数应用程序。 自动配置取代了使用@EnableHypermediaSupport的需求,并注册了一些Bean,以便轻松构建基于超媒体的应用程序,包括LinkDiscoverers(用于客户端支持)和配置为将响应正确地组织到所需表示中的ObjectMapper。 ObjectMapper将根据spring.jackson。*属性或Jackson2ObjectMapperBuilder bean(若是存在)进行自定义。

您可使用@EnableHypermediaSupport控制Spring HATEOAS配置。 请注意,这将禁用上述ObjectMapper定制。

27.1.11 CORS 支持

跨原始资源共享(CORS)是大多数浏览器实现的W3C规范,容许您以灵活的方式指定什么样的跨域请求被受权,而不是使用一些不太安全和不太强大的方法,如IFRAME或JSONP。

从版本4.2起,Spring MVC支持CORS开箱即用。 在Spring Boot应用程序中的controller方法使用@CrossOrigin注解的CORS配置不须要任何特定的配置。 能够经过使用自定义的addCorsMappings(CorsRegistry)方法注册WebMvcConfigurer bean来定义全局CORS配置:

@Configuration
public class MyConfiguration {

@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}

27.2 JAX-RS 和 Jersey

若是您喜欢JAX-RS编程模型的REST endpoints ,您可使用一个可用的实现而不是Spring MVC。 若是您刚刚在应用程序上下文中注册了一个@Bean的Servlet或Filter,那么Jersey 1.x和Apache CXF的功能很是出色。 Jersey2.x有一些本地Spring支持,因此咱们也提供自动配置支持它在Spring Boot与启动器。

要开始使用Jersey 2.x,只需将spring-boot-starter-jersey做为依赖项,而后您须要一个@Bean类型ResourceConfig,您能够在其中注册全部端点(endpoints):

@Component
public class JerseyConfig extends ResourceConfig {

public JerseyConfig() {
register(Endpoint.class);
}

}

Jersey对扫描可执行档案的包是至关有限的。 例如,当运行可执行的war文件时,它没法扫描在WEB-INF/classes中找到的包中的端点(endpoints)。 为了不这种限制,不该使packages方法,而且应使用上述寄存器方法单独注册(register)端点。

您还能够注册任意数量的ResourceConfigCustomizer的实现bean,以实现更高级的自定义。

全部注册的端点都应为具备HTTP资源注解(@GET等)的@Components,例如。

@Component
@Path("/hello")
public class Endpoint {

@GET
public String message() {
return "Hello";
}

}

因为Endpoint是一个Spring @Component,因此Spring的生命周期由Spring管理,您可使用@Autowired依赖关系并使用@Value注入外部配置。 默认状况下,Jersey servlet将被注册并映射到/ *。 您能够经过将@ApplicationPath添加到ResourceConfig来更改映射。

默认状况下,Jersey将经过@Bean以名为jerseyServletRegistration的ServletRegistrationBean类型在Servlet进行设置。 默认状况下,servlet将被初始化,可是您可使用spring.jersey.servlet.load-on-startup进行自定义。您能够经过建立一个本身的同名文件来禁用或覆盖该bean。 您也能够经过设置spring.jersey.type = filter(在这种状况下,@Bean来替换或替换为jerseyFilterRegistration),使用Filter而不是Servlet。 servlet有一个@Order,您可使用spring.jersey.filter.order设置。 可使用spring.jersey.init.* 给出Servlet和过滤器注册的init参数,以指定属性的映射。

有一个Jersey示例,因此你能够看到如何设置。 还有一个Jersey1.x示例。 请注意,在Jersey1.x示例中,spring-boot maven插件已经被配置为打开一些Jersey jar,以便它们能够被JAX-RS实现扫描(由于示例要求它们在Filter注册中进行扫描) 。 若是您的任何JAX-RS资源做为嵌套的jar打包,您可能须要执行相同操做。

27.3 嵌入式servlet容器支持

Spring Boot包括对嵌入式Tomcat,Jetty和Undertow服务器的支持。 大多数开发人员将简单地使用适当的“Starter”来获取彻底配置的实例。 默认状况下,嵌入式服务器将监听端口8080上的HTTP请求。

若是您选择在CentOS上使用Tomcat,请注意,默认状况下,临时目录用于存储已编译的JSP,文件上传等。当您的应用程序正在运行致使故障时,该目录可能会被tmpwatch删除。 为了不这种状况,您可能须要自定义tmpwatch配置,以便tomcat.*目录不被删除,或配置server.tomcat.basedir,以便嵌入式Tomcat使用不一样的位置

27.3.1 Servlets, Filters 和 listeners

当使用嵌入式servlet容器时,可使用Spring bean或经过扫描Servlet组件(例如HttpSessionListener)注册Servlet规范中的Servlet,过滤器和全部监听器。

将Servlets,过滤器和监听器注册为Spring bean

任何Servlet,Filter或Servlet Listener 实例都会做为Spring bean注册到嵌入式容器中。 能够很是方便地在配置过程当中引用您的application.properties中的值。

默认状况下,若是容器中只包含一个Servlet,它将映射到/。 在多个Servlet bean的状况下,bean名称将做为路径前缀。 过滤器(Filters)将映射到/*,默认过滤全部请求。

若是基于惯例的映射不够灵活,可使用ServletRegistrationBean,FilterRegistrationBean和ServletListenerRegistrationBean类来完成控制。

27.3.2 Servlet Context 初始化

嵌入式servlet容器不会直接执行Servlet 3.0+ javax.servlet.ServletContainerInitializer接口或Spring的org.springframework.web.WebApplicationInitializer接口。 这样设计的目的旨在下降在war中运行的第三方库破坏Spring Boot应用程序的风险。

若是您须要在Spring Boot应用程序中执行servlet context 初始化,则应注册一个实现org.springframework.boot.context.embedded.ServletContextInitializer接口的bean。 单个onStartup方法提供对ServletContext的访问,而且若是须要,能够轻松地用做现有WebApplicationInitializer的适配器。

扫描Servlet,过滤器和监听器

使用嵌入式容器时,可使用@ServletComponentScan启用@WebServlet,@WebFilter和@WebListener注解类的自动注册。

@ServletComponentScan在独立容器中不起做用,在该容器中将使用容器的内置发现机制。

27.3.3 EmbeddedWebApplicationContext

在Spring Boot引导下,将会使用一种新类型的ApplicationContext来支持嵌入式的servlet容器。 EmbeddedWebApplicationContext是一种特殊类型的WebApplicationContext,它经过搜索单个EmbeddedServletContainerFactory bean来引导自身。 一般,TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory将被自动配置。

您一般不须要知道这些实现类。 大多数应用程序将被自动配置,并将表明您建立适当的ApplicationContext和EmbeddedServletContainerFactory。

27.3.4 定制嵌入式servlet容器

可使用Spring Environment属性配置常见的servlet容器设置。 一般您能够在application.properties文件中定义属性。

经常使用服务器设置包括:

  • 网络设置:侦听端口的HTTP请求(server.port),接口地址绑定到server.address等。
  • 会话设置:会话是否持久化(server.session.persistence),会话超时(server.session.timeout),会话数据的位置(server.session.store-dir)和session-cookie配置(server.session.cookie.*)。
  • 错误管理:错误页面的位置(server.error.path)等
  • SSL
  • HTTP压缩

Spring Boot尽量地尝试公开常见设置,但并不老是可能的。 对于这些状况,专用命名空间提供服务器特定的定制(请参阅server.tomcat和server.undertow)。 例如,可使用嵌入式servlet容器的特定功能来配置访问日志

有关完整列表,请参阅 ServerProperties 类。

用程序定制

若是须要以编程方式配置嵌入式servlet容器,您能够注册一个实现EmbeddedServletContainerCustomizer接口的Spring bean。 EmbeddedServletContainerCustomizer提供对ConfigurableEmbeddedServletContainer的访问,其中包含许多自定义设置方法。

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);
}

}

直接自定义ConfigurableEmbeddedServletContainer

若是上述定制技术有太多限制,您能够本身注册TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactory或UndertowEmbeddedServletContainerFactory bean。

@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方法提供了许多配置选项。 若是您须要作更多的自定义,还会提供几种保护方法“钩子”。 有关详细信息,请参阅源代码文档。

27.3.5 JSP限制

当运行使用嵌入式servlet容器(并打包为可执行文档)的Spring Boot应用程序时,对JSP支持有一些限制。

  • 可使用Tomcat和war包,便可执行的war将会起做用,而且也能够部署到标准容器(不限于但包括Tomcat)中。 因为Tomcat中的硬编码文件模式,可执行的jar将没法正常工做。
  • 可使用Jetty和war包,便可执行的war将会起做用,而且也能够部署到任何标准的容器,它应该能够工做。
  • Undertow不支持JSP。
  • 建立自定义的error.jsp页面将不会覆盖默认视图以进行错误处理,而应使用自定义错误页面

28. Security

若是Spring Security位于类路径上,则默认状况下,Web应用程序将在全部HTTP端点上使用“basic”身份验证。 要向Web应用程序添加方法级安全性,您还可使用所需的设置添加@EnableGlobalMethodSecurity。 有关更多信息,请参见“Spring Security Reference”。

默认的AuthenticationManager有一个用户(用户名’user’和随机密码,在应用程序启动时以INFO级别打印)

Using default security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35

若是您调整日志记录配置,请确保将org.springframework.boot.autoconfigure.security类别设置为记录INFO消息,不然将不会打印默认密码。

您能够经过提供security.user.password来更改密码。 这个和其余有用的属性经过 SecurityProperties(属性前缀“security”)进行外部化。

默认的安全配置在SecurityAutoConfiguration和从那里导入的类中实现(用于Web安全的SpringBootWebSecurityConfiguration和用于认证配置的AuthenticationManagerConfiguration,这在非Web应用程序中也是相关的)。 要彻底关闭默认的Web应用程序安全配置,您可使用@EnableWebSecurity添加一个bean(这不会禁用身份验证管理器配置或Actuator的安全性)。 要定制它,您一般使用WebSecurityConfigurerAdapter类型的外部属性和bean(例如添加基于表单的登陆)。 要关闭身份验证管理器配置,您能够添加AuthenticationManager类型的bean,或者经过将AuthenticationManagerBuilder自动链接到您的一个@Configuration类中的方法来配置全局AuthenticationManager。 Spring Boot示例中有几个安全应用程序可让您开始使用常见的用例

您在Web应用程序中得到的基本功能包括:

  • 具备内存存储和单个用户的AuthenticationManager Bean(请参阅用于用户属性的SecurityProperties.User)。
  • 对于常见的静态资源位置,忽略(不安全)路径(/css/**, /js/**, /images/**, /webjars/** and **/favicon.ico)。
  • HTTP全部其余端点的baseic security 。
  • 安全事件发布到Spring的ApplicationEventPublisher(成功、不成功的身份验证、拒绝访问)。
  • 默认状况下,Spring Security提供的常见的底层功能(HSTS,XSS,CSRF,缓存)都是打开的。

全部上述可使用外部属性(security.*)打开、关闭或修改。 要覆盖访问规则而不更改任何其余自动配置的功能,请添加一个带有@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)的WebSecurityConfigurerAdapter类型的Bean,并配置它以知足您的须要。

默认状况下,WebSecurityConfigurerAdapter将匹配任何路径。 若是您不想彻底覆盖Spring Boot自动配置的访问规则,您的适配器必须显式配置您要覆盖的路径。

28.1 OAuth2

若是您的类路径中有spring-security-oauth2,您能够利用一些自动配置来轻松设置受权或资源服务器。 有关完整的详细信息,请参阅“Spring Security OAuth 2开发人员指南”。

28.1.1 受权服务器

要建立受权服务器并授予访问令牌,您须要使用@EnableAuthorizationServer并提供security.oauth2.client.client-id和security.oauth2.client.client-secret]属性。 客户端将为您注册在内存中。

$ curl client:secret@localhost:8080/oauth/token -d grant_type=password -d username=user -d password=pwd

/token 端点的基自己份验证凭证是client-id和client-secret。 用户凭据是普通的Spring Security用户details (在Spring引导中默认为“user”和随机密码)。

要关闭自动配置并自行配置受权服务器功能,只需添加一个类型为AuthorizationServerConfigurer的@Bean。

28.1.2 资源服务器

要使用访问令牌(token),您须要一个资源服务器(能够与受权服务器相同)。 建立资源服务器很简单,只需添加@EnableResourceServer并提供一些配置,以容许服务器解码访问令牌。 若是您的应用程序也是受权服务器,则它已经知道如何解码令牌,无需作其余事情。 若是你的应用程序是一个独立的服务,那么你须要给它一些更多的配置,如下选项之一:

若是您同时指定user-info-uri和token-info-uri,那么您能够设置一个标志,表示优先于另外一个(prefer-token-inf=true是默认值)。

或者(不是user-info-uri或token-info-uri的状况)若是令牌是JWT,您能够配置security.oauth2.resource.jwt.key-value来本地解码(key是验证密钥verification key)。 验证密钥值是对称秘密或PEM编码的RSA公钥。 若是您没有密钥,而且它是公开的,您能够提供一个可使用security.oauth2.resource.jwt.key-uri下载的URI(具备“value”字段的JSON对象)。 例如在PWS上:

$ curl https://uaa.run.pivotal.io/token_key
{"alg":"SHA256withRSA","value":"-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----\n"}

若是您使用security.oauth2.resource.jwt.key-uri,则应用程序启动时须要运行受权服务器。 若是找不到密钥,它将记录一个警告,并告诉您如何解决该问题。

若是您使用security.oauth2.resource.jwt.key-uri,则应用程序启动时须要运行受权服务器。 若是找不到密钥,它将会在日志记录一个警告,并告诉您如何解决该问题。

OAuth2资源由order security.oauth2.resource.filter-order的过滤器链保护,默认状况下保护执行器(actuator)端点的过滤器(因此执行器(actuator)端点将保留在HTTP Basic上,除非更改顺序)。

28.2 User Info中的令牌类型

Google和某些其余第三方身份认证提供商对在header中发送到用户信息端点的令牌类型名称更为严格。 默认值为“Bearer”,适合大多数提供程序并匹配规范,但若是须要更改,能够设置security.oauth2.resource.token-type。

28.3 自定义用户信息RestTemplate

若是您有user-info-uri,则资源服务器功能在内部使用OAuth2RestTemplate来获取用户身份验证信息。 这是以UserInfoRestTemplateFactory类型的@Bean提供的。 大多数提供程序的默认值应该是能知足正常使用,但有时您可能须要添加其余拦截器,或者更改请求验证器(例如:令牌如何附加到传出请求)。 进行自定义,只需建立一个类型为UserInfoRestTemplateCustomizer的bean - 它具备一个方法,在bean建立以后但在初始化以前将被调用。 这里定制的rest模板只能在内部进行验证。 或者,您能够定义本身的UserInfoRestTemplateFactory @Bean来彻底控制。

要在YAML中设置RSA密钥值,请使用“pipe”继续标记将其分割成多行(“|”),并记住缩进键值(它是标准的 YAML 语言功能)。 例:

security:
oauth2:
resource:
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC...
-----END PUBLIC KEY-----

28.3.1 Client

要使您的 web-app 进入OAuth2客户端,您能够简单地添加@ EnableOAuth2Client,Spring Boot将建立一个OAuth2ClientContext和OAuth2ProtectedResourceDetails,这些是建立OAuth2RestOperations所必需的。 Spring Boot不会自动建立这样的bean,可是您能够轻松建立本身的bean:

@Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext,
OAuth2ProtectedResourceDetails details) {
return new OAuth2RestTemplate(details, oauth2ClientContext);
}

您可能须要添加限定符并查看您的配置,由于您的应用程序可能会定义多个RestTemplate。

此配置使用security.oauth2.client.*做为凭据(可能与受权服务器中使用的相同),但另外还须要知道受权服务器中的受权和令牌URI。 例如:

application.yml.

security:
oauth2:
client:
clientId: bd1c0a783ccdd1c9b9e4
clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
accessTokenUri: https://github.com/login/oauth/access_token
userAuthorizationUri: https://github.com/login/oauth/authorize
clientAuthenticationScheme: form

当您尝试使用OAuth2RestTemplate时,具备此配置的应用程序将重定向到Github进行受权。 若是您已经登陆Github,您甚至不会注意到它已经被认证。 若是您的应用程序在端口8080上运行(在Github或其余提供商注册本身的客户端应用程序以得到更大的灵活性),这些特定的凭据才会起做用。

要限制客户端在获取访问令牌时要求的范围,您能够设置security.oauth2.client.scope(逗号分隔或YAML中的数组)。 默认状况下,scope是空的,由受权服务器决定其默认值,一般取决于客户端注册中的设置。

还有一个security.oauth2.client.client-authentication-scheme的设置,默认为“header”(可是若是像Github那样,您可能须要将其设置为“form”,例如,您的OAuth2提供程序不喜欢header 认证)。 事实上,security.oauth2.client.*属性绑定到AuthorizationCodeResourceDetails的一个实例,所以能够指定其全部的属性。

在非Web应用程序中,您仍然能够建立一个OAuth2RestOperations,它仍然链接到security.oauth2.client.*配置中。 在这种状况下,它是一个“客户端凭据令牌授予”,您若是使用它就请求它(而且不须要使用@EnableOAuth2Client或@EnableOAuth2Sso)。为了防止定义基础设施,只需从配置中删除security.oauth2.client.client-id(或使其成为空字符串)。

28.3.2 单点登陆

OAuth2客户端可用于从提供商获取用户详细信息(若是此类功能可用),而后将其转换为Spring Security的身份验证令牌。 以上资源服务器经过user-info-uri属性支持此功能这是基于OAuth2的单点登陆(SSO)协议的基础,Spring Boot能够经过提供@ EnableOAuth2Sso注解来轻松加入。 上面的Github客户端能够经过添加该注释并声明在何处查找端点(除了上面列出的security.oauth2.client.*配置)外,还能够保护全部资源并使用Github/user/endpoint进行身份验证:

application.yml.

security:
oauth2:
...
resource:
userInfoUri: https://api.github.com/user
preferTokenInfo: false

因为默认状况下全部路径都是安全的,因此没有能够向未经身份验证的用户显示“家”页面,并邀请他们登陆(经过访问/登陆路径或由security.oauth2.sso.login-path指定的路径) 。

因为默认状况下全部路径都是要求安全的,因此没有能够向未经身份验证的用户显示“home”页面,并邀请他们登陆(经过访问/login 路径或由security.oauth2.sso.login-path指定的路径) 。

要自定义保护的访问规则或路径,所以您能够添加“home”页面,例如,@EnableOAuth2Sso能够添加到WebSecurityConfigurerAdapter,而且注解将使其被修饰和加强,以使所需的/login路径能够工做。 例如,这里咱们简单地容许未经身份验证的访问“/“下的主页面,并保留其余全部内容的默认值:

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
public void init(WebSecurity web) {
web.ignore("/");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();
}

}

28.4 Actuator Security

若是Actuator也在使用中,您会发现:

  • 即便应用程序端点不安全,管理端点也是安全的。
  • Security 事件将转换为AuditEvent实例,并发布到AuditEventRepository。
  • 默认用户将具备ACTUATOR角色以及USER角色。

Actuator的安全功能可使用外部属性(management.security.*)进行修改。要覆盖应用程序访问规则,请添加一个类型为WebSecurityConfigurerAdapter的@Bean,若是您不想覆盖执行程序访问规则,则使用@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)或@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)覆盖执行器访问规则。

29. 使用SQL数据库

Spring Framework 为使用SQL数据库提供了普遍的支持。 从使用JdbcTemplate直接JDBC访问到完成“对象关系映射”技术,如Hibernate。Spring Data提供了额外的功能,直接从接口建立Repository实现,并使用约定从方法名称生成查询。

29.1 配置DataSource

Java的javax.sql.DataSource接口提供了使用数据库链接的标准方法。传统上,DataSource使用URL和一些凭据来创建数据库链接。

还能够查看更多高级示例的“操做方法”部分,一般能够彻底控制DataSource的配置。

29.1.1 嵌入式数据库支持

使用内存中嵌入式数据库开发应用程序一般很方便。 显然,内存数据库不提供持久化存储; 您的应用程序启动时,您将须要初始化数据库,并在应用程序结束时丢弃数据。

“How-to”部分包含如何初始化数据库

Spring Boot能够自动配置嵌入式 H2HSQLDerby 数据库。 您不须要提供任何链接URL,只需将要使用的嵌入式数据库的依赖关系包含进去便可。

若是您在测试中使用此功能,您可能会注意到,整个测试套件都会重复使用相同的数据库,而无论您使用的应用程序上下文的数量。 若是要确保每一个上下文都有一个单独的嵌入式数据库,您应该将spring.datasource.generate-unique-name设置为true。

例如,典型的POM依赖关系是:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>

对于要自动配置的嵌入式数据库,您须要依赖spring-jdbc。 在这个例子中,它是经过spring-boot-starter-data-jpa传递的。

若是因为某种缘由配置嵌入式数据库的链接URL,则应注意确保数据库的自动关闭被禁用。 若是你使用H2,你应该使用DB_CLOSE_ON_EXIT=FALSE这样作。 若是您使用HSQLDB,则应确保不使用shutdown=true。 禁用数据库的自动关闭容许Spring Boot控制数据库什么时候关闭,从而确保在再也不须要访问数据库时发生这种状况。

29.1.2 链接到生产环境数据库

生产数据库链接也可使用链接池数据源自动配置。 这是选择具体实现的算法:

  • 咱们更喜欢Tomcat链接池DataSource的性能和并发性,因此若是可用,咱们老是选择它。
  • 不然,若是HikariCP可用,咱们将使用它。
  • 若是Tomcat池数据源和HikariCP都不可用,而且若是Commons DBCP可用,咱们将使用它,可是咱们不建议在生产中使用它,而且不支持它。
  • 最后,若是Commons DBCP2可用,咱们将使用它。

若是您使用spring-boot-starter-jdbc或spring-boot-starter-data-jpa 的startters,您将自动得到对tomcat-jdbc的依赖。

您能够彻底绕过该算法,并经过spring.datasource.type属性指定要使用的链接池。 若是您在Tomcat容器中运行应用程序,则默认状况下提供tomcat-jdbc,这一点尤其重要。

能够随时手动配置其余链接池。若是您定义本身的DataSource bean,则不会发生自动配置。

DataSource配置由spring.datasource中的外部配置属性控制。 例如,您能够在application.properties中声明如下部分:

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

您应至少使用spring.datasource.url属性指定url,不然Spring Boot将尝试自动配置嵌入式数据库。

您一般不须要指定驱动程序类名称,由于Spring Boot能够从url为大多数数据库推断出驱动程序名称。

对于要建立的池数据源,咱们须要可以验证有效的Driver类是否可用,因此咱们在作任何事情以前检查它。 即 若是您设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver,那么该类必须可加载。

有关更多支持的选项,请参阅 DataSourceProperties。 这些是标准选项,不管实际执行状况如何。 还可使用各自的前缀(spring.datasource.tomcat.*,spring.datasource.hikari.*和spring.datasource.dbcp2.*)微调实现特定的设置。 有关更多详细信息,请参阅您正在使用的链接池实现的文档。

例如,若是您正在使用Tomcat链接池,您能够自定义许多其余设置:

# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.tomcat.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=50

# Validate the connection before borrowing it from the pool.
spring.datasource.tomcat.test-on-borrow=true

29.1.3 链接到JNDI DataSource

若是要将Spring Boot应用程序部署到应用程序服务器,则可能须要使用应用程序服务器内置功能来配置和管理DataSource,并使用JNDI进行访问。

spring.datasource.jndi-name属性能够用做spring.datasource.url,spring.datasource.username和spring.datasource.password属性的替代方法,以从特定的JNDI位置访问DataSource。 例如,application.properties中的如下部分显示了如何访问JBoss AS定义的DataSource:

spring.datasource.jndi-name=java:jboss/datasources/customers

29.2 使用JdbcTemplate

Spring的JdbcTemplate和NamedParameterJdbcTemplate类是自动配置的,您能够将它们直接链接到您本身的bean中:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

private final JdbcTemplate jdbcTemplate;

@Autowired
public MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

// ...

}

29.3 JPA 和 ‘Spring Data’

Java Persistence API是一种标准技术,可以让您将对象映射到关系数据库。 spring-boot-starter-data-jpa POM提供了一种快速入门的方法。 它提供如下关键依赖:

  • Hibernate - 最受欢迎的JPA实现之一。
  • Spring Data JPA - 能够轻松实现基于JPA的存储库。
  • Spring ORMs - 来自Spring Framework的核心ORM支持。

咱们不会在这里介绍太多的JPA或Spring Data的细节。 您能够从spring.io中查看“使用JPA访问数据”指南,并阅读Spring Data JPAHibernate参考文档。

默认状况下,Spring Boot使用Hibernate 5.0.x. 可是,若是您愿意,也可使用4.3.x或5.2.x。 请参考 Hibernate 4Hibernate 5.2 示例,看看如何作到这一点。

29.3.1 实体类

传统上,JPA’Entity’类在persistence.xml文件中指定。 使用Spring Boot此文件不是必需的,而是使用“实体扫描”。 默认状况下,将搜索主配置类下面的全部包(用@EnableAutoConfiguration或@SpringBootApplication注解的类)。

任何用@Entity,@Embeddable或@MappedSuperclass注解的类将被考虑。 典型的实体类将以下所示:

package com.example.myapp.domain;

import java.io.Serializable;
import javax.persistence.*;

@Entity
public class City implements Serializable {

@Id
@GeneratedValue
private Long id;

@Column(nullable = false)
private String name;

@Column(nullable = false)
private String state;

// ... additional members, often include @OneToMany mappings

protected City() {
// no-args constructor required by JPA spec
// this one is protected since it shouldn't be used directly
}

public City(String name, String state) {
this.name = name;
this.country = country;
}

public String getName() {
return this.name;
}

public String getState() {
return this.state;
}

// ... etc

}

您可使用@EntityScan注解自定义实体扫描位置。 请参见第77.4节“从Spring配置中分离@Entity定义”操做方法。

29.3.2 Spring Data JPA Repositories

Spring Data JPA库是能够定义用于访问数据的接口。 JPA查询是从您的方法名称自动建立的。 例如,CityRepository接口能够声明findAllByState(String state)方法来查找给定状态下的全部城市。

对于更复杂的查询,您可使用Spring数据查询注解来注解您的方法。

Spring数据存储库一般从Repository或CrudRepository接口扩展。 若是您正在使用自动配置,将从包含主配置类(经过@EnableAutoConfiguration或@SpringBootApplication注解的包)的包中搜索存储库(repositories)。

这是一个典型的Spring数据库:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

Page<City> findAll(Pageable pageable);

City findByNameAndCountryAllIgnoringCase(String name, String country);

}

咱们只是触及了Spring Data JPA的表面。 有关完整的详细信息,请查阅其参考文档

29.3.3 建立和删除JPA数据库

默认状况下,仅当您使用嵌入式数据库(H2,HSQL或Derby)时才会自动建立JPA数据库。 您可使用spring.jpa。*属性显式配置JPA设置。 例如,要建立和删除表,您能够将如下内容添加到application.properties中。

spring.jpa.hibernate.ddl-auto=create-drop

Hibernate本身的内部属性名称(若是你记得更好)是hibernate.hbm2ddl.auto。您可使用spring.jpa.properties *(将其添加到实体管理器时这个前缀会被删除)与其余Hibernate属性一块儿设置。 例:

spring.jpa.properties.hibernate.globally_quoted_identifiers=true

hibernate.globally_quoted_identifiers 传递给Hibernate实体管理器。

默认状况下,DDL执行(或验证)将延迟到ApplicationContext启动。 还有一个spring.jpa.generate-ddl标志,可是若是Hibernate 自动配置是激活的,那么它将不会被使用,由于ddl-auto配置更好。

29.3.4 在View中打开EntityManager

若是您正在运行Web应用程序,Spring Boot将默认注册OpenEntityManagerInViewInterceptor来应用“查看”中的“打开EntityManager”模式,即容许在Web视图中进行延迟加载。 若是你不想要这个行为,你应该在你的application.properties中将spring.jpa.open-in-view设置为false。

29.4 使用H2的Web控制台

H2数据库提供了一个基于浏览器的控制台,Spring Boot能够为您自动配置。 知足如下条件时,控制台将自动配置:

若是您不使用Spring Boot的开发人员工具,但仍但愿使用H2的控制台,那么能够经过配置一个值为true的spring.h2.console.enabled属性来实现。 H2控制台仅用于开发期间,所以应注意确保spring.h2.console.enabled在生产中未设置为true。

29.4.1 更改H2控制台的路径

默认状况下,控制台路径将在 /h2-console上。 您可使用spring.h2.console.path属性来自定义控制台的路径。

29.4.2 保护H2控制台

当Spring Security位于类路径上且启用了基自己份验证时,H2控制台将自动使用基自己份验证进行保护。 如下属性可用于自定义安全配置:

  • security.user.role
  • security.basic.authorize-mode
  • security.basic.enabled

29.5 使用jOOQ

Java面向对象查询(jOOQ)是Data Geekery的产品,它从数据库生成Java代码,并经过流畅的API构建类型安全的SQL查询。 商业版和开源版均可以与Spring Boot一块儿使用。

29.5.1 代码生成

为了使用jOOQ类型安全的查询,您须要从数据库模式生成Java类。 您能够按照jOOQ用户手册中的说明进行操做。 若是您正在使用jooq-codegen-maven插件(而且还使用spring-boot-starter-parent“父POM”),您能够安全地省略插件的标签。 您还可使用Spring Boot定义的版本变量(例如h2.version)来声明插件的数据库依赖关系。 如下是一个例子:

<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
...
</executions>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
<configuration>
<jdbc>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/yourdatabase</url>
</jdbc>
<generator>
...
</generator>
</configuration>
</plugin>

29.5.2 使用 DSLContext

jOOQ提供的流畅的API是经过org.jooq.DSLContext接口启动的。 Spring Boot将自动配置DSLContext做为Spring Bean并将其链接到应用程序DataSource。 要使用DSLContext,您只需@Autowire它:

@Component
public class JooqExample implements CommandLineRunner {

private final DSLContext create;

@Autowired
public JooqExample(DSLContext dslContext) {
this.create = dslContext;
}

}

jOOQ手册倾向于使用名为create的变量来保存DSLContext,咱们在此示例中也是这样。

而后,您可使用DSLContext构建查询:

public List<GregorianCalendar> authorsBornAfter1980() {
return this.create.selectFrom(AUTHOR)
.where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
.fetch(AUTHOR.DATE_OF_BIRTH);
}

29.5.3 定制jOOQ

您能够经过在application.properties中设置spring.jooq.sql-dialect来自定义jOOQ使用的SQL方言。 例如,要指定Postgres,您能够添加:

spring.jooq.sql-dialect=Postgres

经过定义本身的@Bean定义能够实现更高级的定制,这些定义将在建立jOOQ配置时使用。您能够为如下jOOQ类型定义bean:

  • ConnectionProvider
  • TransactionProvider
  • RecordMapperProvider
  • RecordListenerProvider
  • ExecuteListenerProvider
  • VisitListenerProvider

若是要彻底控制jOOQ配置,您还能够建立本身的org.jooq.Configuration @Bean。

30. 使用NoSQL技术

Spring Data提供了额外的项目,可帮助您访问各类NoSQL技术,包括MongoDBNeo4JElasticsearchSolrRedisGemfireCassandraCouchbaseLDAP。 Spring Boot为Redis,MongoDB,Neo4j,Elasticsearch,Solr Cassandra,Couchbase和LDAP提供了自动配置; 您也可使用其余项目,但您须要自行配置它们。 请参阅projects.spring.io/spring-data中相应的参考文档。

30.1 Redis

Redis是一个缓存,消息代理并有功能丰富的键值存储数据库。Spring Boot提供了Jedis客户端库的基本自动配置和Spring Data Redis提供的抽象。 有一个spring-boot-starter-data-redis“Starter”用于以方便的方式收集依赖关系。

30.1.1 链接到Redis

您能够像任何其余Spring Bean同样注入自动配置的RedisConnectionFactory,StringRedisTemplate或vanilla RedisTemplate实例。 默认状况下,实例将尝试使用localhost:6379链接到Redis服务器:

@Component
public class MyBean {

private StringRedisTemplate template;

@Autowired
public MyBean(StringRedisTemplate template) {
this.template = template;
}

// ...

}

若是您添加了您本身的任何自动配置类型的@Bean,它将替换默认值(除了在RedisTemplate的状况下,排除是基于bean名称“redisTemplate”而不是其类型)。 若是commons-pool2在类路径上,则默认状况下将得到一个pooled链接工厂。

30.2 MongoDB

MongoDB是一个开源的NoSQL文档数据库,它使用相似JSON的架构,而不是传统的基于表的关系数据。 Spring Boot为MongoDB提供了几种便利,包括spring-boot-starter-data-mongodb’Starter’。

相关文章
相关标签/搜索