Spring Boot文档(010)-第九部分

第九部分。'怎么做'指南

本节为使用Spring Boot时经常出现的一些常见“我该怎么做......”类型的问题提供了答案。这绝不是一个详尽的清单,但它确实覆盖了很多。

如果你有一个我们在这里没有涉及的具体问题,你可能想查看 stackoverflow.com,看看有人已经提供了答案; 这也是一个提出新问题的好地方(请使用spring-boot标签)。

我们也非常乐意扩展这一部分; 如果你想添加一个'如何做',你可以给我们一个请求

71. Spring Boot应用程序

71.1创建您自己的FailureAnalyzer

FailureAnalyzer是在启动时拦截异常并将其转换为可读的消息并封装到一个非常好的方法FailureAnalysis。Spring Boot为应用程序上下文相关的异常,JSR-303验证等提供了这样的分析器。创建你自己的实际是非常容易的。

AbstractFailureAnalyzer是一个方便的扩展,FailureAnalyzer用于检查异常中是否存在指定的异常类型。您可以从中进行扩展,以便您的实现只有在实际存在时才有机会处理异常。如果出于任何原因您无法处理异常,请返回null 给另一个实现处理异常的机会。

FailureAnalyzer实现应在META-INF/spring.factories以下寄存器中进行注册ProjectConstraintViolationFailureAnalyzer

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer

71.2排除自动配置故障

Spring Boot自动配置尽最大努力“做正确的事情”,但有时候事情会失败,并且很难说明原因。

ConditionEvaluationReport在任何Spring Boot中 都有一个非常有用的功能ApplicationContext。如果启用DEBUG日志记录输出,您会看到它。如果您使用的spring-boot-actuator是以autoconfigJSON呈现报表的终端。使用它来调试应用程序,并查看Spring Boot在运行时添加了哪些功能(哪些功能未添加)。

通过查看源代码和Javadoc可以回答更多的问题。一些经验法则:

  • 寻找被调用的类*AutoConfiguration并阅读它们的源代码,特别是 @Conditional*注释以找出它们启用的功能以及何时启用。添加 --debug到命令行或System属性中,-Ddebug以获取应用程序中所做的所有自动配置决策的日志。在一个正在运行的执行器应用程序中查看autoconfig端点('/ autoconfig'或JMX等价物)以获取相同的信息。
  • 寻找@ConfigurationProperties(例如 ServerProperties)类并从那里读取可用的外部配置选项。所述 @ConfigurationProperties具有name其用作前缀外部属性属性,因而ServerProperties具有prefix="server"和它的配置属性server.portserver.address等等。在致动器运行的应用程序看configprops端点。
  • 寻找使用RelaxedPropertyResolver以明确地从中提取配置值 Environment。它通常与前缀一起使用。
  • 寻找@Value直接绑定到注释的注释Environment。这比RelaxedPropertyResolver方法更不灵活,但确实允许一些放松的绑定,特别是对于OS环境变量(CAPITALS_AND_UNDERSCORES同义词period.separated)。
  • 查找@ConditionalOnExpression注释,以便根据SpEL表达式开启和关闭功能,通常使用从中解析的占位符进行评估 Environment

71.3在开始之前自定义Environment或ApplicationContext

SpringApplicationhas ApplicationListenersApplicationContextInitializersthat用于将自定义应用于上下文或环境。Spring Boot加载了许多这样的自定义内部使用META-INF/spring.factories。有多种方法可以注册更多的方法:

  • 在运行之前,通过调用addListenersaddInitializers 方法对每个应用程序进行编程SpringApplication
  • 通过设置context.initializer.classes或 声明来为每个应用程序context.listener.classes
  • 通过添加META-INF/spring.factories和打包应用程序都用作库的jar文件来声明性地为所有应用程序声明。

SpringApplication发送一些特殊ApplicationEvents的听众(创建上下文甚至一些之前),然后注册了在公布的事件监听器ApplicationContext为好。有关完整列表请参见 “Spring Boot功能”一节中的第23.5节“应用程序事件和侦听器”

也可以Environment在应用程序上下文使用之前自定义EnvironmentPostProcessor。每个实现应该在以下位置注册 META-INF/spring.factories

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

该实现可以加载任意文件并将其添加到Environment。例如,这个例子从类路径中加载一个YAML配置文件

public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {

	private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment,
			SpringApplication application) {
		Resource path = new ClassPathResource("com/example/myapp/config.yml");
		PropertySource<?> propertySource = loadYaml(path);
		environment.getPropertySources().addLast(propertySource);
	}

	private PropertySource<?> loadYaml(Resource path) {
		if (!path.exists()) {
			throw new IllegalArgumentException("Resource " + path + " does not exist");
		}
		try {
			return this.loader.load("custom-resource", path, null);
		}
		catch (IOException ex) {
			throw new IllegalStateException(
					"Failed to load yaml configuration from " + path, ex);
		}
	}

}
[小费]

Environment已经将已准备与所有常见的财产来源春天引导加载默认。因此可以从环境中获取文件的位置。此示例custom-resource在列表末尾添加属性源,以便在任何常用其他位置定义的键优先。自定义实现可能显然定义另一个订单。

[注意]

虽然@PropertySource在你的使用上@SpringBootApplication看起来Environment既方便又简单,可以在其中加载自定义资源,但我们并不推荐Spring Boot EnvironmentApplicationContext刷新之前做好准备。任何通过定义的按键@PropertySource都会被加载太晚而不能对自动配置产生任何影响。

71.4构建一个ApplicationContext层次结构(添加父级或根级上下文)

您可以使用ApplicationBuilder该类来创建父/子ApplicationContext 层次结构。有关 更多信息请参见“Spring Boot功能”一节中的第23.4节“流利构建器API”

71.5创建一个非Web应用程序

并非所有的Spring应用程序都必须是Web应用程序(或Web服务)。如果你想在一个main方法中执行一些代码,并且引导一个Spring应用程序来设置要使用的基础设施,那么使用SpringApplicationSpring Boot 的特性很容易。A 根据是否认为需要Web应用程序来SpringApplication更改其ApplicationContext类。你可以做的第一件事就是把servlet API的依赖关系放在类路径之外。如果你不能这样做(例如,你从同一个代码库运行2个应用程序),那么你可以明确地调用setWebEnvironment(false)你的SpringApplication实例,或设置 applicationContextClass属性(通过Java API或外部属性)。您想要作为业务逻辑运行的应用程序代码可以实现为 CommandLineRunner并作为@Bean定义放入上下文中。

72.属性和配置

72.1在构建时自动扩展属性

您可以使用现有的生成配置来自动扩展它们,而不是硬编码在您的项目的生成配置中指定的一些属性。这在Maven和Gradle中都是可能的。

72.1.1使用Maven自动扩展属性

您可以使用资源过滤自动扩展Maven项目中的属性。如果你使用spring-boot-starter-parent你可以通过@..@占位符引用你的Maven'项目属性' ,例如

app.encoding=@project.build.sourceEncoding@
app.java.version=@java.version@
[注意]

只有生产配置以这种方式过滤(即不应用过滤 src/test/resources)。

[小费]

spring-boot:run可以添加src/main/resources,如果你能直接到类路径(热重装目的)addResources标志。这规避了资源过滤和此功能。您可以exec:java改为使用目标或自定义插件的配置,请参阅 插件使用页面了解更多详细信息。

如果你不使用初学者父母,pom.xml你需要(在<build/> 元素内):

<resources>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
    </resource>
</resources>

和(里面<plugins/>):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.7</version>
    <configuration>
        <delimiters>
            <delimiter>@</delimiter>
        </delimiters>
        <useDefaultDelimiters>false</useDefaultDelimiters>
    </configuration>
</plugin>
[注意]

useDefaultDelimiters如果您在配置中使用标准Spring占位符(例如${foo}),则该属性非常重要。如果该属性未设置,则这些可能会由构建扩展false

72.1.2使用Gradle自动扩展属性

您可以通过配置Java插件的processResources任务来自动扩展Gradle项目中的属性:

processResources {
    expand(project.properties)
}

然后,您可以通过占位符引用您的Gradle项目的属性,例如

app.name=${name}
app.description=${description}
[注意]

Gradle的expand方法使用了SimpleTemplateEngine转换 ${..}令牌的Groovy 。这种${..}风格与Spring自己的属性占位机制有冲突。要将Spring属性占位符与自动扩展一起使用,Spring属性占位符需要被转义\${..}

72.2外部化SpringApplication的配置

SpringApplication具有bean属性(主要是setter),因此您可以在创建应用程序时使用其Java API来修改其行为。或者,您可以使用中的属性外化配置spring.main.*。例如在application.properties你可能有。

spring.main.web-environment=false
spring.main.banner-mode=off


然后Spring Boot横幅将不会在启动时被打印,并且该应用程序将不会是Web应用程序。

[注意]

上面的例子还演示了灵活绑定如何允许在属性名称中使用下划线(_)以及破折号(-)。

在外部配置中定义的属性会覆盖通过Java API指定的值,但用于创建该属性的源的值得注意的例外ApplicationContext。我们来考虑这个应用程序

new SpringApplicationBuilder()
    .bannerMode(Banner.Mode.OFF)
    .sources(demo.MyApp.class)
    .run(args);

与以下配置一起使用:

spring.main.sources=com.acme.Config,com.acme.ExtraConfig
spring.main.banner-mode=console

实际的应用程序将现在显示的旗帜(通过配置覆盖)和使用三个来源为ApplicationContext(按顺序): ,demo.MyApp,。com.acme.Configcom.acme.ExtraConfig

72.3更改应用程序的外部属性的位置

默认情况下,来自不同源的属性Environment按照定义的顺序添加到Spring 中(请参阅第24章, 'Spring Boot功能部分中的外部化配置 '以了解确切顺序)。

增加和修改这个方法的一个好方法是向@PropertySource应用程序源添加注释。传递给SpringApplication静态便利方法的类以及那些添加使用的方法将setSources()被检查以确定它们是否具有@PropertySources,如果它们具有 这些属性,则Environment尽早将这些属性添加到ApplicationContext生命周期的所有阶段中。以这种方式添加的属性的优先级低于使用默认位置(例如application.properties),系统属性,环境变量或命令行添加的任何属性。

您还可以提供系统属性(或环境变量)来更改行为:

  • spring.config.nameSPRING_CONFIG_NAME),默认application为文件名的根。
  • spring.config.locationSPRING_CONFIG_LOCATION)是要加载的文件(例如类路径资源或URL)。Environment为此文档设置了一个单独的属性源,它可以被系统属性,环境变量或命令行覆盖。

无论您在环境中设置了什么,Spring Boot将始终application.properties按照上述方式加载 。如果使用YAML,默认情况下,具有'.yml'扩展名的文件也会添加到列表中。

Spring Boot会记录在DEBUG级别加载的配置文件以及在级别上未找到的候选项TRACE

查看ConfigFileApplicationListener 更多细节。

72.4使用'short'命令行参数

有些人喜欢使用(例如)--port=9000而不是--server.port=9000在命令行上设置配置属性。您可以通过在application.properties例如中使用占位符来轻松启用此功能

server.port=${port:8080}
[小费]

如果你是从继承spring-boot-starter-parentPOM,的默认筛选器标记maven-resources-plugins已经从变化${*}@(即@maven.token@代替${maven.token}),以防止春季风格占位符冲突。如果您为application.properties 直接启用了Maven过滤,则可能还需要将默认过滤令牌更改为使用 其他分隔符

[注意]

在这种特定情况下,端口绑定将在像Heroku和Cloud Foundry这样的PaaS环境中工作,因为在这两个平台中,PORT环境变量是自动设置的,并且Spring可以绑定到大写的Environment属性同义词。

72.5使用YAML作为外部属性

YAML是JSON的超集,因此这是一种用于以分层格式存储外部属性的非常方便的语法。例如

spring:
    application:
        name: cruncher
    datasource:
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost/test
server:
    port: 9000

创建一个名为的文件,application.yml并将其粘贴到类路径的根目录中,并添加snakeyaml到您的依赖项中(Maven坐标org.yaml:snakeyaml,如果您使用该坐标,则已包括在内spring-boot-starter)。一个YAML文件被解析为一个Java Map<String,Object>(就像一个JSON对象),并且Spring Boot展平地图,使其具有1级深度,并且具有句点分隔的键,就像人们习惯用 PropertiesJava中的文件一样。

上面的示例YAML对应于一个application.properties文件

spring.application.name=cruncher
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000

有关YAML的更多信息请参见第24.6节“在Spring Boot功能部分使用YAML而不是属性”

72.6设置活动的spring配置文件

Spring Environment为此提供了一个API,但通常您可以设置一个System属性(spring.profiles.active)或一个OS环境变量(SPRING_PROFILES_ACTIVE)。例如用-D参数启动你的应用程序(记住把它放在主类或jar文件之前):

$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar

在Spring Boot中,您还可以设置活动配置文件application.properties,例如

spring.profiles.active=production

以此方式设置的值将由系统属性或环境变量设置替代,但不会由SpringApplicationBuilder.profiles()方法替代。因此,后一个Java API可以用来扩充配置文件而不更改默认值。

有关更多信息请参阅第25章 “Spring Boot功能”一节中的配置文件

72.7根据环境更改配置

YAML文件实际上是一系列按---行分隔的文档,并且每个文档都被分别解析为拼合的地图。

如果YAML文档包含一个spring.profiles键,那么配置文件值(以逗号分隔的配置文件列表)将被馈送到Spring中, Environment.acceptsProfiles()并且如果这些配置文件中的任何配置文件处于活动状态,则该文档将包含在最终合并中(否则)。

例:

server:
    port: 9000
---

spring:
    profiles: development
server:
    port: 9001

---

spring:
    profiles: production
server:
    port: 0

在这个例子中,默认端口是9000,但是如果Spring profile'development'被激活,那么端口是9001,如果'production'被激活,那么它是0。

YAML文档按它们遇到的顺序合并(所以后面的值会覆盖先前的值)。

要使用属性文件执行相同的操作,您可以使用它application-${profile}.properties 来指定特定于配置文件的值。

72.8发现外部属性的内置选项

Spring Boot 在运行时将application.properties(或.yml)(和其他位置)的外部属性绑定到应用程序中。在单个位置中没有(也没有技术上不可)所有受支持属性的详尽列表,因为贡献可能来自类路径上的其他jar文件。

具有执行器功能的正在运行的应用程序具有一个configprops端点,可显示所有可用的绑定和可绑定属性@ConfigurationProperties

附录包含一个application.properties带有Spring Boot支持的最常见属性列表的示例。最终列表来自搜索源代码 @ConfigurationProperties@Value注释,以及偶尔使用 RelaxedPropertyResolver

73.嵌入式servlet容器

73.1将Servlet,Filter或Listener添加到应用程序

有两种方法来添加ServletFilterServletContextListener以及由Servlet规范到您的应用程序支持的其他听众。您可以为它们提供Spring bean,或者启用对Servlet组件的扫描。

73.1.1使用Spring bean添加一个Servlet,Filter或Listener

添加一个ServletFilter或者Servlet 为它*Listener提供一个@Bean定义。当你想注入配置或依赖时,这可能非常有用。但是,您必须非常小心,因为它们不会导致太多其他bean的急切初始化,因为它们必须在应用程序生命周期的早期安装在容器中(例如,让它们依赖于您的DataSource或JPA 并不是一个好主意组态)。您可以通过在第一次使用而不是初始化时懒惰地初始化它们来解决这些限制。

在和的情况下FiltersServlets你也可以添加映射和初始化参数,通过添加一个FilterRegistrationBean或者ServletRegistrationBean代替或作为底层组件。

[注意]

如果没有dispatcherType在注册过滤器被指定,它将匹配 FORWARDINCLUDEREQUEST。如果启用了异步,它也会匹配ASYNC

如果你正在迁移一个没有dispatcher元素的过滤器,web.xml你需要指定一个dispatcherType你自己:

@Bean
public FilterRegistrationBean myFilterRegistration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setDispatcherTypes(DispatcherType.REQUEST);
    ....

    return registration;
}
禁用Servlet或Filter的注册

如上所述任何Servlet 或Filterbean将自动注册到servlet容器。要禁用特定FilterServletbean的注册,请为其创建注册bean并将其标记为禁用。例如:

@Bean
public FilterRegistrationBean registration(MyFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}

73.1.2使用类路径扫描添加Servlet,过滤器和监听器

@WebServlet@WebFilter@WebListener注释类可以通过注释一个@Configuration@ServletComponentScan并指定包含要注册的组件的包来自动向嵌入式servlet容器注册。默认情况下,@ServletComponentScan将从注释类的包中扫描。

73.2更改HTTP端口

在独立应用程序中,主要的HTTP端口默认为8080,但可以用 server.port(例如在application.properties或作为系统属性)设置。感谢您轻松绑定Environment值,您也可以使用SERVER_PORT(例如作为一个OS环境变量)。

要完全关闭HTTP端点,但仍然创建一个WebApplicationContext,请使用server.port=-1(这对于测试有时很有用)。

有关更多详细信息 ,请参阅“Spring Boot功能”部分中的第27.3.4节“定制嵌入式servlet容器”或 ServerProperties源代码。

73.3使用随机未分配的HTTP端口

扫描一个空闲端口(使用操作系统本机防止冲突)使用server.port=0

73.4在运行时发现HTTP端口

您可以从日志输出或EmbeddedWebApplicationContext通过其访问端口来访问运行服务器的端口 EmbeddedServletContainer。最好的方法是确保已初始化,并添加一个@Bean类型, ApplicationListener<EmbeddedServletContainerInitializedEvent>并在发布时将容器从事件中拉出。

测试使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)还可以使用@LocalServerPort注释将实际端口注入到字段中。例如:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {

    @Autowired
    EmbeddedWebApplicationContext server;

    @LocalServerPort
    int port;

    // ...

}
[注意]

@LocalServerPort是一个元注释@Value("${local.server.port}")。不要试图在普通应用程序中注入端口。正如我们刚才看到的,只有在容器初始化后才会设置该值; 与测试相反,应用程序代码回调会提前处理(即在值实际可用之前)。

73.5配置SSL

可以通过设置各种server.ssl.*属性来声明性地配置SSL ,通常在application.properties或中application.yml。例如:

server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret

查看Ssl所有支持的属性的详细信息。

使用上述示例的配置意味着应用程序将不再支持8080端口上的普通HTTP连接器。Spring Boot不支持通过HTTP连接器和HTTPS连接器进行配置application.properties。如果你想拥有两者,那么你需要以编程方式配置其中之一。建议使用application.propertiesHTTPS进行配置,因为HTTP连接器更容易以编程方式进行配置。有关spring-boot-sample-tomcat-multi-connectors 示例,请参阅 示例项目。

73.6配置访问日志记录

访问日志可以通过它们各自的命名空间为Tomcat和Undertow配置。

例如,以下日志以自定义模式访问Tomcat 。

server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
[注意]

日志的默认位置是logs相对于tomcat基目录的目录,默认情况下该目录是临时目录,因此您可能需要修复Tomcat的基目录或使用日志的绝对路径。在上面的例子中,日志将my-tomcat/logs相对于应用程序的工作目录可用。

server.undertow.accesslog.enabled=true
server.undertow.accesslog.pattern=%t %a "%r" %s (%D ms)

日志存储在logs相对于应用程序工作目录的目录中。这可以通过定制server.undertow.accesslog.directory

73.7在前端代理服务器后面使用

您的应用程序可能需要发送302重定向或使用绝对链接呈现内容。当在代理后面运行时,调用者需要链接到代理,而不是托管应用的机器的物理地址。通常情况下,这种情况是通过与代理签订合同来处理的,代理将添加标题以告知后端如何构建到自身的链接。

如果代理添加了常规X-Forwarded-ForX-Forwarded-Proto标题(大多数情况下是这样做的),绝对链接应该被正确渲染,只要 在你的server.use-forward-headers设置trueapplication.properties

[注意]

如果您的应用程序在Cloud Foundry或Heroku中运行,则该 server.use-forward-headers属性将默认为true未指定。在所有其他情况下,它默认为false

73.7.1自定义Tomcat的代理配置

如果您使用的是Tomcat,则可以另外配置用于携带“转发”信息的标头的名称:

server.tomcat.remote-ip-header=x-your-remote-ip-header
server.tomcat.protocol-header=x-your-protocol-header

Tomcat还配置了一个默认正则表达式,该正则表达式与要受信任的内部代理相匹配。默认情况下,IP地址中10/8192.168/16, 169.254/16127/8是值得信赖的。您可以通过添加一个条目来自定义阀门的配置application.properties,例如

server.tomcat.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
[注意]

只有在使用属性文件进行配置时才需要双反斜杠。如果您使用的是YAML,则单个反斜杠就足够了,并且与上面显示的值相等的值192\.168\.\d{1,3}\.\d{1,3}

[注意]

您可以通过设置internal-proxies为空来信任所有代理(但不要在生产中这样做)。

您可以RemoteIpValve通过切换自动关闭(即设置server.use-forward-headers=false)和添加一个新的阀门实例来完全控制Tomcat的配置TomcatEmbeddedServletContainerFactory

73.8配置Tomcat

一般来说,你可以从以下建议 第72.8,“探索外部性内置选项”有关 @ConfigurationPropertiesServerProperties主要是一个在这里),还要看看EmbeddedServletContainerCustomizer各种针对Tomcat *Customizers,您可以在其中的一个补充。Tomcat API非常丰富,所以一旦你有权访问TomcatEmbeddedServletContainerFactory你可以用多种方式修改它。或者核选择是增加你自己的TomcatEmbeddedServletContainerFactory

73.9使用Tomcat启用多个连接器

一个添加org.apache.catalina.connector.Connector到 TomcatEmbeddedServletContainerFactory其可允许多个连接器,例如HTTP和HTTPS连接器:

@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
    tomcat.addAdditionalTomcatConnectors(createSslConnector());
    return tomcat;
}

private Connector createSslConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
    try {
        File keystore = new ClassPathResource("keystore").getFile();
        File truststore = new ClassPathResource("keystore").getFile();
        connector.setScheme("https");
        connector.setSecure(true);
        connector.setPort(8443);
        protocol.setSSLEnabled(true);
        protocol.setKeystoreFile(keystore.getAbsolutePath());
        protocol.setKeystorePass("changeit");
        protocol.setTruststoreFile(truststore.getAbsolutePath());
        protocol.setTruststorePass("changeit");
        protocol.setKeyAlias("apitester");
        return connector;
    }
    catch (IOException ex) {
        throw new IllegalStateException("can't access keystore: [" + "keystore"
                + "] or truststore: [" + "keystore" + "]", ex);
    }
}

73.10使用Tomcat的LegacyCookieProcessor

Spring Boot使用的嵌入式Tomcat不支持开箱即用的Cookie格式的“版本0”,并且您可能会看到以下错误:

java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value

如果可能的话,你应该考虑更新你的代码,以便只存储符合以后Cookie规范的值。但是,如果您无法更改Cookie写入的方式,则可以将Tomcat配置为使用LegacyCookieProcessor。要切换到LegacyCookieProcessor使用EmbeddedServletContainerCustomizer添加了TomcatContextCustomizer以下内容的 bean :

@Bean
public EmbeddedServletContainerCustomizer cookieProcessorCustomizer() {
    return new EmbeddedServletContainerCustomizer() {

        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            if (container instanceof TomcatEmbeddedServletContainerFactory) {
                ((TomcatEmbeddedServletContainerFactory) container)
                        .addContextCustomizers(new TomcatContextCustomizer() {

                            @Override
                            public void customize(Context context) {
                                context.setCookieProcessor(
                                        new LegacyCookieProcessor());
                            }

                        });
            }
        }

    };
}

73.11使用Jetty代替Tomcat

Spring Boot初学者(spring-boot-starter-web特别是)默认使用Tomcat作为嵌入式容器。您需要排除这些依赖关系,然后包括Jetty。Spring Boot将Tomcat和Jetty依赖关系捆绑在一起,作为单独的初始者,以帮助使此过程尽可能地简单。

Maven中的示例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

Gradle中的示例:

configurations {
    compile.exclude module: "spring-boot-starter-tomcat"
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.5.14.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-jetty:1.5.14.RELEASE")
    // ...
}

73.12配置码头

一般来说,您可以按照 第72.8节“探索外部属性的内置选项”@ConfigurationProperties(关于 ServerProperties这里是主要的选项)的建议,还可以看一下EmbeddedServletContainerCustomizer。Jetty API非常丰富,所以一旦你有权访问JettyEmbeddedServletContainerFactory你可以用多种方式修改它。或者核选择是增加你自己的JettyEmbeddedServletContainerFactory

73.13使用Undertow而不是Tomcat

使用Undertow而不是Tomcat与使用Jetty而不是Tomcat非常相似。您需要排除Tomcat依赖关系,并包含Undertow启动器。

Maven中的示例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

Gradle中的示例:

configurations {
    compile.exclude module: "spring-boot-starter-tomcat"
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.5.14.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-undertow:1.5.14.RELEASE")
    // ...
}

73.14配置Undertow

一般来说,你可以遵循的建议 第72.8,“探索外部性内置选项”有关 @ConfigurationPropertiesServerPropertiesServerProperties.Undertow是这里的主要的),还看 EmbeddedServletContainerCustomizer。一旦你有权访问 UndertowEmbeddedServletContainerFactory你可以使用UndertowBuilderCustomizer修改Undertow的配置来满足你的需求。或者核选择是增加你自己的UndertowEmbeddedServletContainerFactory

73.15使用Undertow启用多个监听器

一个加入UndertowBuilderCustomizerUndertowEmbeddedServletContainerFactory和监听器添加到Builder

@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
    UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
    factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {

        @Override
        public void customize(Builder builder) {
            builder.addHttpListener(8080, "0.0.0.0");
        }

    });
    return factory;
}

73.16使用Tomcat 7.x或8.0

Tomcat 7和8.0使用Spring Boot,但默认使用Tomcat 8.5。如果您不能使用Tomcat 8.5(例如,因为您使用的是Java 1.6),则需要更改类路径以引用不同的版本。

73.16.1在Maven中使用Tomcat 7.x或8.0

如果您正在使用starters和parent,则可以更改Tomcat版本属性并另外导入tomcat-juli。例如,对于简单的Web应用程序或服务:

<properties>
    <tomcat.version>7.0.59</tomcat.version>
</properties>
<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-juli</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    ...
</dependencies>

73.16.2在Gradle中使用Tomcat 7.x或8.0

借助Gradle,您可以通过设置tomcat.version属性来更改Tomcat版本,并且还包括tomcat-juli

ext['tomcat.version'] = '7.0.59'
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'
    compile group:'org.apache.tomcat', name:'tomcat-juli', version:property('tomcat.version')
}

73.17使用Jetty 9.2

Jetty 9.2适用于Spring Boot,但默认情况下使用Jetty 9.3。如果您不能使用Jetty 9.3(例如,因为您正在使用Java 7),则需要将您的类路径更改为参考Jetty 9.2。

73.17.1在Maven中使用Jetty 9.2

如果您使用的是初学者和家长,则可以添加Jetty启动器并覆盖该jetty.version属性:

<properties>
    <jetty.version>9.2.17.v20160517</jetty.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
</dependencies>

73.17.2在Gradle中使用Jetty 9.2

您可以设置jetty.version属性。例如,对于简单的Web应用程序或服务:

ext['jetty.version'] = '9.2.17.v20160517'
dependencies {
    compile ('org.springframework.boot:spring-boot-starter-web') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
    }
    compile ('org.springframework.boot:spring-boot-starter-jetty')
}

73.18使用Jetty 8

Jetty 8适用于Spring Boot,但默认情况下使用Jetty 9.3。如果您不能使用Jetty 9.3(例如,因为您使用的是Java 1.6),则需要将类路径更改为引用Jetty 8.您还需要排除Jetty的与WebSocket相关的依赖项。

73.18.1在Maven中使用Jetty 8

如果您使用的是初学者和家长,那么您可以将Jetty入门版添加所需的WebSocket排除功能,并更改版本属性,例如,对于简单的Web应用程序或服务:

<properties>
    <jetty.version>8.1.15.v20140411</jetty.version>
    <jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.eclipse.jetty.websocket</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

73.18.2使用带Gradle的Jetty 8

您可以设置该jetty.version属性并排除WebSocket依赖项,例如对于简单的Web应用程序或服务:

ext['jetty.version'] = '8.1.15.v20140411'
dependencies {
    compile ('org.springframework.boot:spring-boot-starter-web') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
    }
    compile ('org.springframework.boot:spring-boot-starter-jetty') {
        exclude group: 'org.eclipse.jetty.websocket'
    }
}

73.19使用@ServerEndpoint创建WebSocket端点

如果您想在使用@ServerEndpoint嵌入式容器的Spring Boot应用程序中使用,则必须声明一个ServerEndpointExporter @Bean

@Bean
public ServerEndpointExporter serverEndpointExporter() {
    return new ServerEndpointExporter();
}

这个bean将注册任何带@ServerEndpoint注释的bean和底层的WebSocket容器。当部署到独立的servlet容器时,该角色由servlet容器初始化程序执行,并且ServerEndpointExporter不需要该bean。

73.20启用HTTP响应压缩

Jetty,Tomcat和Undertow支持HTTP响应压缩。它可以通过application.properties以下方式启用:

server.compression.enabled=true

默认情况下,为了执行压缩,响应长度必须至少为2048个字节。这可以使用server.compression.min-response-size 属性进行配置。

默认情况下,只有在响应内容类型为以下内容时才会压缩响应:

  • text/html
  • text/xml
  • text/plain
  • text/css

这可以使用server.compression.mime-types属性进行配置。

74. Spring MVC

74.1编写一个JSON REST服务

@RestController只要Jackson2位于类路径中,Spring Boot应用程序中的任何Spring 都应默认呈现JSON响应。例如:

@RestController
public class MyController {

    @RequestMapping("/thing")
    public MyThing thing() {
            return new MyThing();
    }

}

只要MyThing可以由Jackson2序列化(例如普通的POJO或Groovy对象)localhost:8080/thing,默认情况下将为其提供JSON表示。有时在浏览器中可能会看到XML响应,因为浏览器倾向于发送喜欢XML的接受标头。

74.2编写XML REST服务

如果您jackson-dataformat-xml在类路径中具有Jackson XML扩展名(),则它将用于呈现XML响应,并且与我们用于JSON的例子相同。要使用它,请将以下依赖项添加到您的项目中:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

您可能还想添加对Woodstox的依赖关系。它比JDK提供的默认StAX实现更快,并且还增加了漂亮的打印支持和改进的命名空间处理:

<dependency>
    <groupId>org.codehaus.woodstox</groupId>
    <artifactId>woodstox-core-asl</artifactId>
</dependency>

如果Jackson的XML扩展不可用,则将使用JAXB(在JDK中默认提供),并且附加要求MyThing注释为 @XmlRootElement

@XmlRootElement
public class MyThing {
    private String name;
    // .. getters and setters
}

要让服务器呈现XML而不是JSON,您可能必须发送一个 Accept: text/xml标头(或使用浏览器)。

74.3自定义Jackson ObjectMapper

Spring MVC(客户端和服务器端)用于HttpMessageConverters在HTTP交换中协商内容转换。如果Jackson在类路径中,则已经获得了由其提供的默认转换器Jackson2ObjectMapperBuilder,其中的一个实例将为您自动配置。

默认创建的ObjectMapper(或XmlMapper用于Jackson XML转换器)实例具有以下自定义属性:

  • MapperFeature.DEFAULT_VIEW_INCLUSION 被禁用
  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 被禁用

Spring Boot还具有一些功能,可以更轻松地自定义此行为。

您可以使用该环境配置ObjectMapperXmlMapper实例。Jackson提供了一整套简单的开/关功能,可用于配置其处理的各个方面。这些功能在杰克逊的六个枚举中进行了描述,映射到环境中的属性:

ackson enumEnvironment property

com.fasterxml.jackson.databind.DeserializationFeature

spring.jackson.deserialization.<feature_name>=true|false

com.fasterxml.jackson.core.JsonGenerator.Feature

spring.jackson.generator.<feature_name>=true|false

com.fasterxml.jackson.databind.MapperFeature

spring.jackson.mapper.<feature_name>=true|false

com.fasterxml.jackson.core.JsonParser.Feature

spring.jackson.parser.<feature_name>=true|false

com.fasterxml.jackson.databind.SerializationFeature

spring.jackson.serialization.<feature_name>=true|false

com.fasterxml.jackson.annotation.JsonInclude.Include

spring.jackson.default-property-inclusion=always|non_null|non_absent|non_default|non_empty

例如,要启用漂亮的打印,请设置spring.jackson.serialization.indent_output=true。请注意,由于使用了宽松的绑定,所以indent_output不需要匹配相应的枚举常量的情况INDENT_OUTPUT

此基于环境的配置应用于自动配置的 Jackson2ObjectMapperBuilderbean,并将应用于使用构建器创建的任何映射器,包括自动配置的ObjectMapperbean。

上下文Jackson2ObjectMapperBuilder可以由一个或多个Jackson2ObjectMapperBuilderCustomizerbean 自定义 。这些定制程序bean可以订购,而Boot自己的定制程序的订购数量为0,允许在定制Boot的前后应用其他定制。

任何类型的bean com.fasterxml.jackson.databind.Module将自动注册到自动配置Jackson2ObjectMapperBuilder并应用于ObjectMapper 它创建的任何实例。这为您在向应用程序添加新功能时提供了一种全球机制,可以为自定义模块提供支持

如果要ObjectMapper完全替换默认值,请定义@Bean该类型的标记并将其标记为@Primary,或者,如果您更喜欢基于构建器的方法,请定义一个Jackson2ObjectMapperBuilder @Bean。请注意,在任何情况下,这将禁用所有的自动配置ObjectMapper

如果您提供了任何@Beans类型,MappingJackson2HttpMessageConverter那么它们将替换MVC配置中的默认值。此外,还提供了一个便利bean类型HttpMessageConverters(如果您使用默认的MVC配置,总是可用的),它有一些有用的方法来访问默认和用户增强的消息转换器。

有关 更多详细信息另请参阅第74.4节“自定义@ResponseBody呈现”部分和 WebMvcAutoConfiguration源代码。

74.4自定义@ResponseBody呈现

Spring HttpMessageConverters用来渲染@ResponseBody(或来自 @RestController)。您可以通过在Spring Boot上下文中简单添加该类型的Bean来贡献其他转换器。如果您添加的bean是默认包含的类型(如MappingJackson2HttpMessageConverter用于JSON转换),那么它将替换默认值。一个便利bean提供了类型HttpMessageConverters(如果你使用默认的MVC配置,总是可用的),它有一些有用的方法来访问默认的和用户增强的消息转换器(例如,如果你想手动将它们注入到自定义中RestTemplate)。

和正常的MVC用法一样,WebMvcConfigurerAdapter你提供的任何bean都可以通过重载configureMessageConverters方法来提供转换器,但与普通MVC不同的是,你只能提供你需要的额外的转换器(因为Spring Boot使用相同的机制来提供它的默认值)。最后,如果您通过提供自己的@EnableWebMvc配置选择退出Spring Boot默认MVC 配置,那么您可以完全控制并使用getMessageConverters从中手动执行所有操作 WebMvcConfigurationSupport

有关WebMvcAutoConfiguration 更多详细信息,请参阅源代码。

74.5处理多部分文件上传

Spring Boot包含Servlet 3 javax.servlet.http.PartAPI以支持上传文件。默认情况下,Spring Boot以每个文件1MB的最大文件和一个请求中最多10MB的文件数据配置Spring MVC。您可以/tmp 通过使用MultipartProperties类中公开的属性来覆盖这些值以及中间数据存储的位置(例如,目录)以及数据刷新到磁盘的阈值。例如,如果要指定文件不受限制,请将该spring.http.multipart.max-file-size属性设置为-1

当您想要在Spring MVC控制器处理程序方法中将多部分编码文件数据作为@RequestParam类型的注释参数接收时,多部分支持很有用MultipartFile

查看MultipartAutoConfiguration 来源获取更多细节。

74.6关闭Spring MVC DispatcherServlet

Spring Boot希望/向下提供应用程序根目录中的所有内容。如果您宁愿将自己的servlet映射到该URL,则可以这样做,但当然可能会失去其他一些Boot MVC功能。要添加自己的servlet并将其映射到根资源,只需声明一个@Bean类型Servlet并为其指定特殊的bean名称 dispatcherServlet(如果要将其关闭并且不替换它,也可以使用该名称创建不同类型的bean) 。

74.7关闭默认的MVC配置

完全控制MVC配置的最简单方法是提供自己 @Configuration@EnableWebMvc注释。这将使所有的MVC配置都在你手中。

74.8自定义ViewResolvers

ViewResolver是Spring MVC的核心组件,将视图名称转换 @Controller为实际的View实现。请注意,ViewResolvers它们主要用于UI应用程序,而不是REST风格的服务(a View不用于渲染@ResponseBody)。有许多ViewResolver可供选择的实现,Spring本身并不认为你应该使用哪一个。另一方面,Spring Boot根据在类路径和应用程序上下文中找到的内容,为您安装一个或两个。在DispatcherServlet使用所有解析器发现在应用方面,试着用每一个转动,直到它得到的结果,因此,如果您要添加自己的,你必须要知道的秩序,在加入哪个位置您解析。

WebMvcAutoConfiguration将以下内容添加ViewResolvers到上下文中:

  • InternalResourceViewResolver豆ID“defaultViewResolver”。这个定位可以使用DefaultServlet(例如静态资源和JSP页面,如果你正在使用的话)呈现的物理资源。它将前缀和后缀应用于视图名称,然后在servlet上下文中查找具有该路径的物理资源(默认值均为空,但可通过spring.mvc.view.prefixand 访问外部配置 spring.mvc.view.suffix)。它可以通过提供相同类型的bean来覆盖。
  • 一个BeanNameViewResolverID为'beanNameViewResolver'的。这是视图解析器链的一个有用的成员,并且将会选取与View正在解析的名称相同的任何bean 。不应该有必要重写或替换它。
  • ContentNegotiatingViewResolverID为“的ViewResolver”如果只有加入 实际类型的豆View存在。这是一个“主”解析器,委托给所有其他人,并试图找到与客户端发送的“Accept”HTTP头匹配。有一个有用的 博客ContentNegotiatingViewResolver ,您可能想了解更多信息,也可以查看源代码以了解详细信息。您可以ContentNegotiatingViewResolver通过定义一个名为'viewResolver'的bean 来关闭自动配置 。
  • 如果您使用Thymeleaf,您也将拥有一个ThymeleafViewResolverID为'thymeleafViewResolver'的ID。它通过用前缀和后缀来包围视图名称来寻找资源(分别用于外部化spring.thymeleaf.prefix和 spring.thymeleaf.suffix默认'classpath:/ templates /'和'.html')。它可以通过提供相同名称的bean来覆盖。
  • 如果你使用FreeMarker,你也会有一个FreeMarkerViewResolverid为'freeMarkerViewResolver'的。它会在加载器路径资源(外部化到spring.freemarker.templateLoaderPath,默认的“类路径:/模板/”)用前缀和后缀周边视图名称(外部化到spring.freemarker.prefixspring.freemarker.suffix分别与空而“.ftl”默认值)。它可以通过提供相同名称的bean来覆盖。
  • 如果您使用Groovy模板(实际上,如果groovy-templates位于您的类路径中),您还将GroovyMarkupViewResolver使用id为“groovyMarkupViewResolver”。它通过用前缀和后缀(分别外化到spring.groovy.template.prefix和 spring.groovy.template.suffix默认'classpath:/ templates /'和'.tpl')来包围视图名称来查找加载器路径中的资源。它可以通过提供相同名称的bean来覆盖。

退房WebMvcAutoConfiguration, ThymeleafAutoConfiguration, FreeMarkerAutoConfiguration和 GroovyTemplateAutoConfiguration

74.9使用Thymeleaf 3

默认情况下,spring-boot-starter-thymeleaf使用Thymeleaf 2.1。如果您使用的是 spring-boot-starter-parent,您可以通过重写thymeleaf.versionthymeleaf-layout-dialect.version属性来使用Thymeleaf 3 ,例如:

<properties>
    <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
</properties>
[注意]

如果您自己在管理依赖关系,请查看spring-boot-dependencies与这两个版本相关的工件列表。

为了避免对被弃用的HTML 5模板模式和HTML模板模式的警告信息被用来代替,你可能还需要明确配置 spring.thymeleaf.modeHTML,例如:

spring.thymeleaf.mode: HTML

请参阅 Thymeleaf 3样本以查看这一行动。

如果您正在使用任何其他自动配置的Thymeleaf Extras(Spring安全性,数据属性或Java 8时间),您还应该将其每个版本覆盖为与Thymeleaf 3.0兼容的版本。

75. Jersey

75.1使用Spring Security来保护Jersey端点

Spring Security可以用来保护一个基于Jersey的Web应用程序,就像它可以用来保护基于Spring MVC的Web应用程序一样。但是,如果你想使用与新泽西州Spring Security的方法级别的安全性,您必须配置泽西使用setStatus(int)相当sendError(int)。这可以防止Jersey在Spring Security有机会向客户端报告身份验证或授权失败之前提交响应。

jersey.config.server.response.setStatusOverSendError必须设置为true应用的ResourceConfig豆类,如下面的例子:

@Component
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        register(Endpoint.class);
        setProperties(Collections.singletonMap(
                "jersey.config.server.response.setStatusOverSendError", true));
    }

}

76. HTTP客户端

76.1配置RestTemplate以使用代理

第33.1节“RestTemplate自定义”中所述RestTemplateCustomizer可以使用RestTemplateBuildera来构建自定义 RestTemplate。这是创建RestTemplate配置为使用代理的推荐方法。

代理配置的确切细节取决于正在使用的底层客户端请求工厂。下面是配置的一个例子 HttpComponentsClientRequestFactoryHttpClient使用以外的所有主机的代理192.168.0.5

static class ProxyCustomizer implements RestTemplateCustomizer {

    @Override
    public void customize(RestTemplate restTemplate) {
        HttpHost proxy = new HttpHost("proxy.example.com");
        HttpClient httpClient = HttpClientBuilder.create()
                .setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {

                    @Override
                    public HttpHost determineProxy(HttpHost target,
                            HttpRequest request, HttpContext context)
                            throws HttpException {
                        if (target.getHostName().equals("192.168.0.5")) {
                            return null;
                        }
                        return super.determineProxy(target, request, context);
                    }

                }).build();
        restTemplate.setRequestFactory(
                new HttpComponentsClientHttpRequestFactory(httpClient));
    }

}

77. Logging

Spring Boot没有强制日志依赖性,Commons Logging API除外,其中有许多实现可供选择。要使用Logback, 你需要jcl-over-slf4j在类路径中包含它和(它实现Commons Logging API)。最简单的方法是通过所有依赖的初学者 spring-boot-starter-logging。对于Web应用程序,您只需要 spring-boot-starter-web它,因为它依赖于日志启动器。例如,使用Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot有一个LoggingSystem抽象,试图根据类路径的内容配置日志记录。如果Logback可用,它是首选。

如果您需要对日志记录进行的唯一更改是设置各种日志记录器的级别,那么您可以application.properties使用“logging.level”前缀来完成此操作,例如

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

您还可以使用“logging.file”设置要登录的文件的位置(除了控制台之外)。

要配置日志记录系统的更精细的设置,您需要使用LoggingSystem问题支持的本机配置格式。默认情况下,Spring Boot从系统的默认位置(例如classpath:logback.xmlLogback)中选取本机配置 ,但可以使用“logging.config”属性设置配置文件的位置。

77.1配置Logback进行日志记录

如果你把logback.xml类放在你的类路径的根目录中,它会从那里拾取(或者logback-spring.xml利用Boot提供的模板功能)。Spring Boot提供了一个默认的基本配置,如果你只是想设置级别,你可以包含这个配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <logger name="org.springframework.web" level="DEBUG"/>
</configuration>

如果你base.xml在spring-boot jar中看到它,你会发现它使用了一些有用的系统属性,这些属性LoggingSystem会为你创建。这些是:

  • ${PID} 当前进程ID。
  • ${LOG_FILE}如果logging.file在Boot的外部配置中设置。
  • ${LOG_PATH}如果logging.path已设置(表示日志文件所在的目录)。
  • ${LOG_EXCEPTION_CONVERSION_WORD}如果logging.exception-conversion-word在Boot的外部配置中设置。

Spring Boot还使用自定义的Logback转换器在控制台(但不是日志文件)上提供一些漂亮的ANSI彩色终端输出。详情请参阅默认base.xml配置。

如果Groovy位于类路径中,您应该能够配置Logback logback.groovy(如果存在,将会给予优先权)。

77.1.1为仅文件输出配置logback

如果要禁用控制台日志记录并仅将输出写入文件,则需要logback-spring.xml导入的自定义 ,file-appender.xml但不要console-appender.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
    <root level="INFO">
        <appender-ref ref="FILE" />
    </root>
</configuration>

您还需要添加logging.file到您的application.properties

logging.file=myapplication.log

77.2配置Log4j进行日志记录

Spring Boot支持Log4j 2用于记录配置,如果它在类路径上。如果您使用starters来组装依赖关系,那意味着您必须排除Logback,然后包含log4j 2。如果您没有使用启动器,那么jcl-over-slf4j 除了Log4j 2之外,您还需要提供(至少)。

最简单的路径可能是通过初学者,即使它需要一些与Maven中的排除,例如:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
[注意]

Log4j入门者的使用收集了常见日志需求的依赖关系(例如,包括使用Tomcat,java.util.logging但使用Log4j 2配置输出)。有关更多详细信息,请参阅执行器Log4j 2样本,并查看它的实际使用情况。

[注意]

要确保使用的调试日志记录java.util.logging路由到Log4j 2,请通过将系统属性 设置为,配置其JDK日志记录适配器java.util.logging.managerorg.apache.logging.log4j.jul.LogManager

77.2.1使用YAML或JSON配置Log4j 2

除了默认的XML配置格式之外,Log4j 2还支持YAML和JSON配置文件。要将Log4j 2配置为使用备用配置文件格式,请将相应的依赖关系添加到类路径中,并将您的配置文件命名为符合您选择的文件格式:

FormatDependenciesFile names

YAML

com.fasterxml.jackson.core:jackson-databindcom.fasterxml.jackson.dataformat:jackson-dataformat-yaml

log4j2.yamllog4j2.yml

JSON

com.fasterxml.jackson.core:jackson-databind

log4j2.jsonlog4j2.jsn

78.数据访问

78.1配置一个自定义数据源

在你的配置中配置你自己DataSource定义@Bean的那种类型。Spring Boot将重用您DataSource需要的任何地方,包括数据库初始化。如果您需要将某些设置外部化,则可以轻松地将其绑定 DataSource到环境(请参见 第24.7.1节“第三方配置”)。

@Bean
@ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() {
    return new FancyDataSource();
}
app.datasource.url=jdbc:h2:mem:mydb
app.datasource.username=sa
app.datasource.pool-size=30

假设您FancyDataSource的url,用户名和池大小具有常规的JavaBean属性,这些设置将在DataSource其他组件可用之前自动绑定 。常规的 数据库初始化也会发生(因此相关的子集spring.datasource.*仍然可以用于您的自定义配置)。

如果您正在配置自定义JNDI,则可以应用相同的原则DataSource

@Bean(destroyMethod="")
@ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() throws Exception {
    JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
    return dataSourceLookup.getDataSource("java:comp/env/jdbc/YourDS");
}

Spring Boot还提供了一个实用程序构建器类DataSourceBuilder,可用于创建其中一个标准数据源(如果它位于类路径中)。构建器可以根据类路径上可用的内容来检测要使用的那个。它还会根据JDBC URL自动检测驱动程序

@Bean
@ConfigurationProperties("app.datasource")
public DataSource dataSource() {
    return DataSourceBuilder.create().build();
}

为了运行一个应用程序DataSource,所需要的只是连接信息; 还可以提供特定于池的设置,请检查将在运行时使用的实现以获取更多详细信息

app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30

但有一个问题。由于连接池的实际类型未公开,因此您的自定义元数据中不会生成任何键,DataSource并且您的IDE中没有可用的完成(该DataSource界面不会公开任何属性)。另外,如果你碰巧在类路径上只有 Hikari,这个基本设置将不起作用,因为Hikari没有url参数(但是是一个jdbcUrl参数)。您将不得不按照以下方式重写您的配置:

app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30

你可以通过强制使用连接池并返回一个专用的实现来解决这个问题DataSource。您将无法在运行时更改实现,但选项列表将是明确的。

@Bean
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource() {
    return (HikariDataSource) DataSourceBuilder.create()
            .type(HikariDataSource.class).build();
}

你甚至可以进一步利用DataSourceProperties它为你提供一个默认的嵌入式数据库,如果没有提供一个明智的用户名和密码的URL。你可以很容易地DataSourceBuilder从任何状态初始化一个, DataSourceProperties所以你可以注入Spring Boot自动创建的一个。但是,这会将您的配置拆分为两个命名空间:url,用户名,密码,类型和驱动程序,spring.datasource以及其他自定义命名空间(app.datasource)。为了避免这种情况,您可以DataSourceProperties在自定义名称空间上重新定义自 定义:

@Bean
@Primary
@ConfigurationProperties("app.datasource")
public DataSourceProperties dataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource(DataSourceProperties properties) {
    return (HikariDataSource) properties.initializeDataSourceBuilder()
            .type(HikariDataSource.class).build();
}

除了选择了一个专用的连接池(在代码中)并且它的设置暴露在相同的命名空间中之外,这个设置使您与默认情况下的Spring Boot为您做的配对。由于DataSourceProperties正在 为您翻译urljdbcUrl翻译,您可以像这样配置它:

app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30
[注意]

因为您的自定义配置选择与Hikari一起使用,app.datasource.type 将不起作用。在实践中,建筑师将被初始化为您可能设置的任何值,然后被呼叫覆盖.type()

有关 更多详细信息请参见“Spring Boot功能”部分和 DataSourceAutoConfiguration类中的第29.1节“配置数据源”

78.2配置两个数据源

如果您需要配置多个数据源,则可以应用上一节中介绍的相同技巧。但是,您必须标记出其中一种DataSource @Primary不同的自动配置,希望能够逐个获取。

如果你自己创建DataSource,自动配置将退出。在下面的示例中,我们提供了与自动配置在主数据源上提供的功能完全相同的功能集:

@Bean
@Primary
@ConfigurationProperties("app.datasource.foo")
public DataSourceProperties fooDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@Primary
@ConfigurationProperties("app.datasource.foo")
public DataSource fooDataSource() {
    return fooDataSourceProperties().initializeDataSourceBuilder().build();
}

@Bean
@ConfigurationProperties("app.datasource.bar")
public BasicDataSource barDataSource() {
    return (BasicDataSource) DataSourceBuilder.create()
            .type(BasicDataSource.class).build();
}
[小费]

fooDataSourceProperties必须进行标记,@Primary以便数据库初始化程序功能使用您的副本(如果使用的话)。

这两个数据源也都是用于高级自定义的。例如,你可以如下配置它们:

app.datasource.foo.type=com.zaxxer.hikari.HikariDataSource
app.datasource.foo.maximum-pool-size=30

app.datasource.bar.url=jdbc:mysql://localhost/test
app.datasource.bar.username=dbuser
app.datasource.bar.password=dbpass
app.datasource.bar.max-total=30

当然,您也可以将相同的概念应用于辅助DataSource

@Bean
@Primary
@ConfigurationProperties("app.datasource.foo")
public DataSourceProperties fooDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@Primary
@ConfigurationProperties("app.datasource.foo")
public DataSource fooDataSource() {
    return fooDataSourceProperties().initializeDataSourceBuilder().build();
}

@Bean
@ConfigurationProperties("app.datasource.bar")
public DataSourceProperties barDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("app.datasource.bar")
public DataSource barDataSource() {
    return barDataSourceProperties().initializeDataSourceBuilder().build();
}

这个最后的例子使用与Spring Boot在自动配置中完成的逻辑相同的逻辑在自定义命名空间上配置两个数据源。

78.3使用Spring Data存储库

Spring Data可以为您创建@Repository各种风格的接口。只要那些@Repositories 包含在你@EnableAutoConfiguration 班级的同一个包(或一个子包)中,Spring Boot将为你处理所有这些事情。

对于许多应用程序,您只需将正确的Spring Data依赖项放在您的类路径中(spring-boot-starter-data-jpa对于JPA和spring-boot-starter-data-mongodbMongodb 有一个),创建一些存储库接口来处理您的 @Entity对象。例子在JPA示例 或Mongodb示例中

Spring Boot尝试根据找到的内容猜测@Repository定义 的位置@EnableAutoConfiguration。为了获得更多控制权,请使用@EnableJpaRepositories 注释(来自Spring Data JPA)。

78.4来自Spring配置的单独实体定义

Spring Boot尝试根据找到的内容猜测@Entity定义 的位置@EnableAutoConfiguration。为了获得更多控制,可以使用@EntityScan 注释,例如

@Configuration
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
public class Application {

    //...

}

78.5配置JPA属性

Spring Data JPA已经提供了一些与供应商无关的配置选项(例如用于SQL日志记录),Spring Boot公开了这些,还有一些作为外部配置属性的hibernate。其中一些是根据上下文自动检测的,所以您不必设置它们。

spring.jpa.hibernate.ddl-auto是一个特殊情况,因为它具有不同的默认值,具体取决于您是使用嵌入式数据库(create-drop)还是不使用(none)。使用的方言也可以根据当前情况自动检测,DataSourcespring.jpa.database如果您想明确并在启动时绕过该检查,则可以设置自己的方言。

[注意]

指定一个database导致定义明确的Hibernate方言的配置。有几个数据库有不止一个Dialect,这可能不适合您的需要。在这种情况下,您可以设置spring.jpa.databasedefault让Hibernate将事情弄清楚或使用spring.jpa.database-platform属性设置方言。

最常见的选项有:

spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy
spring.jpa.show-sql=true

此外,创建spring.jpa.properties.*本地时,所有属性都将作为正常的JPA属性(剥离前缀)传递EntityManagerFactory

78.6配置Hibernate命名策略

Spring Boot提供了一致的命名策略,无论您使用的是何种Hibernate代理。如果你使用的是Hibernate 4,你可以使用 spring.jpa.hibernate.naming.strategy; 休眠5定义PhysicalImplicit 命名策略。

Spring Boot SpringPhysicalNamingStrategy默认配置。这个实现提供了与Hibernate 4相同的表结构:所有的点都被下划线替代,而且驼峰也被下划线替换。默认情况下,所有表名都以小写形式生成,但如果您的模式需要它,则可以覆盖该标志。

具体来说,一个TelephoneNumber实体将被映射到该telephone_number表。

如果您宁愿使用Hibernate 5的默认值,请设置以下属性:

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

请参阅HibernateJpaAutoConfiguration 并JpaBaseConfiguration 了解更多详情。

78.7使用一个自定义的EntityManagerFactory

要完全控制配置EntityManagerFactory,你需要添加一个@Bean名为'entityManagerFactory'。Spring Boot自动配置根据该类型的bean的存在关闭其实体管理器。

78.8使用两个EntityManagers

即使默认EntityManagerFactory工作正常,您将需要定义一个新的,因为否则该类型的第二个bean的存在将关闭默认值。为了简化操作,您可以使用EntityManagerBuilder Spring Boot提供的便利,或者如果您愿意,可以直接使用 LocalContainerEntityManagerFactoryBeanSpring ORM。

例:

// add two data sources configured as above

@Bean
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
        EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(customerDataSource())
            .packages(Customer.class)
            .persistenceUnit("customers")
            .build();
}

@Bean
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
        EntityManagerFactoryBuilder builder) {
    return builder
            .dataSource(orderDataSource())
            .packages(Order.class)
            .persistenceUnit("orders")
            .build();
}

上面的配置几乎可以自行完成。要完成图片,您还需要配置TransactionManagers两者EntityManagersJpaTransactionManager如果将其标记为,则其中一个可以由Spring Boot中 的默认值选取@Primary。另一个必须明确地注入一个新的实例。或者你也许可以使用跨越两者的JTA事务管理器。

如果您使用的是Spring Data,则需要相应地进行配置@EnableJpaRepositories

@Configuration
@EnableJpaRepositories(basePackageClasses = Customer.class,
        entityManagerFactoryRef = "customerEntityManagerFactory")
public class CustomerConfiguration {
    ...
}

@Configuration
@EnableJpaRepositories(basePackageClasses = Order.class,
        entityManagerFactoryRef = "orderEntityManagerFactory")
public class OrderConfiguration {
    ...
}

78.9使用传统的persistence.xml

Spring Boot将不会搜索或META-INF/persistence.xml默认使用。如果你喜欢使用传统的persistence.xml,你需要定义你自己@Bean的类型LocalEntityManagerFactoryBean(id为'entityManagerFactory',并在那里设置持久化单元名称。

请参阅 JpaBaseConfiguration 默认设置。

78.10使用Spring Data JPA和Mongo仓库

Spring Data JPA和Spring Data Mongo都可以Repository自动为您创建实现。如果它们都出现在类路径中,那么您可能需要做一些额外的配置来告诉Spring Boot您想为您创建哪一个(或两者)存储库。最明显的方法是使用标准的Spring Data @Enable*Repositories并告诉它Repository接口的位置('*'是'Jpa'或'Mongo'或两者)。

还有一些标志spring.data.*.repositories.enabled可用于在外部配置中打开和关闭自动配置的存储库。例如,如果您想关闭Mongo存储库并仍然使用自动配置,这很有用MongoTemplate

其他自动配置的Spring Data存储库类型(Elasticsearch,Solr)存在相同的障碍和相同的功能。只需分别更改注释和标志的名称即可。

78.11将Spring Data存储库公开为REST端点

Repository只要为应用程序启用了Spring MVC,Spring Data REST就可以将实现公开为REST端点。

Spring Boot公开了一组spring.data.rest自定义命名空间 的有用属性RepositoryRestConfiguration。如果你需要提供额外的定制,你应该使用一个RepositoryRestConfigurer bean。

[注意]

如果你没有在你的定制中指定任何顺序,RepositoryRestConfigurer它将在一个Spring Boot在内部使用后运行。如果您需要指定订单,请确保它大于0。

78.12配置由JPA使用的组件

如果你想配置一个将被JPA使用的组件,那么你需要确保组件在JPA之前被初始化。如果组件是自动配置的,Spring Boot将为您处理此问题。例如,当Flyway被自动配置时,Hibernate被配置为依赖于Flyway,以便后者有机会在Hibernate尝试使用它之前初始化数据库。

如果您自己配置组件,则可以使用 EntityManagerFactoryDependsOnPostProcessor子类作为设置必要依赖项的便捷方式。例如,如果您将Hibernate Search与Elasticsearch一起用作其索引管理器,则EntityManagerFactory必须将任何bean配置为依赖于该elasticsearchClientbean:

/**
 * {@link EntityManagerFactoryDependsOnPostProcessor} that ensures that
 * {@link EntityManagerFactory} beans depend on the {@code elasticsearchClient} bean.
 */
@Configuration
static class ElasticsearchJpaDependencyConfiguration
        extends EntityManagerFactoryDependsOnPostProcessor {

    ElasticsearchJpaDependencyConfiguration() {
        super("elasticsearchClient");
    }

}

78.13用两个数据源配置jOOQ

如果您需要将jOOQ与多个数据源一起使用,您应该DSLContext为每个数据源创建您自己 的,请参阅 JooqAutoConfiguration 以获取更多详细信息。

[小费]

特别是,JooqExceptionTranslatorSpringTransactionProvider可以重复使用,以提供类似的功能与一个单一的自动配置做了什么DataSource

数据库初始化

SQL数据库可以用不同的方式初始化,具体取决于你的堆栈是什么。或者当然,只要数据库是一个独立的进程,你就可以手动完成。

79.1使用JPA初始化数据库

JPA具有用于生成DDL的功能,可以将这些功能设置为在启动时针对数据库运行。这是通过两个外部属性来控制的:

  • spring.jpa.generate-ddl (布尔型)开启和关闭功能,并且独立于供应商。
  • spring.jpa.hibernate.ddl-auto(枚举)是一个Hibernate特性,以更细粒度的方式控制行为。请参阅下面的更多细节。

79.2使用Hibernate初始化数据库

您可以设置spring.jpa.hibernate.ddl-auto明确和标准的Hibernate属性值nonevalidateupdatecreatecreate-drop。Spring Boot根据它是否认为你的数据库是嵌入的(默认create-drop)或不是(默认none)为你选择一个默认值 。嵌入式数据库是通过观察检测 Connection类型:hsqldbh2derby嵌入,其余的都没有。从内存切换到“真实”数据库时,请小心谨慎,因为您不会假设新平台中存在表和数据。您必须ddl-auto 明确设置,或使用其他机制之一来初始化数据库。

[注意]

您可以通过启用org.hibernate.SQL记录器来输出模式创建。如果启用调试模式,这会自动完成。

另外,import.sql如果Hibernate从头开始创建模式(即ddl-auto属性设置为createcreate-drop),则将在启动时执行类路径根中命名的文件。如果您非常小心,这对于演示和测试可能很有用,但可能不是您想要在生产中的类路径上进行的操作。这是一个休眠功能(与Spring无关)。

79.3初始化数据库

Spring Boot可以自动创建DataSource并初始化它的模式(DDL脚本)(DML脚本):它分别从标准的根类路径位置schema.sqldata.sql分别加载SQL 。另外Spring Boot会处理 schema-${platform}.sqldata-${platform}.sql文件(如果有的话),其中platform 的值是spring.datasource.platform。这允许您根据需要切换到数据库特定脚本,例如,你可能会选择将其设置为数据库的供应商名称(hsqldbh2oraclemysqlpostgresql等)。

Spring Boot默认启用了Spring JDBC初始化程序的快速失败功能,因此如果脚本导致异常,应用程序将无法启动。你可以调整使用spring.datasource.continue-on-error

[注意]

在基于JPA的应用程序中,您可以选择让Hibernate创建模式或使用,schema.sql但不能同时使用 。spring.jpa.hibernate.ddl-auto如果您选择稍后,请确保禁用。

您也可以通过设置spring.datasource.initialize为禁用初始化false

79.4初始化一个Spring批处理数据库

如果您使用的是Spring Batch,那么它将为大多数常用数据库平台预先打包SQL初始化脚本。Spring Boot会检测你的数据库类型,并默认执行这些脚本,在这种情况下,会将失败的快速设置切换为假(错误已记录,但不会阻止应用程序启动)。这是因为脚本已知是可靠的并且通常不包含错误,所以错误是可以忽略的,忽略它们会使脚本具有幂等性。您可以使用明确的关闭初始化spring.batch.initializer.enabled=false

79.5使用更高级别的数据库迁移工具

春天引导支持两种更高级别的迁移工具:迁飞 和Liquibase

79.5.1在启动时执行Flyway数据库迁移

要在启动时自动运行Flyway数据库迁移,请将其添加 org.flywaydb:flyway-core到类路径中。

迁移是表单中的脚本V<VERSION>__<NAME>.sql(带有<VERSION>下划线分隔的版本,例如'1'或'2_1')。默认情况下,他们住的文件夹中classpath:db/migration,但你可以修改使用flyway.locations。您还可以添加一个特殊的{vendor}占位符来使用供应商特定的脚本。假设如下:

flyway.locations=db/migration/{vendor}

db/migration这个配置不是使用,而是根据数据库的类型(例如db/migration/mysqlMySQL)来设置文件夹的使用。支持的数据库列表可在DatabaseDriver

有关可用设置(如架构等)的详细信息,另请参阅flyway-core的Flyway类。另外,Spring Boot提供了一组FlywayProperties 可用于禁用迁移或关闭位置检查的属性。Spring Boot将调用Flyway.migrate()执行数据库迁移。如果你想要更多的控制,提供一个@Bean实现 FlywayMigrationStrategy

[小费]

如果您想使用Flyway回调,那些脚本也应该存在于classpath:db/migration文件夹中。

默认情况下,Flyway将在您的上下文中自动装载(@PrimaryDataSource,并将其用于迁移。如果你喜欢使用不同的,DataSource你可以创建一个,并将其标记@Bean@FlywayDataSource- 如果你这样做,记得创建另一个,并将其标记为@Primary需要两个数据源。或者,您可以DataSource通过设置flyway.[url,user,password] 外部属性来使用Flyway的本地功能。

有一个Flyway样本,所以你可以看到如何设置。

您还可以使用Flyway为特定场景提供数据。例如,您可以将特定于测试的迁移置入,src/test/resources并且只有在您的应用程序启动测试时才会运行它们。如果您想更加复杂,可以使用特定于配置文件的配置进行自定义,flyway.locations以便某些迁移只在特定配置文件处于活动状态时才会运行。例如,application-dev.properties您可以设置flyway.locationsclasspath:/db/migration, classpath:/dev/db/migrationdev/db/migration 只有在dev配置文件处于活动状态时才会运行。

79.5.2启动时执行Liquibase数据库迁移

要在启动时自动运行Liquibase数据库迁移,请将其添加 org.liquibase:liquibase-core到类路径中。

主更改日志默认为从中读取,db/changelog/db.changelog-master.yaml但可以使用设置liquibase.change-log。除了YAML,Liquibase还支持JSON,XML和SQL更改日志格式。

默认情况下,Liquibase将在你的上下文中自动装载(@PrimaryDataSource并将其用于迁移。如果你喜欢使用不同的,DataSource你可以创建一个,并将其标记@Bean@LiquibaseDataSource- 如果你这样做,记得创建另一个,并将其标记为@Primary需要两个数据源。或者你可以DataSource通过设置liquibase.[url,user,password]外部属性来使用Liquibase的本机 。

查看 LiquibaseProperties 可用设置的细节,如上下文,默认架构等。

有一个Liquibase样本, 所以你可以看到如何设置。

80. 消息

80.1禁用事务处理JMS会话

如果您的JMS代理不支持事务会话,则必须完全禁用事务支持。如果您自己创建JmsListenerContainerFactory ,则无需执行任何操作,因为默认情况下不会进行事务处理。如果您想使用DefaultJmsListenerContainerFactoryConfigurerSpring Boot的默认值,可以按如下方式禁用事务会话:

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(
        ConnectionFactory connectionFactory,
        DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory listenerFactory =
            new DefaultJmsListenerContainerFactory();
    configurer.configure(listenerFactory, connectionFactory);
    listenerFactory.setTransactionManager(null);
    listenerFactory.setSessionTransacted(false);
    return listenerFactory;
}

这将覆盖默认工厂,这应该应用于应用程序定义的任何其他工厂(如果有)。

81.批量应用程序

[注意]

默认情况下,批处理应用程序需要DataSource存储作业详细信息。如果你想偏离这一点,你需要实现BatchConfigurer,请参阅 Javadoc的@EnableBatchProcessing更多细节。

81.1启动时执行Spring Batch作业

Spring Batch自动配置通过@EnableBatchProcessing 在上下文中的某个地方添加(从Spring Batch)启用。

默认情况下,它在启动时执行应用程序上下文中的所有内容 Jobs( 有关详细信息,请参阅 JobLauncherCommandLineRunner)。您可以通过指定spring.batch.job.names(以逗号分隔的作业名称模式)来缩小特定作业或作业范围 。

如果应用程序上下文包含a,JobRegistryspring.batch.job.names在注册表中查找作业, 而不是从上下文自动装配。对于更复杂的系统,这是一种常见模式,其中多个作业在子上下文中定义并集中注册。

有关 更多详细信息,请参阅 BatchAutoConfiguration 和 @EnableBatchProcessing

82.Actuator

82.1更改actuator endpoints的HTTP端口或地址

在独立应用程序中,Actuator HTTP端口默认与主HTTP端口相同。为了让应用程序在不同的端口上侦听,设置了外部属性 management.port。要监听完全不同的网络地址(例如,如果您有用于管理的内部网络和用于应用程序的外部网络),您还可以设置management.address为服务器能够绑定的有效IP地址。

有关更多详细信息,请参阅 ManagementServerProperties 源代码和 “生产就绪功能”部分中的第48.3节“自定义管理服务器端口”

82.2自定义'whitelabel'错误页面

如果您遇到服务器错误(使用JSON和其他媒体类型的计算机客户端应该看到具有正确错误代码的合理响应),Spring Boot将安装一个'browser'客户端中会出现的'whitelabel'错误页面。

[注意]

设置server.error.whitelabel.enabled=false为关闭默认错误页面,这将恢复您正在使用的servlet容器的默认值。请注意,Spring Boot仍然会尝试解决错误视图,因此您可能会添加自己的错误页面,而不是完全禁用它。

用你自己覆盖错误页面取决于你正在使用的模板技术。例如,如果您使用的是Thymeleaf,则需要添加一个error.html模板,如果您使用的是FreeMarker,则需要添加一个error.ftl模板。一般来说,你需要的是一个View以名称error和/或@Controller处理/error路径的方式解决的问题。除非你替换了一些默认配置,否则你应该BeanNameViewResolver在你ApplicationContext@Beanid中找到一个这样的id,error这将是一个简单的方法。看看ErrorMvcAutoConfiguration更多的选择。

有关如何在servlet容器中注册处理程序的详细信息,另请参阅错误处理一节。

82.3消除敏感的价值

由返回的信息envconfigprops从而匹配特定模式键由缺省(即它们的值被替换为消毒端点可以是有些敏感)。

Spring Boot对这些键使用合理的默认设置:例如,任何以“password”,“secret”,“key”或“token”结尾的键都将被清理。也可以改为使用正则表达式,例如credentials.清理任何将该单词credentials作为该键的一部分的键。

要使用的模式可以分别使用endpoints.env.keys-to-sanitize和 自定义endpoints.configprops.keys-to-sanitize

82.4执行器和泽西岛

执行器HTTP端点仅适用于基于Spring MVC的应用程序。如果您想使用Jersey并仍然使用执行器,则需要启用Spring MVC(spring-boot-starter-web例如,取决于)。默认情况下,Jersey和Spring MVC调度程序servlet都映射到相同的路径(/)。您将需要更改其中一个路径(通过配置server.servlet-pathSpring MVC或spring.jersey.application-path泽西岛)。例如,如果添加 server.servlet-path=/systemapplication.properties,执行器HTTP端点将在下面可用/system

83.安全

83.1关闭Spring Boot安全配置

如果您在应用程序中的任何位置定义了一个@Configuration@EnableWebSecurity它将关闭Spring Boot中的默认Web应用程序安全设置(但启用Actuator的安全性)。要调整默认尝试设置的属性 security.*(请参阅 SecurityProperties 有关可用设置的详细信息)和SECURITY部分 常用的应用程序性能

83.2更改AuthenticationManager并添加用户帐户

如果你提供了一个默认@Bean的类型AuthenticationManager,那么你将拥有完整的Spring Security功能集(例如 各种认证选项)。

Spring Security还提供了一个方便的选项AuthenticationManagerBuilder,可以用来构建一个AuthenticationManager通用选项。在webapp中使用这个建议的方法是将它注入一个void方法中 WebSecurityConfigurerAdapter,例如

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                .withUser("barry").password("password").roles("USER"); // ... etc.
    }

    // ... other stuff for application security

}

如果将它放在嵌套类或独立类中(即,不会混入许多其他@Beans可能会影响实例化顺序的混合类),您将获得最佳结果。该安全网样本 是按照一个有用的模板。

如果遇到实例化问题(例如,对用户详细信息存储使用JDBC或JPA),可能需要将AuthenticationManagerBuilder回调提取到GlobalAuthenticationConfigurerAdapter(在该init()方法中,以便在其他地方需要身份验证管理器之前发生),例如

@Configuration
public class AuthenticationManagerConfiguration extends
        GlobalAuthenticationConfigurerAdapter {

    @Override
    public void init(AuthenticationManagerBuilder auth) {
        auth.inMemoryAuthentication() // ... etc.
    }

}

83.3在代理服务器后运行时启用HTTPS

确保所有主要端点都只能通过HTTPS访问,这对于任何应用程序来说都是一件非常重要的事情。如果您使用Tomcat作为servlet容器,那么Spring Boot会在RemoteIpValve检测到某些环境设置时自动添加Tomcat ,并且您应该能够依靠HttpServletRequest它来报告它是否安全(即使是代理服务器的下游处理真正的SSL终止)。标准行为取决于是否存在某些请求头(x-forwarded-forx-forwarded-proto),它们的名称是常规的,所以它应该适用于大多数前端代理。您可以通过添加一些条目来切换阀门application.properties,例如

server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto

(这些属性中的任何一个都会打开阀门,或者你可以RemoteIpValve通过添加一个TomcatEmbeddedServletContainerFactorybean 来添加 自己。)

Spring Security也可以配置为需要所有(或某些请求)的安全通道。要切换是在你只需要设置一个春天启动的应用程序 security.require_ssltrueapplication.properties

84.热插拔

84.1重新加载静态内容

有几种热重载的选项。推荐的方法是使用, spring-boot-devtools因为它提供了额外的开发时间功能,例如支持快速应用程序重启和LiveReload以及合理的开发时配置(例如模板缓存)。Devtools通过监视类路径的变化来工作。这意味着静态资源更改必须“建立”,以使更改生效。默认情况下,当您保存更改时,这会在Eclipse中自动发生。在IntelliJ IDEA中,Make Project将触发必要的构建。由于 默认的重新启动排除,对静态资源的更改不会触发应用程序的重新启动。但是,他们会触发实时重新加载。

或者,在IDE中运行(特别是在调试时)是开发的好方法(所有现代IDE允许重新加载静态资源,并且通常还可以热切换Java类更改)。

最后,Maven和摇篮插件可被配置成(见addResources属性),以支持在命令行运行直接从源的静态文件重装。如果您使用更高级别的工具编写该代码,则可以将其用于外部css / js编译器进程。

84.2重新加载模板而不重新启动容器

Spring Boot支持的大多数模板技术都包含禁用缓存的配置选项(详情请参阅下文)。如果您使用 spring-boot-devtools模块,这些属性将 在开发时自动配置

84.2.1阔叶树模板

如果你使用的是Thymeleaf,那么设置spring.thymeleaf.cachefalse。请参阅 ThymeleafAutoConfiguration 其他Thymeleaf自定义选项。

84.2.2 FreeMarker模板

如果您正在使用FreeMarker,则设置spring.freemarker.cachefalse。查看 FreeMarkerAutoConfiguration 其他FreeMarker自定义选项。

84.2.3 Groovy模板

如果您正在使用Groovy模板,请设置spring.groovy.template.cachefalse。请参阅 GroovyTemplateAutoConfiguration 其他Groovy自定义选项。

84.3快速应用程序重新启动

spring-boot-devtools模块包含对自动应用程序重新启动的支持。虽然速度不如JRebel 或Spring Loaded等技术,但它通常比“冷启动”快得多。在调查下面讨论的一些更复杂的重新加载选项之前,您应该尝试一下。

有关更多详细信息,请参阅第20章开发人员工具部分。

84.4重新加载Java类而不重新启动容器

现代的IDE(Eclipse,IDEA等)都支持字节码的热插拔,所以如果你做了一个不影响类或方法签名的改变,它应该干净地重新加载而没有副作用。

Spring Loaded进一步发展,它可以通过方法签名中的更改来重新加载类定义。通过一些定制,它可以强制ApplicationContext刷新自己(但是没有通用的机制来确保对于正在运行的应用程序来说是安全的,因此它可能只是一个开发时间技巧)。

84.4.1配置Spring加载用于Maven

要使用Spring加载Maven命令行,只需将它作为Spring Boot插件声明中的依赖项添加,例如

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.6.RELEASE</version>
        </dependency>
    </dependencies>
</plugin>

对于Eclipse和IntelliJ IDEA,只要它们的构建配置与Maven默认值保持一致(Eclipse m2e可以实现此功能),这通常可以很好地工作。

84.4.2配置加载的Spring以用于Gradle和IntelliJ IDEA

如果您想要将Spring Loaded与Gradle和IntelliJ IDEA结合使用,则需要跳过一些箍环。默认情况下,IntelliJ IDEA会将类编译到与Gradle不同的位置,从而导致Spring Loaded监视失败。

要正确配置IntelliJ IDEA,您可以使用ideaGradle插件:

buildscript {
    repositories { jcenter() }
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:1.5.14.RELEASE"
        classpath 'org.springframework:springloaded:1.2.6.RELEASE'
    }
}

apply plugin: 'idea'

idea {
    module {
        inheritOutputDirs = false
        outputDir = file("$buildDir/classes/main/")
    }
}

// ...
[注意]

IntelliJ IDEA必须配置为使用与命令行Gradle任务相同的Java版本,并且springloaded 必须作为buildscript依赖项包含在内。

您还可以在IntelliJ IDEA中另外启用'自动创建项目',以便在保存文件时自动编译您的代码。

85.建设

85.1生成构建信息

Maven和Gradle插件都允许生成包含项目坐标,名称和版本的构建信息。该插件也可以配置为通过配置添加其他属性。当这样的文件存在时,Spring Boot会自动配置一个BuildPropertiesbean。

要使用Maven生成构建信息,请为该build-info目标添加一个执行:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>1.5.14.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
[小费]

查看Spring Boot Maven Plugin文档 以获取更多详细信息。

并用Gradle来做同样的事情:

springBoot  {
    buildInfo()
}

可以使用DSL添加其他属性:

springBoot  {
    buildInfo {
        additionalProperties = [
            'foo': 'bar'
        ]
    }
}

85.2生成git信息

Maven和Gradle都允许在构建项目时生成一个git.properties包含有关git源代码库状态信息的文件。

对于Maven用户,spring-boot-starter-parentPOM包含一个预先配置的插件来生成一个git.properties文件。只需将以下声明添加到您的POM:

<build>
    <plugins>
        <plugin>
            <groupId>pl.project13.maven</groupId>
            <artifactId>git-commit-id-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Gradle用户可以使用该gradle-git-properties插件获得相同的结果

plugins {
    id "com.gorylenko.gradle-git-properties" version "1.4.17"
}
[小费]

提交时间git.properties预计与格式匹配 yyyy-MM-dd’T’HH:mm:ssZ。这是上面列出的两个插件的默认格式。使用这种格式可以将时间Date序列化为JSON,并通过Jackson的日期序列化配置设置来控制时间。

85.3自定义依赖版本

如果您使用从spring-boot-dependencies (例如spring-boot-starter-parent)直接或间接继承的Maven构建,但您想覆盖特定的第三方依赖关系,则可以添加适当的<properties>元素。浏览spring-boot-dependencies POM以获取完整的属性列表。例如,要选择不同的slf4j版本,您可以添加以下内容:

<properties>
    <slf4j.version>1.7.5<slf4j.version>
</properties>
[注意]

这只适用于你的Maven项目继承(直接或间接) spring-boot-dependencies。如果您spring-boot-dependencies在自己的dependencyManagement部分中添加了自己,则<scope>import</scope>必须自己重新定义工件,而不是覆盖该属性。

[警告]

每个Spring Boot版本都针对特定的第三方依赖关系进行设计和测试。覆盖版本可能会导致兼容性问题。

要覆盖Gradle中的依赖版本,您可以指定一个版本,如下所示:

ext['slf4j.version'] = '1.7.5'

有关更多信息,请参阅 Gradle Dependency Management插件文档

85.4用Maven创建一个可执行的JAR

spring-boot-maven-plugin可用于创建可执行的“胖” JAR。如果您使用spring-boot-starter-parentPOM,则可以简单地声明该插件,并且您的罐子将被重新包装:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

如果你没有使用父POM,你仍然可以使用插件,但是,你必须另外添加一个<executions>部分:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>1.5.14.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

有关完整的使用详细信息,请参阅插件文档

85.5使用Spring Boot应用程序作为依赖项

像战争文件一样,Spring Boot应用程序不打算用作依赖项。如果您的应用程序包含要与其他项目共享的类,则建议的方法是将该代码移入单独的模块。这个单独的模块可以被你的应用程序和其他项目所依赖。

如果您不能像上面推荐的那样重新安排您的代码,Spring Boot的Maven和Gradle插件必须配置为生成适合用作依赖关系的单独工件。可执行文件不能用作依赖项,因为 可执行的jar格式将应用程序类包装进来BOOT-INF/classes。这意味着当可执行jar用作依赖项时,它们不能被找到。

为了产生两个工件,一个可以用作依赖关系和一个可执行工件,必须指定一个分类器。此分类器应用于可执行归档文件的名称,保留默认归档文件以用作依赖项。

要配置execMaven中的分类器,可以使用以下配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <classifier>exec</classifier>
            </configuration>
        </plugin>
    </plugins>
</build>

在使用Gradle时,可以使用以下配置:

bootRepackage  {
    classifier = 'exec'
}

85.6当可执行jar运行时提取特定的库

可执行jar中的大多数嵌套库不需要解压以便运行,但某些库可能会遇到问题。例如,JRuby包含它自己的嵌套jar支持,它假设它jruby-complete.jar始终直接作为文件独立存在。

为了处理任何有问题的库,你可以标记特定的嵌套jar应该在可执行jar第一次运行时自动解压到'temp folder'。

例如,为了表明JRuby应该被标记为使用Maven Plugin解压缩,您可以添加以下配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <requiresUnpack>
                    <dependency>
                        <groupId>org.jruby</groupId>
                        <artifactId>jruby-complete</artifactId>
                    </dependency>
                </requiresUnpack>
            </configuration>
        </plugin>
    </plugins>
</build>

并且用Gradle做同样的事情:

springBoot  {
    requiresUnpack = ['org.jruby:jruby-complete']
}

85.7用排除项创建一个不可执行的JAR

通常,如果您将可执行文件和非可执行文件的jar作为构建产品,则可执行文件的版本将具有库jar中不需要的其他配置文件。例如,application.yml配置文件可能会从不可执行的JAR中排除。

以下是在Maven中如何做到这一点:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <classifier>exec</classifier>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <id>exec</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <classifier>exec</classifier>
                    </configuration>
                </execution>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <!-- Need this to ensure application.yml is excluded -->
                        <forceCreation>true</forceCreation>
                        <excludes>
                            <exclude>application.yml</exclude>
                        </excludes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

在Gradle中,您可以使用标准任务DSL功能创建新的JAR归档,然后bootRepackage使用其withJarTask属性依赖该任务:

jar {
    baseName = 'spring-boot-sample-profile'
    version =  '0.0.0'
    excludes = ['**/application.yml']
}

task('execJar', type:Jar, dependsOn: 'jar') {
    baseName = 'spring-boot-sample-profile'
    version =  '0.0.0'
    classifier = 'exec'
    from sourceSets.main.output
}

bootRepackage  {
    withJarTask = tasks['execJar']
}

85.8远程调试使用Maven启动的Spring Boot应用程序

要将远程调试器附加到以Maven开始的Spring Boot应用程序,您可以使用maven插件jvmArguments属性。

查看这个例子获取更多细节。

85.9远程调试使用Gradle启动的Spring Boot应用程序

要将远程调试器附加到使用Gradle启动的Spring Boot应用程序,可以使用任务或命令行选项的jvmArgs属性。bootRun--debug-jvm

build.gradle

bootRun {
    jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
}

命令行:

$ gradle bootRun --debug-jvm

检查Gradle应用程序插件了解更多详情。

85.10在不使用spring-boot-antlib的情况下从Ant构建可执行档案

要使用Ant进行构建,您需要获取依赖关系,编译并创建jar或war归档文件。要使其可执行,您可以使用该spring-boot-antlib 模块,也可以按照以下说明操作:

  1. 如果您正在构建jar,请将应用程序的类和资源打包到嵌套 BOOT-INF/classes目录中。如果您正在构建战争,请WEB-INF/classes像往常一样将应用程序的类打包到嵌套目录中。
  2. 将运行时依赖关系添加到BOOT-INF/libjar或WEB-INF/lib战争的嵌套目录中 。切记不要压缩存档中的条目。
  3. provided(嵌入容器)依赖项添加到BOOT-INF/lib jar或WEB-INF/lib-provided战争的嵌套目录中。切记不要压缩存档中的条目。
  4. spring-boot-loader在档案的根目录添加类(所以Main-Class 可用)。
  5. 使用适当的启动程序(例如JarLauncherjar文件)作为Main-Class 清单中的一个属性,并指定它作为清单条目所需的其他属性,主要是a Start-Class

例:

<target name="build" depends="compile">
    <jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
        <mappedresources>
            <fileset dir="target/classes" />
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="src/main/resources" erroronmissingdir="false"/>
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="${lib.dir}/runtime" />
            <globmapper from="*" to="BOOT-INF/lib/*"/>
        </mappedresources>
        <zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
        <manifest>
            <attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
            <attribute name="Start-Class" value="${start-class}" />
        </manifest>
    </jar>
</target>

 Ant示例有手动任务的build.xml, 如果您使用它运行,它应该可以工作

$ ant -lib <folder containing ivy-2.2.jar> clean manual

之后你可以运行该应用程序

$ java -jar target/*.jar

85.11如何使用Java 6

如果你想在Java 6中使用Spring Boot,那么你需要做少量的配置更改。确切的更改取决于您的应用程序的功能。

85.11.1嵌入式servlet容器兼容性

如果您使用Boot的嵌入式Servlet容器之一,则必须使用Java 6兼容容器。Tomcat 7和Jetty 8都与Java 6兼容。有关详细信息,请参见 第73.16节“使用Tomcat 7.x或8.0”第73.18节“使用Jetty 8”

85.11.2 Jackson

Jackson 2.7和更高版本要求使用Java 7.如果要使用Java 6,则必须将其降级到Jackson 2.6。

Spring Boot使用杰克逊2.7引入的Jackson BOM,因此您不能仅仅覆盖该jackson.version属性。为了使用Jackson 2.6,您必须在dependencyManagement构建部分中定义各个模块,请查看 此示例以获取更多详细信息。

85.11.3 JTA API兼容性

虽然Java Transaction API本身不需要Java 7,但官方的API jar包含的内容是为了要求Java 7而构建的。如果您使用的是JTA,那么您需要将官方的JTA 1.2 API jar替换为已经构建的jar在Java 6上工作。为此,请排除任何传递依赖关系 javax.transaction:javax.transaction-api并将其替换为依赖关系org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Final

86.传统部署

86.1创建一个可部署的战争文件

生成可展开war文件的第一步是提供一个 SpringBootServletInitializer子类并覆盖它的configure方法。这可以利用Spring框架的Servlet 3.0支持,并允许您在应用程序由servlet容器启动时对其进行配置。通常,您更新应用程序的主类以扩展SpringBootServletInitializer

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

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

}

下一步是更新您的构建配置,以便您的项目生成war文件而不是jar文件。如果您使用Maven并使用spring-boot-starter-parent(为您配置Maven的战争插件),您只需修改pom.xml以将包装更改为war:

<packaging>war</packaging>

如果您使用的是Gradle,则需要修改build.gradle以将war插件应用于该项目:

apply plugin: 'war'

这个过程的最后一步是确保内置的servlet容器不会干扰要部署war文件的servlet容器。为此,您需要标记所提供的嵌入式servlet容器依赖项。

如果你使用Maven:

<dependencies>
    <!-- … -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- … -->
</dependencies>

如果你使用Gradle:

dependencies {
    // …
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    // …
}
[注意]

如果您使用的是支持仅编译依赖关系(2.12或更高版本)的Gradle版本,则应继续使用providedRuntime。在其他限制中, compileOnly依赖关系不在测试类路径上,因此任何基于Web的集成测试都将失败。

如果您使用的是Spring Boot构建工具,则根据提供的标记嵌入的Servlet容器依赖关系将生成一个可执行的war文件,其中提供的依赖项打包在一个lib-provided目录中。这意味着,除了可部署到servlet容器外,您还可以java -jar在命令行上运行应用程序。

[小费]

看看Spring Boot的示例应用程序,以 获得上述配置的基于Maven的示例

86.2为较旧的servlet容器创建可部署的war文件

较老的Servlet容器不支持ServletContextInitializerServlet 3.0中使用的引导过程。你仍然可以在这些容器中使用Spring和Spring Boot,但是你将需要添加一个web.xml到你的应用程序并配置它来ApplicationContext通过a 加载DispatcherServlet

86.3将现有的应用程序转换为Spring Boot

对于非web应用程序应该很容易(扔掉创建你的代码 ApplicationContext,并呼吁重新放回SpringApplication或 SpringApplicationBuilder)。Spring MVC Web应用程序通常可以首先创建可部署的战争应用程序,然后将其稍后迁移到可执行的战争和/或jar。有用的阅读内容在“将jar转换为war入门指南”中

通过扩展SpringBootServletInitializer(例如,在一个名为的类中Application)来创建可部署的战争,并添加Spring Boot @SpringBootApplication注释。例:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        // Customize the application or call application.sources(...) to add sources
        // Since our example is itself a @Configuration class (via @SpringBootApplication)
        // we actually don't need to override this method.
        return application;
    }

}

请记住,无论你放入什么sources只是一个Spring ApplicationContext,通常任何已经有效的东西都应该在这里工作。可能会有一些bean可以稍后删除,并让Spring Boot为它们提供自己的默认值,但应该有可能首先开始工作。

可以将静态资源移动到类路径根中/public/static/resources或 /META-INF/resources)。同为messages.properties(春季启动在classpath的根目录会自动检测这一点)。

Spring DispatcherServlet和Spring Security的香草应用不需要进一步修改。如果您的应用程序中有其他功能,例如使用其他servlet或过滤器,那么您可能需要在您的Application上下文中添加一些配置,从中替换这些元素web.xml,如下所示:

  • @Bean的类型,Servlet或者ServletRegistrationBean将bean安装在容器中,就好像它是a <servlet/><servlet-mapping/>in一样web.xml
  • @Bean类型FilterFilterRegistrationBean行为类似(如a <filter/>和)<filter-mapping/>
  • 一个ApplicationContextXML文件可以通过添加@ImportResource在你的Application。或者注释配置大量使用的简单情况已经可以作为@Bean定义在几行中重新创建。

战争开始后,我们通过向main我们添加一个方法来 使其可执行Application,例如

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

如果您打算将应用程序作为战争或作为可执行应用程序启动,则需要在可用于SpringBootServletInitializer回调和main方法的方法中共享构建器的自定义设置 ,如下所示:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return configureApplication(builder);
    }

    public static void main(String[] args) {
        configureApplication(new SpringApplicationBuilder()).run(args);
    }

    private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
        return builder.sources(Application.class).bannerMode(Banner.Mode.OFF);
    }

}

应用程序可以分为多个类别:

  • Servlet 3.0+应用程序没有web.xml
  • 应用程序使用web.xml
  • 具有上下文层次的应用程序
  • 没有上下文层次的应用程序

所有这些都应该适合翻译,但每个可能需要稍微不同的技巧。

如果Servlet 3.0+应用程序已经使用Spring Servlet 3.0+初始化器支持类,它们可能会很容易转换。通常来自现有的所有代码 WebApplicationInitializer都可以被移入一个SpringBootServletInitializer。如果您的现有应用程序有多个ApplicationContext(例如,如果它使用AbstractDispatcherServletInitializer),那么您可能能够将所有上下文源压缩到一个SpringApplication。您可能遇到的主要难题是如果这不起作用并且您需要维护上下文层次结构。请参阅构建示例层次结构的 条目。通常需要分解包含网络特定功能的现有父上下文,以便所有ServletContextAware组件都位于子上下文中。

不是Spring应用程序的应用程序可能会转换为Spring Boot应用程序,上面的指导可能会有帮助,但是您的里程可能会有所不同。

86.4将WAR部署到WebLogic

要将Spring Boot应用程序部署到WebLogic,您必须确保您的Servlet初始化程序直接实现WebApplicationInitializer(即使您从已经实现它的基类中进行扩展)。

一个典型的WebLogic初始化器就是这样的:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

}

如果使用logback,则还需要告知WebLogic更喜欢打包的版本,而不是预装在服务器上的版本。您可以通过添加WEB-INF/weblogic.xml具有以下内容的文件来完成此操作 :

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
    xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
        http://xmlns.oracle.com/weblogic/weblogic-web-app
        http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
    <wls:container-descriptor>
        <wls:prefer-application-packages>
            <wls:package-name>org.slf4j</wls:package-name>
        </wls:prefer-application-packages>
    </wls:container-descriptor>
</wls:weblogic-web-app>

86.5在旧的(Servlet 2.5)容器中部署WAR

Spring Boot使用Servlet 3.0 API来初始化ServletContext(注册Servlets 等),因此您不能在Servlet 2.5容器中使用相同的应用程序。这但是,可以运行一些特殊工具的旧容器上的春天启动应用程序。如果包含org.springframework.boot:spring-boot-legacy作为依赖项(独立于Spring Boot的核心并且目前可用于1.0.2.RELEASE),则您只需创建一个web.xml并声明一个上下文侦听器来创建应用程序上下文以及您的过滤器和servlet 。上下文监听器是Spring Boot的特殊用途,但其余部分对于Servlet 2.5中的Spring应用程序来说是正常的。例:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>demo.Application</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
    </listener>

    <filter>
        <filter-name>metricsFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>metricsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextAttribute</param-name>
            <param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

在这个例子中,我们使用一个应用程序上下文(由上下文监听器创建的上下文)并将其附加到DispatcherServlet使用init参数。这在Spring Boot应用程序中很正常(通常只有一个应用程序上下文)。

转载于:https://my.oschina.net/u/128964/blog/1831961

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值