spring-boot(三) HowTo

Spring Boot How To

1. 简介

本章节将回答一些常见的"我该怎么作"类型的问题,这些问题在咱们使用spring Boot时常常遇到。这毫不是一个详尽的列表,但它覆盖了不少方面。javascript

若是遇到一个特殊的咱们没有覆盖的问题,你可能想去查看stackoverflow.comcss

2. Spring Boot应用

2.1. 解决自动配置问题

Spring Boot自动配置老是尝试尽最大努力去作正确的事,但有时候会失败而且很难说出失败缘由。html

在每一个Spring Boot ApplicationContext中都存在一个至关有用的ConditionEvaluationReport。若是开启DEBUG日志输出,你将会看到它。若是你使用spring-boot-actuator,则会有一个autoconfig的端点,它将以JSON形式渲染该报告。可使用它调试应用程序,并能查看Spring Boot运行时都添加了哪些特性(及哪些没添加)。前端

经过查看源码和javadoc能够获取更多问题的答案。如下是一些经验:java

查找名为*AutoConfiguration的类并阅读源码,特别是@Conditional*注解,这能够帮你找出它们启用哪些特性及什么时候启用。 将--debug添加到命令行或添加系统属性-Ddebug能够在控制台查看日志,该日志会记录你的应用中全部自动配置的决策。在一个运行的Actuator app中,经过查看autoconfig端点(/autoconfig或等效的JMX)能够获取相同信息。

查找是@ConfigurationProperties的类(好比ServerProperties)并看下有哪些可用的外部配置选项。@ConfigurationProperties类有一个用于充当外部配置前缀的name属性,所以ServerProperties的值为prefix="server",它的配置属性有server.port,server.address等。在运行的Actuator应用中能够查看configprops端点。

查看使用RelaxedEnvironment明确地将配置从Environment暴露出去。它常常会使用一个前缀。

查看@Value注解,它直接绑定到Environment。相比RelaxedEnvironment,这种方式稍微缺少灵活性,但它也容许松散的绑定,特别是OS环境变量(因此CAPITALS_AND_UNDERSCORES是period.separated的同义词)。

查看@ConditionalOnExpression注解,它根据SpEL表达式的结果来开启或关闭特性,一般使用解析自Environment的占位符进行计算。

2.2. 启动前自定义Environment或ApplicationContext

每一个SpringApplication都有ApplicationListeners和ApplicationContextInitializers,用于自定义上下文(context)或环境(environment)。Spring Boot从META-INF/spring.factories下加载不少这样的内部使用的自定义。有不少方法能够注册其余的自定义:mysql

以编程方式为每一个应用注册自定义,经过在SpringApplication运行前调用它的addListeners和addInitializers方法来实现。
以声明方式为每一个应用注册自定义,经过设置context.initializer.classes或context.listener.classes来实现。
以声明方式为全部应用注册自定义,经过添加一个META-INF/spring.factories并打包成一个jar文件(该应用将它做为一个库)来实现。

SpringApplication会给监听器(即便是在上下文被建立以前就存在的)发送一些特定的ApplicationEvents,而后也会注册监听ApplicationContext发布的事件的监听器。查看Spring Boot特性章节中的Section 22.4, “Application events and listeners” 能够获取一个完整列表。web

2.3. 建立一个非web(non-web)应用

不是全部的Spring应用都必须是web应用(或web服务)。若是你想在main方法中执行一些代码,但须要启动一个Spring应用去设置须要的底层设施,那使用Spring Boot的SpringApplication特性能够很容易实现。SpringApplication会根据它是否须要一个web应用来改变它的ApplicationContext类。首先你须要作的是去掉servlet API依赖,若是不能这样作(好比,基于相同的代码运行两个应用),那你能够明确地调用SpringApplication.setWebEnvironment(false)或设置applicationContextClass属性(经过Java API或使用外部配置)。你想运行的,做为业务逻辑的应用代码能够实现为一个CommandLineRunner,并将上下文降级为一个@Bean定义。正则表达式

3. 属性&配置

3.1. 外部化SpringApplication配置

SpringApplication已经被属性化(主要是setters),因此你能够在建立应用时使用它的Java API修改它的行为。或者你可使用properties文件中的spring.main.*来外部化(在应用代码外配置)这些配置。好比,在application.properties中可能会有如下内容:spring

spring.main.web_environment=false
spring.main.show_banner=false

而后Spring Boot在启动时将不会显示banner,而且该应用也不是一个web应用。sql

3.2. 改变应用程序外部配置文件的位置

默认状况下,来自不一样源的属性以一个定义好的顺序添加到Spring的Environment中(查看'Sprin Boot特性'章节的Chapter 23, Externalized Configuration获取精确的顺序)。

为应用程序源添加@PropertySource注解是一种很好的添加和修改源顺序的方法。传递给SpringApplication静态便利设施(convenience)方法的类和使用setSources()添加的类都会被检查,以查看它们是否有@PropertySources,若是有,这些属性会被尽量早的添加到Environment里,以确保ApplicationContext生命周期的全部阶段都能使用。以这种方式添加的属性优先于任何使用默认位置添加的属性,但低于系统属性,环境变量或命令行参数。

你也能够提供系统属性(或环境变量)来改变该行为:

spring.config.name(SPRING_CONFIG_NAME)是根文件名,默认为application。
spring.config.location(SPRING_CONFIG_LOCATION)是要加载的文件(例如,一个classpath资源或一个URL)。Spring Boot为该文档设置一个单独的Environment属性,它能够被系统属性,环境变量或命令行参数覆盖。

无论你在environment设置什么,Spring Boot都将加载上面讨论过的application.properties。若是使用YAML,那具备'.yml'扩展的文件默认也会被添加到该列表。

3.3. 使用'short'命令行参数

有些人喜欢使用(例如)--port=9000代替--server.port=9000来设置命令行配置属性。你能够经过在application.properties中使用占位符来启用该功能,好比:

server.port=${port:8080}

注:若是你继承自spring-boot-starter-parent POM,为了防止和Spring-style的占位符产生冲突,maven-resources-plugins默认的过滤令牌(filter token)已经从${*}变为@(即@maven.token@代替了${maven.token})。若是已经直接启用maven对application.properties的过滤,你可能也想使用其余的分隔符替换默认的过滤令牌。

注:在这种特殊的状况下,端口绑定可以在一个PaaS环境下工做,好比Heroku和Cloud Foundry,由于在这两个平台中PORT环境变量是自动设置的,而且Spring可以绑定Environment属性的大写同义词。

3.4. 使用YAML配置外部属性

YAML是JSON的一个超集,能够很是方便的将外部配置以层次结构形式存储起来。好比:

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

建立一个application.yml文件,将它放到classpath的根目录下,并添加snakeyaml依赖(Maven坐标为org.yaml:snakeyaml,若是你使用spring-boot-starter那就已经被包含了)。一个YAML文件会被解析为一个java Map<String,Object>(和一个JSON对象相似),Spring Boot会平伸该map,这样它就只有1级深度,而且有period-separated的keys,跟人们在Java中常用的Properties文件很是相似。 上面的YAML示例对应于下面的application.properties文件:

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

3.5. 设置生效的Spring profiles

Spring Environment有一个API能够设置生效的profiles,但一般你会设置一个系统profile(spring.profiles.active)或一个OS环境变量(SPRINGPROFILESACTIVE)。好比,使用一个-D参数启动应用程序(记着把它放到main类或jar文件以前):

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

在Spring Boot中,你也能够在application.properties里设置生效的profile,例如:

spring.profiles.active=production

经过这种方式设置的值会被系统属性或环境变量替换,但不会被SpringApplicationBuilder.profiles()方法替换。所以,后面的Java API可用来在不改变默认设置的状况下增长profiles。

3.6. 根据环境改变配置

一个YAML文件其实是一系列以---线分割的文档,每一个文档都被单独解析为一个平坦的(flattened)map。

若是一个YAML文档包含一个spring.profiles关键字,那profiles的值(以逗号分割的profiles列表)将被传入Spring的Environment.acceptsProfiles()方法,而且若是这些profiles的任何一个被激活,对应的文档被包含到最终的合并中(不然不会)。

示例:

server:
    port: 9000
---

spring:
    profiles: development
server:
    port: 9001

---

spring:
    profiles: production
server:
    port: 0

在这个示例中,默认的端口是9000,但若是Spring profile 'development'生效则该端口是9001,若是'production'生效则它是0。

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

想要使用profiles文件完成一样的操做,你可使用application-${profile}.properties指定特殊的,profile相关的值。

3.7. 发现外部属性的内置选项

Spring Boot在运行时未来自application.properties(或.yml)的外部属性绑定进一个应用中。在一个地方不可能存在详尽的全部支持属性的列表(技术上也是不可能的),由于你的classpath下的其余jar文件也可以贡献。

每一个运行中且有Actuator特性的应用都会有一个configprops端点,它可以展现全部边界和可经过@ConfigurationProperties绑定的属性。

附录中包含一个application.properties示例,它列举了Spring Boot支持的大多数经常使用属性。获取权威列表可搜索@ConfigurationProperties和@Value的源码,还有不常用的RelaxedEnvironment。

4. 内嵌的servlet容器

4.1. 为应用添加Servlet,Filter或ServletContextListener

Servlet规范支持的Servlet,Filter,ServletContextListener和其余监听器能够做为@Bean定义添加到你的应用中。须要格外当心的是,它们不会引发太多的其余beans的热初始化,由于在应用生命周期的早期它们已经被安装到容器里了(好比,让它们依赖你的DataSource或JPA配置就不是一个好主意)。你能够经过延迟初始化它们到第一次使用而不是初始化时来突破该限制。

在Filters和Servlets的状况下,你也能够经过添加一个FilterRegistrationBean或ServletRegistrationBean代替或以及底层的组件来添加映射(mappings)和初始化参数。

4.2. 改变HTTP端口

在一个单独的应用中,主HTTP端口默认为8080,但可使用server.port设置(好比,在application.properties中或做为一个系统属性)。因为Environment值的宽松绑定,你也可使用SERVER_PORT(好比,做为一个OS环境变)。

为了彻底关闭HTTP端点,但仍建立一个WebApplicationContext,你能够设置server.port=-1(测试时可能有用)。

想获取更多详情可查看'Spring Boot特性'章节的Section 26.3.3, “Customizing embedded servlet containers”,或ServerProperties源码。

4.3. 使用随机未分配的HTTP端口

想扫描一个未使用的端口(为了防止冲突使用OS本地端口)可使用server.port=0。

4.4. 发现运行时的HTTP端口

你能够经过日志输出或它的EmbeddedServletContainer的EmbeddedWebApplicationContext获取服务器正在运行的端口。获取和确认服务器已经初始化的最好方式是添加一个ApplicationListener类型的@Bean,而后当事件发布时将容器pull出来。

使用@WebIntegrationTests的一个有用实践是设置server.port=0,而后使用@Value注入实际的('local')端口。例如:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)
@WebIntegrationTest("server.port:0")
public class CityRepositoryIntegrationTests {

    @Autowired
    EmbeddedWebApplicationContext server;

    @Value("${local.server.port}")
    int port;

    // ...

}

4.5. 配置SSL

SSL可以以声明方式进行配置,通常经过在application.properties或application.yml设置各类各样的server.ssl.*属性。例如:

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

获取全部支持的配置详情可查看Ssl。

注:Tomcat要求key存储(若是你正在使用一个可信存储)可以直接在文件系统上访问,即它不能从一个jar文件内读取。Jetty和Undertow没有该限制。

使用相似于以上示例的配置意味着该应用将不在支持端口为8080的普通HTTP链接。Spring Boot不支持经过application.properties同时配置HTTP链接器和HTTPS链接器。若是你两个都想要,那就须要以编程的方式配置它们中的一个。推荐使用application.properties配置HTTPS,由于HTTP链接器是两个中最容易以编程方式进行配置的。获取示例可查看spring-boot-sample-tomcat-multi-connectors示例项目。

4.6. 配置Tomcat

一般你能够遵循Section 63.7, “Discover built-in options for external properties”关于@ConfigurationProperties(这里主要的是ServerProperties)的建议,但也看下EmbeddedServletContainerCustomizer和各类你能够添加的Tomcat-specific的*Customizers。

Tomcat APIs至关丰富,一旦获取到TomcatEmbeddedServletContainerFactory,你就可以以多种方式修改它。或核心选择是添加你本身的TomcatEmbeddedServletContainerFactory。

4.7. 启用Tomcat的多链接器(Multiple Connectors)

你能够将一个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);
    }
}

4.8. 在前端代理服务器后使用Tomcat

Spring Boot将自动配置Tomcat的RemoteIpValve,若是你启用它的话。这容许你透明地使用标准的x-forwarded-for和x-forwarded-proto头,不少前端代理服务器都会添加这些头信息(headers)。经过将这些属性中的一个或所有设置为非空的内容来开启该功能(它们是大多数代理约定的值,若是你只设置其中的一个,则另外一个也会被自动设置)。

server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto

若是你的代理使用不一样的头部(headers),你能够经过向application.properties添加一些条目来自定义该值的配置,好比:

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

该值也能够配置为一个默认的,可以匹配信任的内部代理的正则表达式。默认状况下,受信任的IP包括 10/8, 192.168/16, 169.254/16 和 127/8。能够经过向application.properties添加一个条目来自定义该值的配置,好比:

server.tomcat.internal_proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}

注:只有在你使用一个properties文件做为配置的时候才须要双反斜杠。若是你使用YAML,单个反斜杠就足够了,192.168.\d{1,3}.\d{1,3}和上面的等价。

另外,经过在一个TomcatEmbeddedServletContainerFactory bean中配置和添加RemoteIpValve,你就能够彻底控制它的设置了。

4.9. 使用Jetty替代Tomcat

Spring Boot starters(特别是spring-boot-starter-web)默认都是使用Tomcat做为内嵌容器的。你须要排除那些Tomcat的依赖并包含Jetty的依赖。为了让这种处理尽量简单,Spring Boot将Tomcat和Jetty的依赖捆绑在一块儿,而后提供单独的starters。

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.3.0.BUILD-SNAPSHOT")
    compile("org.springframework.boot:spring-boot-starter-jetty:1.3.0.BUILD-SNAPSHOT")
    // ...
}

4.10. 配置Jetty

一般你能够遵循Section 63.7, “Discover built-in options for external properties”关于@ConfigurationProperties(此处主要是ServerProperties)的建议,但也要看下EmbeddedServletContainerCustomizer。Jetty API至关丰富,一旦获取到JettyEmbeddedServletContainerFactory,你就可使用不少方式修改它。或更完全地就是添加你本身的JettyEmbeddedServletContainerFactory。

4.11. 使用Undertow替代Tomcat

使用Undertow替代Tomcat和使用Jetty替代Tomcat很是相似。你须要排除Tomat依赖,并包含Undertow starter。

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.3.0.BUILD-SNAPSHOT")
    compile 'org.springframework.boot:spring-boot-starter-undertow:1.3.0.BUILD-SNAPSHOT")
    // ...
}

4.13. 启用Undertow的多监听器(Multiple Listeners)

往UndertowEmbeddedServletContainerFactory添加一个UndertowBuilderCustomizer,而后添加一个监听者到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;
}

4.14. 使用Tomcat7

Tomcat7可用于Spring Boot,但默认使用的是Tomcat8。若是不能使用Tomcat8(例如,你使用的是Java1.6),你须要改变classpath去引用Tomcat7。

4.14.1. 经过Maven使用Tomcat7

若是正在使用starter pom和parent,你只须要改变Tomcat的version属性,好比,对于一个简单的webapp或service:

<properties>
    <tomcat.version>7.0.59</tomcat.version>
</properties>
<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    ...
</dependencies>

4.14.2. 经过Gradle使用Tomcat7

你能够经过设置tomcat.version属性改变Tomcat的版本:

ext['tomcat.version'] = '7.0.59' dependencies { compile 'org.springframework.boot:spring-boot-starter-web' }

4.15. 使用Jetty8

Jetty8可用于Spring Boot,但默认使用的是Jetty9。若是不能使用Jetty9(例如,由于你使用的是Java1.6),你只需改变classpath去引用Jetty8。你也须要排除Jetty的WebSocket相关的依赖。

4.15.1. 经过Maven使用Jetty8

若是正在使用starter pom和parent,你只需添加Jetty starter,去掉WebSocket依赖,并改变version属性,好比,对于一个简单的webapp或service:

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

4.16. 使用@ServerEndpoint建立WebSocket端点

若是想在一个使用内嵌容器的Spring Boot应用中使用@ServerEndpoint,你须要声明一个单独的ServerEndpointExporter @Bean:

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

该bean将用底层的WebSocket容器注册任何的被@ServerEndpoint注解的beans。当部署到一个单独的servlet容器时,该角色将被一个servlet容器初始化方法履行,ServerEndpointExporter bean也就不是必需的了。

4.17. 启用HTTP响应压缩

Spring Boot提供两种启用HTTP压缩的机制;一种是Tomcat特有的,另外一种是使用一个filter,能够配合Jetty,Tomcat和Undertow。

4.17.1. 启用Tomcat的HTTP响应压缩

Tomcat对HTTP响应压缩提供内建支持。默认是禁用的,但能够经过application.properties轻松的启用:

server.tomcat.compression: on

当设置为on时,Tomcat将压缩响应的长度至少为2048字节。你能够配置一个整型值来设置该限制而不仅是on,好比:

server.tomcat.compression: 4096

默认状况下,Tomcat只压缩某些MIME类型的响应(text/html,text/xml和text/plain)。你可使用server.tomcat.compressableMimeTypes属性进行自定义,好比:

server.tomcat.compressableMimeTypes=application/json,application/xml

4.17.2. 使用GzipFilter开启HTTP响应压缩

若是你正在使用Jetty或Undertow,或想要更精确的控制HTTP响应压缩,Spring Boot为Jetty的GzipFilter提供自动配置。虽然该过滤器是Jetty的一部分,但它也兼容Tomcat和Undertow。想要启用该过滤器,只需简单的为你的应用添加org.eclipse.jetty:jetty-servlets依赖。

GzipFilter可使用spring.http.gzip.*属性进行配置。具体参考GzipFilterProperties。

5. Spring MVC

5.1. 编写一个JSON REST服务

在Spring Boot应用中,任何Spring @RestController默认应该渲染为JSON响应,只要classpath下存在Jackson2。例如:

@RestController
public class MyController {

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

}

只要MyThing可以经过Jackson2序列化(好比,一个标准的POJO或Groovy对象),localhost:8080/thing默认响应一个JSON表示。有时在一个浏览器中你可能看到XML响应由于浏览器倾向于发送XML 响应头。

5.2. 编写一个XML REST服务

若是classpath下存在Jackson XML扩展(jackson-dataformat-xml),它会被用来渲染XML响应,示例和JSON的很是类似。想要使用它,只需为你的项目添加如下的依赖:

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

你可能也想添加对Woodstox的依赖。它比JDK提供的默认Stax实现快不少,而且支持良好的格式化输出,提升了namespace处理能力:

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

若是Jackson的XML扩展不可用,Spring Boot将使用JAXB(JDK默认提供),不过你须要为MyThing添加额外的注解@XmlRootElement:

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

想要服务器渲染XML而不是JSON,你可能须要发送一个Accept: text/xml头部(或使用浏览器)。

5.3. 自定义Jackson ObjectMapper

在一个HTTP交互中,Spring MVC(客户端和服务端)使用HttpMessageConverters协商内容转换。若是classpath下存在Jackson,你就已经获取到Jackson2ObjectMapperBuilder提供的默认转换器。

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

MapperFeature.DEFAULT_VIEW_INCLUSION禁用
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES禁用

Spring Boot也有一些简化自定义该行为的特性。

你可使用当前的environment配置ObjectMapper和XmlMapper实例。Jackson提供一个扩展套件,能够用来简单的关闭或开启一些特性,你能够用它们配置Jackson处理的不一样方面。这些特性在Jackson中使用5个枚举进行描述的,并被映射到environment的属性上:

Jackson枚举 Environment属性 com.fasterxml.jackson.databind.DeserializationFeaturespring.jackson.generator.=true false com.fasterxml.jackson.databind.MapperFeature spring.jackson.parser.=true falsecom.fasterxml.jackson.databind.SerializationFeature output=true能够开启漂亮打印。注意,因为松绑定的使用,indentoutput没必要匹配对应的枚举常量INDENT_OUTPUT。

若是想完全替换默认的ObjectMapper,你须要定义一个该类型的@Bean并将它标记为@Primary。

定义一个Jackson2ObjectMapperBuilder类型的@Bean将容许你自定义默认的ObjectMapper和XmlMapper(分别用于MappingJackson2HttpMessageConverter和MappingJackson2XmlHttpMessageConverter)。

另外一种自定义Jackson的方法是向你的上下文添加com.fasterxml.jackson.databind.Module类型的beans。它们会被注册入每一个ObjectMapper类型的bean,当为你的应用添加新特性时,这就提供了一种全局机制来贡献自定义模块。

最后,若是你提供任何MappingJackson2HttpMessageConverter类型的@Beans,那它们将替换MVC配置中的默认值。同时,也提供一个HttpMessageConverters类型的bean,它有一些有用的方法能够获取默认的和用户加强的message转换器。

5.4. 自定义@ResponseBody渲染

Spring使用HttpMessageConverters渲染@ResponseBody(或来自@RestController的响应)。你能够经过在Spring Boot上下文中添加该类型的beans来贡献其余的转换器。若是你添加的bean类型默认已经包含了(像用于JSON转换的MappingJackson2HttpMessageConverter),那它将替换默认的。Spring Boot提供一个方便的HttpMessageConverters类型的bean,它有一些有用的方法能够访问默认的和用户加强的message转换器(有用,好比你想要手动将它们注入到一个自定义的RestTemplate)。

在一般的MVC用例中,任何你提供的WebMvcConfigurerAdapter beans经过覆盖configureMessageConverters方法也能贡献转换器,但不一样于一般的MVC,你能够只提供你须要的转换器(由于Spring Boot使用相同的机制来贡献它默认的转换器)。最终,若是你经过提供本身的@EnableWebMvc注解覆盖Spring Boot默认的MVC配置,那你就能够彻底控制,并使用来自WebMvcConfigurationSupport的getMessageConverters手动作任何事。

5.5. 处理Multipart文件上传

Spring Boot采用Servlet 3 javax.servlet.http.Part API来支持文件上传。默认状况下,Spring Boot配置Spring MVC在单个请求中每一个文件最大1Mb,最多10Mb的文件数据。你能够覆盖那些值,也能够设置临时文件存储的位置(好比,存储到/tmp文件夹下)及传递数据刷新到磁盘的阀值(经过使用MultipartProperties类暴露的属性)。若是你须要设置文件不受限制,例如,能够设置multipart.maxFileSize属性值为-1。

当你想要接收部分(multipart)编码文件数据做为Spring MVC控制器(controller)处理方法中被@RequestParam注解的MultipartFile类型的参数时,multipart支持就很是有用了。

5.6. 关闭Spring MVC DispatcherServlet

Spring Boot想要服务来自应用程序root /下的全部内容。若是你想将本身的servlet映射到该目录下也是能够的,但固然你可能失去一些Boot MVC特性。为了添加你本身的servlet,并将它映射到root资源,你只需声明一个Servlet类型的@Bean,并给它特定的bean名称dispatcherServlet(若是只想关闭但不替换它,你可使用该名称建立不一样类型的bean)。

5.7. 关闭默认的MVC配置

彻底控制MVC配置的最简单方式是提供你本身的被@EnableWebMvc注解的@Configuration。这样全部的MVC配置都逃不出你的掌心。

5.8. 自定义ViewResolvers

ViewResolver是Spring MVC的核心组件,它负责转换@Controller中的视图名称到实际的View实现。注意ViewResolvers主要用在UI应用中,而不是REST风格的服务(View不是用来渲染@ResponseBody的)。Spring有不少你能够选择的ViewResolver实现,而且Spring本身对如何选择相应实现也没发表意见。另外一方面,Spring Boot会根据classpath上的依赖和应用上下文为你安装一或两个ViewResolver实现。DispatcherServlet使用全部在应用上下文中找到的解析器(resolvers),并依次尝试每个直到它获取到结果,因此若是你正在添加本身的解析器,那就要当心顺序和你的解析器添加的位置。

WebMvcAutoConfiguration将会为你的上下文添加如下ViewResolvers:

bean id为defaultViewResolver的InternalResourceViewResolver。这个会定位可使用DefaultServlet渲染的物理资源(好比,静态资源和JSP页面)。它在视图(view name)上应用了一个前缀和后缀(默认都为空,但你能够经过spring.view.prefix和spring.view.suffix外部配置设置),而后查找在servlet上下文中具备该路径的物理资源。能够经过提供相同类型的bean覆盖它。

id为beanNameViewResolver的BeanNameViewResolver。这是视图解析器链的一个很是有用的成员,它能够在View被解析时收集任何具备相同名称的beans。 id为viewResolver的ContentNegotiatingViewResolver只会在实际View类型的beans出现时添加。这是一个'主'解析器,它的职责会代理给其余解析器,它会尝试找到客户端发送的一个匹配'Accept'的HTTP头部。这有一篇有用的,关于你须要更多了解的ContentNegotiatingViewResolver的博客,也要具体查看下源码。经过定义一个名叫'viewResolver'的bean,你能够关闭自动配置的ContentNegotiatingViewResolver。

若是使用Thymeleaf,你将有一个id为thymeleafViewResolver的ThymeleafViewResolver。它会经过加前缀和后缀的视图名来查找资源(外部配置为spring.thymeleaf.prefix和spring.thymeleaf.suffix,对应的默认为'classpath:/templates/'和'.html')。你能够经过提供相同名称的bean来覆盖它。

若是使用FreeMarker,你将有一个id为freeMarkerViewResolver的FreeMarkerViewResolver。它会使用加前缀和后缀(外部配置为spring.freemarker.prefix和spring.freemarker.suffix,对应的默认值为空和'.ftl')的视图名从加载路径(外部配置为spring.freemarker.templateLoaderPath,默认为'classpath:/templates/')下查找资源。你能够经过提供一个相同名称的bean来覆盖它。

若是使用Groovy模板(实际上只要你把groovy-templates添加到classpath下),你将有一个id为groovyTemplateViewResolver的Groovy TemplateViewResolver。它会使用加前缀和后缀(外部属性为spring.groovy.template.prefix和spring.groovy.template.suffix,对应的默认值为'classpath:/templates/'和'.tpl')的视图名从加载路径下查找资源。你能够经过提供一个相同名称的bean来覆盖它。

若是使用Velocity,你将有一个id为velocityViewResolver的VelocityViewResolver。它会使用加前缀和后缀(外部属性为spring.velocity.prefix和spring.velocity.suffix,对应的默认值为空和'.vm')的视图名从加载路径(外部属性为spring.velocity.resourceLoaderPath,默认为'classpath:/templates/')下查找资源。你能够经过提供一个相同名称的bean来覆盖它。 具体参考: WebMvcAutoConfiguration,ThymeleafAutoConfiguration,FreeMarkerAutoConfiguration,GroovyTemplateAutoConfiguration, VelocityAutoConfiguration。

6. 日志

Spring Boot除了commons-logging API外没有其余强制性的日志依赖,你有不少可选的日志实现。想要使用Logback,你须要包含它,及一些对classpath下commons-logging的绑定。最简单的方式是经过依赖spring-boot-starter-logging的starter pom。对于一个web应用程序,你只需添加spring-boot-starter-web依赖,由于它依赖于logging starter。例如,使用Maven:

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

Spring Boot有一个LoggingSystem抽象,用于尝试经过classpath上下文配置日志系统。若是Logback可用,则首选它。若是你惟一须要作的就是设置不一样日志的级别,那能够经过在application.properties中使用logging.level前缀实现,好比:

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

你也可使用logging.file设置日志文件的位置(除控制台以外,默认会输出到控制台)。

想要对日志系统进行更细粒度的配置,你须要使用正在说的LoggingSystem支持的原生配置格式。默认状况下,Spring Boot从系统的默认位置加载原生配置(好比对于Logback为classpath:logback.xml),但你可使用logging.config属性设置配置文件的位置。

6.1. 配置Logback

若是你将一个logback.xml放到classpath根目录下,那它将会被从这加载。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>

若是查看spring-boot jar包中的默认logback.xml,你将会看到LoggingSystem为你建立的不少有用的系统属性,好比:

${PID},当前进程id
${LOG_FILE},若是在Boot外部配置中设置了logging.file
${LOG_PATH},若是设置了logging.path(表示日志文件产生的目录)

Spring Boot也提供使用自定义的Logback转换器在控制台上输出一些漂亮的彩色ANSI日志信息(不是日志文件)。具体参考默认的base.xml配置。

若是Groovy在classpath下,你也可使用logback.groovy配置Logback。

6.2. 配置Log4j

Spring Boot也支持Log4j或Log4j 2做为日志配置,但只有在它们中的某个在classpath下存在的状况。若是你正在使用starter poms进行依赖装配,这意味着你须要排除Logback,而后包含你选择的Log4j版本。若是你不使用starter poms,那除了你选择的Log4j版本外还要提供commons-logging(至少)。

最简单的方式可能就是经过starter poms,尽管它须要排除一些依赖,好比,在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-log4j</artifactId>
</dependency>

想要使用Log4j 2,只须要依赖spring-boot-starter-log4j2而不是spring-boot-starter-log4j。

注:使用Log4j各版本的starters都会收集好依赖以知足common logging的要求(好比,Tomcat中使用java.util.logging,但使用Log4j或 Log4j 2做为输出)。具体查看Actuator Log4j或Log4j 2的示例,了解如何将它用于实战。

6.2.1. 使用YAML或JSON配置Log4j2

除了它的默认XML配置格式,Log4j 2也支持YAML和JSON配置文件。想要使用其余配置文件格式来配置Log4j 2,你须要添加合适的依赖到classpath。为了使用YAML,你须要添加com.fasterxml.jackson.dataformat:jackson-dataformat-yaml依赖,Log4j 2将查找名称为log4j2.yaml或log4j2.yml的配置文件。为了使用JSON,你须要添加com.fasterxml.jackson.core:jackson-databind依赖,Log4j 2将查找名称为log4j2.json或log4j2.jsn的配置文件

7. 数据访问

7.1. 配置一个数据源

想要覆盖默认的设置只须要定义一个你本身的DataSource类型的@Bean。Spring Boot提供一个工具构建类DataSourceBuilder,可用来建立一个标准的DataSource(若是它处于classpath下),或者仅建立你本身的DataSource,而后将它和在Section 23.7.1, “Third-party configuration”解释的一系列Environment属性绑定。 好比:

@Bean
@ConfigurationProperties(prefix="datasource.mine")
public DataSource dataSource() {
    return new FancyDataSource();
}

datasource.mine.jdbcUrl=jdbc:h2:mem:mydb
datasource.mine.user=sa
datasource.mine.poolSize=30

具体参考'Spring Boot特性'章节中的Section 28.1, “Configure a DataSource”和DataSourceAutoConfiguration类源码。

7.2. 配置两个数据源

建立多个数据源和建立第一个工做都是同样的。若是使用针对JDBC或JPA的默认自动配置,你可能想要将其中一个设置为@Primary(而后它就能被任何@Autowired注入获取)。

@Bean
@Primary
@ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
@ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
    return DataSourceBuilder.create().build();
}

7.3. 使用Spring Data仓库

Spring Data能够为你的@Repository接口建立各类风格的实现。Spring Boot会为你处理全部事情,只要那些@Repositories接口跟你的@EnableAutoConfiguration类处于相同的包(或子包)。

对于不少应用来讲,你须要作的就是将正确的Spring Data依赖添加到classpath下(对于JPA有一个spring-boot-starter-data-jpa,对于MongoDB有一个spring-boot-starter-data-mongodb),建立一些repository接口来处理@Entity对象。具体参考JPA sample或Mongodb sample。

Spring Boot会基于它找到的@EnableAutoConfiguration来尝试猜想你的@Repository定义的位置。想要获取更多控制,可使用@EnableJpaRepositories注解(来自Spring Data JPA)。

7.4. 从Spring配置分离@Entity定义

Spring Boot会基于它找到的@EnableAutoConfiguration来尝试猜想你的@Entity定义的位置。想要获取更多控制,你可使用@EntityScan注解,好比:

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

    //...

}

7.5. 配置JPA属性

Spring Data JPA已经提供了一些独立的配置选项(好比,针对SQL日志),而且Spring Boot会暴露它们,针对hibernate的外部配置属性也更多些。最多见的选项以下:

spring.jpa.hibernate.ddl-auto: create-drop
spring.jpa.hibernate.naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.database: H2
spring.jpa.show-sql: true

(因为宽松的数据绑定策略,连字符或下划线做为属性keys做用应该是等效的)ddl-auto配置是个特殊状况,它有不一样的默认设置,这取决于你是否使用一个内嵌数据库(create-drop)。当本地EntityManagerFactory被建立时,全部spring.jpa.properties.*属性都被做为正常的JPA属性(去掉前缀)传递进去了。

具体参考HibernateJpaAutoConfiguration和JpaBaseConfiguration。

7.6. 使用自定义的EntityManagerFactory

为了彻底控制EntityManagerFactory的配置,你须要添加一个名为entityManagerFactory的@Bean。Spring Boot自动配置会根据是否存在该类型的bean来关闭它的实体管理器(entity manager)。

7.7. 使用两个EntityManagers

即便默认的EntityManagerFactory工做的很好,你也须要定义一个新的EntityManagerFactory,由于一旦出现第二个该类型的bean,默认的将会被关闭。为了轻松的实现该操做,你可使用Spring Boot提供的EntityManagerBuilder,或者若是你喜欢的话能够直接使用来自Spring ORM的LocalContainerEntityManagerFactoryBean。

示例:

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

上面的配置靠本身基本能够运行。想要完成做品你也须要为两个EntityManagers配置TransactionManagers。其中的一个会被Spring Boot默认的JpaTransactionManager获取,若是你将它标记为@Primary。另外一个须要显式注入到一个新实例。或你可使用一个JTA事物管理器生成它两个。

7.8. 使用普通的persistence.xml

Spring不要求使用XML配置JPA提供者(provider),而且Spring Boot假定你想要充分利用该特性。若是你倾向于使用persistence.xml,那你须要定义你本身的id为'entityManagerFactory'的LocalEntityManagerFactoryBean类型的@Bean,并在那设置持久化单元的名称。

默认设置可查看JpaBaseConfiguration

7.9. 使用Spring Data JPA和Mongo仓库

Spring Data JPA和Spring Data Mongo都能自动为你建立Repository实现。若是它们同时出如今classpath下,你可能须要添加额外的配置来告诉Spring Boot你想要哪一个(或两个)为你建立仓库。最明确地方式是使用标准的Spring Data @EnableRepositories,而后告诉它你的Repository接口的位置(此处便可以是Jpa,也能够是Mongo,或者二者都是)。

这里也有spring.data.*.repositories.enabled标志,可用来在外部配置中开启或关闭仓库的自动配置。这在你想关闭Mongo仓库,但仍旧使用自动配置的MongoTemplate时很是有用。

相同的障碍和特性也存在于其余自动配置的Spring Data仓库类型(Elasticsearch, Solr)。只须要改变对应注解的名称和标志。

7.10. 将Spring Data仓库暴露为REST端点

Spring Data REST可以将Repository的实现暴露为REST端点,只要该应用启用Spring MVC。

Spring Boot暴露一系列来自spring.data.rest命名空间的有用属性来定制化RepositoryRestConfiguration。若是须要提供其余定制,你能够建立一个继承自SpringBootRepositoryRestMvcConfiguration的@Configuration类。该类功能和RepositoryRestMvcConfiguration相同,但容许你继续使用spring.data.rest.*属性。

8. 数据库初始化

一个数据库可使用不一样的方式进行初始化,这取决于你的技术栈。或者你能够手动完成该任务,只要数据库是单独的过程。

8.1. 使用JPA初始化数据库

JPA有个生成DDL的特性,这些能够设置为在数据库启动时运行。这能够经过两个外部属性进行控制:

spring.jpa.generate-ddl(boolean)控制该特性的关闭和开启,跟实现者不要紧
spring.jpa.hibernate.ddl-auto(enum)是一个Hibernate特性,用于更细力度的控制该行为。更多详情参考如下内容。

8.2. 使用Hibernate初始化数据库

你能够显式设置spring.jpa.hibernate.ddl-auto,标准的Hibernate属性值有none,validate,update,create,create-drop。Spring Boot根据你的数据库是否为内嵌数据库来选择相应的默认值,若是是内嵌型的则默认值为create-drop,不然为none。经过查看Connection类型能够检查是否为内嵌型数据库,hsqldb,h2和derby是内嵌的,其余都不是。当从内存数据库迁移到一个真正的数据库时,你须要小心,在新的平台中不能对数据库表和数据是否存在进行臆断。你也须要显式设置ddl-auto,或使用其余机制初始化数据库。

此外,启动时处于classpath根目录下的import.sql文件会被执行。这在demos或测试时颇有用,但在生产环境中你可能不指望这样。这是Hibernate的特性,和Spring没有一点关系。

8.3. 使用Spring JDBC初始化数据库

Spring JDBC有一个DataSource初始化特性。Spring Boot默认启用了该特性,并从标准的位置schema.sql和data.sql(位于classpath根目录)加载SQL。此外,Spring Boot将加载schema-${platform}.sql和data-${platform}.sql文件(若是存在),在这里platform是spring.datasource.platform的值,好比,你能够将它设置为数据库的供应商名称(hsqldb, h2, Oracle, MySQL, postgresql等)。Spring Boot默认启用Spring JDBC初始化快速失败特性,因此若是脚本致使异常产生,那应用程序将启动失败。脚本的位置能够经过设置spring.datasource.schema和spring.datasource.data来改变,若是设置spring.datasource.initialize=false则哪一个位置都不会被处理。

你能够设置spring.datasource.continueOnError=true禁用快速失败特性。一旦应用程序成熟并被部署了不少次,那该设置就颇有用,由于脚本能够充当"可怜人的迁移"-例如,插入失败时意味着数据已经存在,也就不必阻止应用继续运行。

若是你想要在一个JPA应用中使用schema.sql,那若是Hibernate试图建立相同的表,ddl-auto=create-drop将致使错误产生。为了不那些错误,能够将ddl-auto设置为“”(推荐)或“none”。无论是否使用ddl-auto=create-drop,你总可使用data.sql初始化新数据。

8.4. 初始化Spring Batch数据库

若是你正在使用Spring Batch,那么它会为大多数的流行数据库平台预装SQL初始化脚本。Spring Boot会检测你的数据库类型,并默认执行那些脚本,在这种状况下将关闭快速失败特性(错误被记录但不会阻止应用启动)。这是由于那些脚本是可信任的,一般不会包含bugs,因此错误会被忽略掉,而且对错误的忽略可让脚本具备幂等性。你可使用spring.batch.initializer.enabled=false显式关闭初始化功能。

8.5. 使用一个高级别的数据迁移工具

Spring Boot跟高级别的数据迁移工具Flyway(基于SQL)和Liquibase(XML)工做的很好。一般咱们倾向于Flyway,由于它一眼看去好像很容易,另外它一般不须要平台独立:通常一个或至多须要两个平台。

8.5.1. 启动时执行Flyway数据库迁移

想要在启动时自动运行Flyway数据库迁移,须要将org.flywaydb:flyway-core添加到你的classpath下。

迁移是一些V_.sql格式的脚本(是一个下划线分割的版本号,好比'1'或'21')。默认状况下,它们存放在一个classpath:db/migration的文件夹中,但你可使用flyway.locations(一个列表)来改变它。详情可参考flyway-core中的Flyway类,查看一些可用的配置,好比schemas。Spring Boot在FlywayProperties中提供了一个小的属性集,可用于禁止迁移,或关闭位置检测。

默认状况下,Flyway将自动注入(@Primary)DataSource到你的上下文,并用它进行数据迁移。若是你想使用一个不一样的DataSource,你能够建立一个,并将它标记为@FlywayDataSource的@Bean-若是你这样作了,且想要两个数据源,记得建立另外一个并将它标记为@Primary。或者你能够经过在外部配置文件中设置flyway.[url,user,password]来使用Flyway的原生DataSource。

这是一个Flyway示例,你能够做为参考。

8.5.2. 启动时执行Liquibase数据库迁移

想要在启动时自动运行Liquibase数据库迁移,你须要将org.liquibase:liquibase-core添加到classpath下。

主改变日志(master change log)默认从db/changelog/db.changelog-master.yaml读取,但你可使用liquibase.change-log进行设置。详情查看LiquibaseProperties以获取可用设置,好比上下文,默认的schema等。

这里有个Liquibase示例可做为参考。

9. 批处理应用

9.1. 在启动时执行Spring Batch做业

你能够在上下文的某个地方添加@EnableBatchProcessing来启用Spring Batch的自动配置功能。

默认状况下,在启动时它会执行应用的全部做业(Jobs),具体查看JobLauncherCommandLineRunner。你能够经过指定spring.batch.job.names(多个做业名以逗号分割)来缩小到一个特定的做业或多个做业。

若是应用上下文包含一个JobRegistry,那么处于spring.batch.job.names中的做业将会从registry中查找,而不是从上下文中自动装配。这是复杂系统中常见的一个模式,在这些系统中多个做业被定义在子上下文和注册中心。

具体参考BatchAutoConfiguration和@EnableBatchProcessing。

10. 执行器(Actuator)

10.1. 改变HTTP端口或执行器端点的地址

在一个单独的应用中,执行器的HTTP端口默认和主HTTP端口相同。想要让应用监听不一样的端口,你能够设置外部属性management.port。为了监听一个彻底不一样的网络地址(好比,你有一个用于管理的内部网络和一个用于用户应用程序的外部网络),你能够将management.address设置为一个可用的IP地址,而后将服务器绑定到该地址。

查看ManagementServerProperties源码和'Production-ready特性'章节中的Section 41.3, “Customizing the management server port”来获取更多详情。

10.2. 自定义'白标'(whitelabel,能够了解下相关理念)错误页面

Spring Boot安装了一个'whitelabel'错误页面,若是你遇到一个服务器错误(机器客户端消费的是JSON,其余媒体类型则会看到一个具备正确错误码的合乎情理的响应),那就能在客户端浏览器中看到该页面。你能够设置error.whitelabel.enabled=false来关闭该功能,但一般你想要添加本身的错误页面来取代whitelabel。确切地说,如何实现取决于你使用的模板技术。例如,你正在使用Thymeleaf,你将添加一个error.html模板。若是你正在使用FreeMarker,那你将添加一个error.ftl模板。一般,你须要的只是一个名称为error的View,和/或一个处理/error路径的@Controller。除非你替换了一些默认配置,不然你将在你的ApplicationContext中找到一个BeanNameViewResolver,因此一个id为error的@Bean多是完成该操做的一个简单方式。详情参考ErrorMvcAutoConfiguration。

查看Error Handling章节,了解下如何将处理器(handlers)注册到servlet容器中。

11. 安全

11.1. 关闭Spring Boot安全配置

无论你在应用的什么地方定义了一个使用@EnableWebSecurity注解的@Configuration,它将会关闭Spring Boot中的默认webapp安全设置。想要调整默认值,你能够尝试设置security.*属性(具体查看SecurityProperties和常见应用属性的SECURITY章节)。

11.2. 改变AuthenticationManager并添加用户帐号

若是你提供了一个AuthenticationManager类型的@Bean,那么默认的就不会被建立了,因此你能够得到Spring Security可用的所有特性(好比,不一样的认证选项)。

Spring Security也提供了一个方便的AuthenticationManagerBuilder,可用于构建具备常见选项的AuthenticationManager。在一个webapp中,推荐将它注入到WebSecurityConfigurerAdapter的一个void方法中,好比:

@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混合在一块儿将容许你改变实例化的顺序)。secure web sample是一个有用的参考模板。

若是你遇到了实例化问题(好比,使用JDBC或JPA进行用户详细信息的存储),那将AuthenticationManagerBuilder回调提取到一个GlobalAuthenticationConfigurerAdapter(放到init()方法内以防其余地方也须要authentication manager)多是个不错的选择,好比:

@Configuration
public class AuthenticationManagerConfiguration extends

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

}

11.3. 当前端使用代理服务器时,启用HTTPS

对于任何应用来讲,确保全部的主端点(URL)都只在HTTPS下可用是个重要的苦差事。若是你使用Tomcat做为servlet容器,那Spring Boot若是发现一些环境设置的话,它将自动添加Tomcat本身的RemoteIpValve,你也能够依赖于HttpServletRequest来报告是否请求是安全的(即便代理服务器的downstream处理真实的SSL终端)。这个标准行为取决于某些请求头是否出现(x-forwarded-for和x-forwarded-proto),这些请求头的名称都是约定好的,因此对于大多数前端和代理都是有效的。

你能够向application.properties添加如下设置里开启该功能,好比:

server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto

(这些属性出现一个就会开启该功能,或者你能够经过添加一个TomcatEmbeddedServletContainerFactory bean本身添加RemoteIpValve)

Spring Security也能够配置成针对因此或某些请求须要一个安全渠道(channel)。想要在一个Spring Boot应用中开启它,你只需将application.properties中的security.require_ssl设置为true便可。

  1. 热交换 =======

12.1. 从新加载静态内容

Spring Boot有不少用于热加载的选项。使用IDE开发是一个不错的方式,特别是须要调试的时候(全部的现代IDEs都容许从新加载静态资源,一般也支持对变动的Java类进行热交换)。Maven和Gradle插件也支持命令行下的静态文件热加载。若是你使用其余高级工具编写css/js,并使用外部的css/js编译器,那你就能够充分利用该功能。

12.2. 在不重启容器的状况下从新加载Thymeleaf模板

若是你正在使用Thymeleaf,那就将spring.thymeleaf.cache设置为false。查看ThymeleafAutoConfiguration能够获取其余Thymeleaf自定义选项。

12.3. 在不重启容器的状况下从新加载FreeMarker模板

若是你正在使用FreeMarker,那就将spring.freemarker.cache设置为false。查看FreeMarkerAutoConfiguration 能够获取其余FreeMarker自定义选项。

12.4. 在不重启容器的状况下从新加载Groovy模板

若是你正在使用Groovy模板,那就将spring.groovy.template.cache设置为false。查看GroovyTemplateAutoConfiguration能够获取其余Groovy自定义选项。

12.5. 在不重启容器的状况下从新加载Velocity模板

若是你正在使用Velocity,那就将spring.velocity.cache设置为false。查看VelocityAutoConfiguration能够获取其余Velocity自定义选项。

12.6. 在不重启容器的状况下从新加载Java类

现代IDEs(Eclipse, IDEA等)都支持字节码的热交换,因此若是你作了一个没有影响类或方法签名的改变,它会利索地从新加载并无任何影响。

Spring Loaded在这方面走的更远,它可以从新加载方法签名改变的类定义。若是对它进行一些自定义配置能够强制ApplicationContext刷新本身(但没有通用的机制来确保这对一个运行中的应用老是安全的,因此它可能只是一个开发时间的技巧)。

12.6.1. 使用Maven配置Spring Loaded

为了在Maven命令行下使用Spring Loaded,你只需将它做为一个依赖添加到Spring Boot插件声明中便可,好比:

org.springframework.boot spring-boot-maven-plugin org.springframework springloaded 1.2.0.RELEASE 正常状况下,这在Eclipse和IntelliJ中工做的至关漂亮,只要它们有相应的,和Maven默认一致的构建配置(Eclipse m2e对此支持的更好,开箱即用)。

13 构建

13.1. 使用Maven自定义依赖版本

若是你使用Maven进行一个直接或间接继承spring-boot-dependencies(好比spring-boot-starter-parent)的构建,并想覆盖一个特定的第三方依赖,那你能够添加合适的元素。浏览spring-boot-dependencies POM能够获取一个全面的属性列表。例如,想要选择一个不一样的slf4j版本,你能够添加如下内容:

<properties>
    <slf4j.version>1.7.5<slf4j.version>
</properties>

注:这只在你的Maven项目继承(直接或间接)自spring-boot-dependencies才有用。若是你使用import,将spring-boot-dependencies添加到本身的dependencyManagement片断,那你必须本身从新定义artifact而不是覆盖属性。

注:每一个Spring Boot发布都是基于一些特定的第三方依赖集进行设计和测试的,覆盖版本可能致使兼容性问题。

13.2. 使用Maven建立可执行JAR

spring-boot-maven-plugin可以用来建立可执行的'胖'JAR。若是你正在使用spring-boot-starter-parent POM,你能够简单地声明该插件,而后你的jar将被从新打包:

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

若是没有使用parent POM,你仍旧可使用该插件。不过,你须要另外添加一个片断:

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

查看插件文档获取详细的用例。

13.3. 建立其余的可执行JAR

若是你想将本身的项目以library jar的形式被其余项目依赖,而且须要它是一个可执行版本(例如demo),你须要使用略微不一样的方式来配置该构建。

对于Maven来讲,正常的JAR插件和Spring Boot插件都有一个'classifier',你能够添加它来建立另外的JAR。示例以下(使用Spring Boot Starter Parent管理插件版本,其余配置采用默认设置):

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

上述配置会产生两个jars,默认的一个和使用带有classifier 'exec'的Boot插件构建的可执行的一个。

对于Gradle用户来讲,步骤相似。示例以下:

bootRepackage  {
    classifier = 'exec'
}

13.4. 在可执行jar运行时提取特定的版本

在一个可执行jar中,为了运行,多数内嵌的库不须要拆包(unpacked),然而有一些库可能会遇到问题。例如,JRuby包含它本身的内嵌jar,它假定jruby-complete.jar自己老是可以直接做为文件访问的。

为了处理任何有问题的库,你能够标记那些特定的内嵌jars,让它们在可执行jar第一次运行时自动解压到一个临时文件夹中。例如,为了将JRuby标记为使用Maven插件拆包,你须要添加以下的配置:

<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']
}

13.6. 远程调试一个使用Maven启动的Spring Boot项目

想要为使用Maven启动的Spring Boot应用添加一个远程调试器,你可使用mave插件的jvmArguments属性。详情参考示例。

13.7. 远程调试一个使用Gradle启动的Spring Boot项目

想要为使用Gradle启动的Spring Boot应用添加一个远程调试器,你可使用build.gradle的applicationDefaultJvmArgs属性或--debug-jvm命令行选项。

build.gradle:

applicationDefaultJvmArgs = [
    "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
]

命令行:

$ gradle run --debug-jvm

详情查看Gradle应用插件。

13.9. 如何使用Java6

若是想在Java6环境中使用Spring Boot,你须要改变一些配置。具体的变化取决于你应用的功能。

13.9.1. 内嵌Servlet容器兼容性

若是你在使用Boot的内嵌Servlet容器,你须要使用一个兼容Java6的容器。Tomcat 7和Jetty 8都是Java 6兼容的。具体参考Section 63.15, “Use Tomcat 7”和Section 63.16, “Use Jetty 8”。

13.9.2. JTA API兼容性

Java事务API自身并不要求Java 7,而是官方的API jar包含的已构建类要求Java 7。若是你正在使用JTA,那么你须要使用可以在Java 6工做的构建版本替换官方的JTA 1.2 API jar。为了完成该操做,你须要排除任何对javax.transaction:javax.transaction-api的传递依赖,并使用org.jboss.spec.javax.transaction:jboss-transaction-api1.2spec:1.0.0.Final依赖替换它们。

14 传统部署

14.1. 建立一个可部署的war文件

产生一个可部署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的war插件),全部你须要作的就是更改pom.xml的packaging为war:

<packaging>war</packaging>

若是你使用Gradle,你须要修改build.gradle来将war插件应用到项目上:

apply plugin: 'war'

该过程最后的一步是确保内嵌的servlet容器不能干扰war包将部署的servlet容器。为了达到这个目的,你须要将内嵌容器的依赖标记为provided。

若是使用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'
    // …
}

若是你使用Spring Boot构建工具,将内嵌容器依赖标记为provided将产生一个可执行war包,在lib-provided目录有该war包的provided依赖。这意味着,除了部署到servlet容器,你还能够经过使用命令行java -jar命令来运行应用。

注:查看Spring Boot基于以上配置的一个Maven示例应用。

14.2. 为老的servlet容器建立一个可部署的war文件

老的Servlet容器不支持在Servlet 3.0中使用的ServletContextInitializer启动处理。你仍旧能够在这些容器使用Spring和Spring Boot,但你须要为应用添加一个web.xml,并将它配置为经过一个DispatcherServlet加载一个ApplicationContext。

14.3. 将现有的应用转换为Spring Boot

对于一个非web项目,转换为Spring Boot应用很容易(抛弃建立ApplicationContext的代码,取而代之的是调用SpringApplication或SpringApplicationBuilder)。Spring MVC web应用一般先建立一个可部署的war应用,而后将它迁移为一个可执行的war或jar。建议阅读Getting Started Guide on Converting a jar to a war.。

经过继承SpringBootServletInitializer建立一个可执行war(好比,在一个名为Application的类中),而后添加Spring Boot的@EnableAutoConfiguration注解。示例:

@Configuration
@EnableAutoConfiguration
@ComponentScan
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 we actually don't
        // need to override this method.
        return application;
    }

}

记住无论你往sources放什么东西,它仅是一个Spring ApplicationContext,正常状况下,任何生效的在这里也会起做用。有一些beans你能够先移除,而后让Spring Boot提供它的默认实现,不过有可能须要先完成一些事情。

静态资源能够移到classpath根目录下的/public(或/static,/resources,/META-INF/resources)。一样的方式也适合于messages.properties(Spring Boot在classpath根目录下自动发现这些配置)。

美妙的(Vanilla usage of)Spring DispatcherServlet和Spring Security不须要改变。若是你的应用有其余特性,好比使用其余servlets或filters,那你可能须要添加一些配置到你的Application上下文中,按如下操做替换web.xml的那些元素:

在容器中安装一个Servlet或ServletRegistrationBean类型的@Bean,就好像web.xml中的和<servlet-mapping/>。 一样的添加一个Filter或FilterRegistrationBean类型的@Bean(相似于和<filter-mapping/>)。 在XML文件中的ApplicationContext能够经过@Import添加到你的Application中。简单的状况下,大量使用注解配置能够在几行内定义@Bean定义。 一旦war可使用,咱们就经过添加一个main方法到Application来让它能够执行,好比:

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

应用能够划分为多个类别:

没有web.xml的Servlet 3.0+应用
有web.xml的应用
有上下文层次的应用
没有上下文层次的应用
全部这些均可以进行适当的转化,但每一个可能须要稍微不一样的技巧。

Servlet 3.0+的应用转化的至关简单,若是它们已经使用Spring Servlet 3.0+初始化器辅助类。一般全部来自一个存在的WebApplicationInitializer的代码能够移到一个SpringBootServletInitializer中。若是一个存在的应用有多个ApplicationContext(好比,若是它使用AbstractDispatcherServletInitializer),那你能够将全部上下文源放进一个单一的SpringApplication。你遇到的主要难题多是若是那样不能工做,那你就要维护上下文层次。参考示例entry on building a hierarchy。一个存在的包含web相关特性的父上下文一般须要分解,这样全部的ServletContextAware组件都处于子上下文中。

对于还不是Spring应用的应用来讲,上面的指南有助于你把应用转换为一个Spring Boot应用,但你也能够选择其余方式。

14.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>
相关文章
相关标签/搜索