第4章 使用 Spring Boot

使用 Spring Boot

    本部分将详细介绍如何使用Spring Boot。 这部分涵盖诸如构建系统,自动配置以及如何运行应用程序等主题。 我们还介绍了一些Spring Boot的最佳实践(best practices)。 虽然Spring Boot没有什么特殊之处(它只是一个可以使用的库),但是有一些建议可以让您的开发过程更容易一些。

如果您刚刚开始使用Spring Boot,那么在深入本部分之前,您应该阅读入门指南

13. 构建系统

强烈建议您选择一个支持依赖管理并可以使用“Maven Central”存储库的构建系统。 我们建议您选择Maven或Gradle。 Spring Boot 可以与其他构建系统(例如 Ant )配合使用,但是它们不会得到很好的支持。

13.1 依赖管理

每个版本的Spring Boot提供了一个它所支持的依赖关系列表。 实际上,您不需要为构建配置文件中的这些依赖关系提供版本,因为Spring Boot会为您进行管理这些依赖的版本。 当您升级Spring Boot本身时,这些依赖关系也将以一致的进行升级。

如果您觉得有必要,您仍然可以指定一个版本并覆盖Spring Boot建议的版本。

管理的列表中包含可以使用Spring Boot的所有Spring模块以及第三方库的精简列表。 该列表可作为标准的物料(Materials)清单(spring-boot-dependencies)使用,并且还提供了对 MavenGradle 的额外支持。

Spring Boot的每个版本与Spring Framework的基本版本相关联,因此我们强烈建议您不要自己指定其版本。

13.2 Maven

Maven用户可以从 spring-boot-starter-parent-parent 项目中继承,以获得合理的默认值。 父项目提供以下功能:

  • Java 1.6作为默认编译器级别。
  • 源代码UTF-8编码。
  • 依赖关系管理,允许您省略常见依赖的标签,其默认版本继承自spring-boot-dependencies POM。
  • 更合理的资源过滤
  • 更合理的插件配置(exec pluginsurefireGit commit IDshade)。
  • 针对application.properties和application.yml的更合理的资源过滤,包括特定的文件(例如application-foo.properties和application-foo.yml)
  • 最后一点:由于默认的配置文件接受Spring样式占位符(${…}),Maven过滤更改为使用 @..@ 占位符(您可以使用Maven属性resource.delimiter覆盖它)。

13.2.1 继承启动器parent

要将项目配置为继承spring-boot-starter-parent,只需设置标签如下:

<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>

您只需要在此依赖项上指定Spring Boot版本号。 如果您导入其他起始器,则可以放心地省略他们的版本号。

通过该设置,您还可以通过覆盖自己的项目中的属性来覆盖单个依赖。 例如,要升级到另一个 Spring Data 版本序列,您需要将以下内容添加到您的pom.xml中。

<properties>
<spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>

检查 spring-boot-dependencies pom 以获取支持的属性列表。

13.2.2 使用没有父POM的 Spring Boot

不是每个人都喜欢从spring-boot-starter-parent POM继承。 您公司可能有自己标准的父母,或者您可能只希望明确声明所有的Maven配置。

如果您不想使用spring-boot-starter-parent,则仍然可以通过使用scope=import依赖来保持依赖管理(但不能进行插件管理)的好处:

<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

该设置不允许您使用如13.2.1 所述的属性来覆盖单个依赖关系。 要实现相同的结果,您需要在spring-boot-dependencies条目之前在项目的dependencyManagement中添加一个条目。 例如,要升级到另一个Spring Data发行版本,您需要将以下内容添加到您的pom.xml中。

<dependencyManagement>
<dependencies>
<!-- Override Spring Data release train provided by Spring Boot -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Fowler-SR2</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

在上面的例子中,我们指定了一个BOM,但是任何依赖关系类型都可以被这样覆盖。

13.2.3 更改Java版本

spring-boot-starter-parent选择相当保守的Java兼容性版本。 如果要遵循我们的建议并使用更高版本的Java版本,可以添加java.version属性:

<properties>
<java.version>1.8</java.version>
</properties>

13.2.4 使用Spring Boot Maven插件

Spring Boot包括一个Maven插件,可以将项目打包成可执行jar。 如果要使用它,请将插件添加到部分:

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

如果您使用Spring Boot启动器 parent pom,则只需要添加这个插件,除非您要更改parent中定义的设置,否则不需要进行配置。

13.3 Gradle

Gradle用户可以直接在其依赖关系部分导入“启动器”。 不像Maven,没有“超级父”导入来共享一些配置。

repositories {
jcenter()
}

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

spring-boot-gradle-plugin也是可用的,它提供了从源代码创建可执行jar并运行项目的任务。 它还提供依赖关系管理,除其他功能外,还允许您省略由Spring Boot管理的任何依赖关系的版本号:

plugins {
id 'org.springframework.boot' version '1.5.2.RELEASE'
id 'java'
}


repositories {
jcenter()
}

dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}

13.4 Ant

可以使用Apache Ant + Ivy构建Spring Boot项目。 spring-boot-antlib“AntLib”模块也可用于帮助Ant创建可执行文件。

要声明依赖关系,典型的ivy.xml文件将如下所示:

<ivy-module version="2.0">
<info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
<configurations>
<conf name="compile" description="everything needed to compile this module" />
<conf name="runtime" extends="compile" description="everything needed to run this module" />
</configurations>
<dependencies>
<dependency org="org.springframework.boot" name="spring-boot-starter"
rev="${spring-boot.version}" conf="compile" />
</dependencies>
</ivy-module>

典型的build.xml将如下所示:

<project
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp" default="build">

<property name="spring-boot.version" value="1.3.0.BUILD-SNAPSHOT" />

<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" />
</target>

<target name="classpaths" depends="resolve">
<path id="compile.classpath">
<fileset dir="lib/compile" includes="*.jar" />
</path>
</target>

<target name="init" depends="classpaths">
<mkdir dir="build/classes" />
</target>

<target name="compile" depends="init" description="compile">
<javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" />
</target>

<target name="build" depends="compile">
<spring-boot:exejar destfile="build/myapp.jar" classes="build/classes">
<spring-boot:lib>
<fileset dir="lib/runtime" />
</spring-boot:lib>
</spring-boot:exejar>
</target>
</project>

请参见第84.10节“从Ant构建可执行存档,而不使用spring-boot-antlib”如果不想使用spring-boot-antlib模块,请参阅“操作方法”。

13.5 启动器

启动器是一组方便的依赖关系描述符,可以包含在应用程序中。 您可以获得所需的所有Spring和相关技术的一站式服务,无需通过示例代码搜索和复制粘贴依赖配置。 例如,如果要开始使用Spring和JPA进行数据库访问,那么只需在项目中包含spring-boot-starter-data-jpa依赖关系即可。

启动器包含许多依赖关系,包括您需要使项目快速启动并运行,并具有一致的受支持的依赖传递关系。

What’s in a name

所有正式起动器都遵循类似的命名模式: spring-boot-starter- ,其中 是特定类型的应用程序。 这个命名结构旨在帮助你快速找到一个启动器。 许多IDE中的Maven插件允许您按名称搜索依赖项。 例如,安装Eclipse或STS的Maven插件后,您可以简单地在POM编辑器中点击 Dependency Hierarchy,并在filter输入“spring-boot-starter”来获取完整的列表。
创建自己的启动器部分所述,第三方启动程序不应该从Spring-boot开始,因为它是为正式的Spring Boot artifacts 保留的。 acme 的 第三方启动器通常被命名为acme-spring-boot-starter。

Spring Boot在org.springframework.boot组下提供了以下应用程序启动器:

表13.1. Spring Boot应用程序启动器

名称描述Pom
spring-boot-starter-thymeleaf 使用Thymeleaf视图构建MVC Web应用程序的启动器 Pom
spring-boot-starter-data-couchbase 使用Couchbase面向文档的数据库和Spring Data Couchbase的启动器 Pom
spring-boot-starter-artemis 使用Apache Artemis的JMS启动器 Pom
spring-boot-starter-web-services Spring Web Services 启动器 Pom
spring-boot-starter-mail Java Mail和Spring Framework的电子邮件发送支持的启动器 Pom
spring-boot-starter-data-redis Redis key-value 数据存储与Spring Data Redis和Jedis客户端启动器 Pom
spring-boot-starter-web 使用Spring MVC构建Web,包括RESTful应用程序。使用Tomcat作为默认的嵌入式容器的启动器 Pom
spring-boot-starter-data-gemfire 使用GemFire分布式数据存储和Spring Data GemFire的启动器 Pom
spring-boot-starter-activemq 使用Apache ActiveMQ的JMS启动器 Pom
spring-boot-starter-data-elasticsearch 使用Elasticsearch搜索和分析引擎和Spring Data Elasticsearch的启动器 Pom
spring-boot-starter-integration Spring Integration 启动器 Pom
spring-boot-starter-test 使用JUnit,Hamcrest和Mockito的库测试Spring Boot应用程序的启动器 Pom
spring-boot-starter-jdbc 使用JDBC与Tomcat JDBC连接池的启动器 Pom
spring-boot-starter-mobile 使用Spring Mobile构建Web应用程序的启动器 Pom
spring-boot-starter-validation 使用Java Bean Validation 与Hibernate Validator的启动器 Pom
spring-boot-starter-hateoas 使用Spring MVC和Spring HATEOAS构建基于超媒体的RESTful Web应用程序的启动器 Pom
spring-boot-starter-jersey 使用JAX-RS和Jersey构建RESTful Web应用程序的启动器。spring-boot-starter-web的替代方案 Pom
spring-boot-starter-data-neo4j 使用Neo4j图数据库和Spring Data Neo4j的启动器 Pom
spring-boot-starter-data-ldap 使用Spring Data LDAP的启动器 Pom
spring-boot-starter-websocket 使用Spring Framework的WebSocket支持构建WebSocket应用程序的启动器 Pom
spring-boot-starter-aop 使用Spring AOP和AspectJ进行面向切面编程的启动器 Pom
spring-boot-starter-amqp 使用Spring AMQP和Rabbit MQ的启动器 Pom
spring-boot-starter-data-cassandra 使用Cassandra分布式数据库和Spring Data Cassandra的启动器 Pom
spring-boot-starter-social-facebook 使用Spring Social Facebook 的启动器 Pom
spring-boot-starter-jta-atomikos 使用Atomikos的JTA事务的启动器 Pom
spring-boot-starter-security 使用Spring Security的启动器 Pom
spring-boot-starter-mustache 使用Mustache视图构建MVC Web应用程序的启动器 Pom
spring-boot-starter-data-jpa 使用Spring数据JPA与Hibernate的启动器 Pom
spring-boot-starter 核心启动器,包括自动配置支持,日志记录和YAML Pom
spring-boot-starter-groovy-templates 使用Groovy模板视图构建MVC Web应用程序的启动器 Pom
spring-boot-starter-freemarker 使用FreeMarker视图构建MVC Web应用程序的启动器 Pom
spring-boot-starter-batch 使用Spring Batch的启动器 Pom
spring-boot-starter-social-linkedin 使用Spring Social LinkedIn的启动器 Pom
spring-boot-starter-cache 使用Spring Framework缓存支持的启动器 Pom
spring-boot-starter-data-solr 使用Apache Solr搜索平台与Spring Data Solr的启动器 Pom
spring-boot-starter-data-mongodb 使用MongoDB面向文档的数据库和Spring Data MongoDB的启动器 Pom
spring-boot-starter-jooq 使用jOOQ访问SQL数据库的启动器。 spring-boot-starter-data-jpa或spring-boot-starter-jdbc的替代方案 Pom
spring-boot-starter-jta-narayana Spring Boot Narayana JTA 启动器 Pom
spring-boot-starter-cloud-connectors 使用Spring Cloud连接器,简化了与Cloud Foundry和Heroku等云平台中的服务连接的启动器 Pom
spring-boot-starter-jta-bitronix 使用Bitronix进行JTA 事务的启动器 Pom
spring-boot-starter-social-twitter 使用Spring Social Twitter的启动器 Pom
spring-boot-starter-data-rest 通过使用Spring Data REST在REST上暴露Spring数据库的启动器 Pom

除了应用程序启动器,以下启动器可用于添加生产准备(production ready)功能:

表13.2 Spring Boot生产环境启动器

名称描述Pom
spring-boot-starter-actuator 使用Spring Boot Actuator提供生产准备功能,可帮助您监控和管理应用程序的启动器 Pom
spring-boot-starter-remote-shell 使用CRaSH远程shell通过SSH监视和管理您的应用程序的启动器。 自1.5以来已弃用 Pom

最后,Spring Boot还包括一些启动器,如果要排除或替换特定的技术,可以使用它们:

名称描述Pom
spring-boot-starter-undertow 使用Undertow作为嵌入式servlet容器的启动器。 spring-boot-starter-tomcat的替代方案 Pom
spring-boot-starter-jetty 使用Jetty作为嵌入式servlet容器的启动器。 spring-boot-starter-tomcat的替代方案 Pom
spring-boot-starter-logging 使用Logback进行日志记录的启动器。 默认的日志启动器 Pom
spring-boot-starter-tomcat 使用Tomcat作为嵌入式servlet容器的启动器。 spring-boot-starter-web的默认servlet容器启动器 Pom
spring-boot-starter-log4j2 使用Log4j2进行日志记录的启动器。 spring-boot-start-logging的替代方法 Pom

有关社区贡献的更多启动器的列表,请参阅GitHub上的spring-boot-startters模块中的README文件

14. 构建代码

Spring Boot不需要任何特定的代码组织结构,但是有一些最佳实践可以帮助您。

14.1 不要使用“default”包

当类不包括包声明时,它被认为是在“默认包”中。 通常不鼓励使用“默认包”,并应该避免使用。 对于使用@ComponentScan,@EntityScan或@SpringBootApplication注解的Spring Boot应用程序,可能会有一些特殊的问题,因为每个jar的每个类都将被读取。

我们建议您遵循Java推荐的软件包命名约定,并使用反向域名(例如,com.example.project)。

14.2 查找主应用程序类

我们通常建议您将应用程序主类放到其他类之上的根包(root package)中。 @EnableAutoConfiguration注解通常放置在您的主类上,它隐式定义了某些项目的基本“搜索包”。 例如,如果您正在编写JPA应用程序,则@EnableAutoConfiguration注解类的包将用于搜索@Entity项。

使用根包(root package)还可以使用@ComponentScan注释,而不需要指定basePackage属性。 如果您的主类在根包中,也可以使用@SpringBootApplication注释。

这是一个典型的布局:

com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java

Application.java文件将声明main方法以及基本的@Configuration。

package com.example.myproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {

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

}

15. 配置类

Spring Boot支持基于Java的配置。虽然可以使用XML配置用SpringApplication.run(),但我们通常建议您的主source是@Configuration类。 通常,定义main方法的类也是作为主要的@Configuration一个很好的选择。

许多使用XML配置的Spring示例已经在网上发布。 如果可能的话我们建议始终尝试使用等效的基于Java的配置。 搜索 enable* 注解可以是一个很好的起点。

15.1 导入其他配置类

您不需要将所有的@Configuration放在一个类中。 @Import注解可用于导入其他配置类。 或者,您可以使用@ComponentScan自动扫描所有Spring组件,包括@Configuration类。

15.2 导入XML配置

如果您必须使用基于XML的配置,我们建议您仍然从@Configuration类开始。 然后,您可以使用的@ImportResource注释来加载XML配置文件。

16. 自动配置

Spring Boot 会根据您添加的jar依赖关系自动配置您的Spring应用程序。例如,如果HSQLDB在您的类路径上,并且您没有手动配置任何数据库连接bean,那么我们将自动配置内存数据库。

您需要通过将@EnableAutoConfiguration或@SpringBootApplication注解添加到您的一个@Configuration类中来选择自动配置。

您应该只添加一个@EnableAutoConfiguration注解。 我们通常建议您将其添加到主@Configuration类中。

16.1逐渐取代自动配置

自动配置是非侵入式的,您可以随时定义自己的配置来替换自动配置。 例如,如果您添加自己的 DataSource bean,则默认的嵌入式数据库支持将会退回。

如果您需要了解当前有哪些自动配置,以及为什么,请使用–debug开关启动应用程序。 这将启用debug日志,并将自动配置日志记录到控制台。

16.2 禁用指定的自动配置

如果您发现正在使用一些不需要的自动配置类,可以使用@EnableAutoConfiguration的exclude属性来禁用它们。

import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;

@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}

如果类不在classpath路径上,则可以使用注释的excludeName属性,并指定全限定名(fully qualified name)。 最后,您还可以通过spring.autoconfigure.exclude属性控制要排除的自动配置类列表。

注解和使用属性(property)定义都可以指定要排除的自动配置类。

17. Spring Beans 和 依赖注入

您可以自由使用任何标准的Spring Framework技术来定义您的bean及其依赖注入关系。 为了简单起见,我们发现使用@ComponentScan搜索bean,结合@Autowired构造函数(constructor)注入效果很好。

如果您按照上述建议(将应用程序类放在根包(root package)中)构建代码,则可以使用
@ComponentScan而不使用任何参数。 所有应用程序组件(@Component,@Service,@Repository,@Controller等)将自动注册为Spring Bean。

以下是一个@Service Bean的例子,我们可以使用构造函数注入获取RiskAssessor bean。

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DatabaseAccountService implements AccountService {

private final RiskAssessor riskAssessor;

@Autowired
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}

// ...

}

如果一个bean 只有一个构造函数,则可以省略@Autowired。

@Service
public class DatabaseAccountService implements AccountService {

private final RiskAssessor riskAssessor;

public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}

// ...

}

注意,如何使用构造函数注入允许将RiskAssessor字段标记为final,表示不能更改。

18. 使用@SpringBootApplication注解

许多Spring Boot开发人员总是使用@Configuration,@EnableAutoConfiguration和@ComponentScan来标注它们的主类。 由于这些注解经常一起使用(特别是如果您遵循之前说的最佳实践),Spring Boot提供了一个方便的@SpringBootApplication注解作为这三个的替代方法。

@SpringBootApplication注解相当于使用@Configuration,@EnableAutoConfiguration和@ComponentScan和他们的默认属性:

package com.example.myproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

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

}

@SpringBootApplication还提供了别名来定制@EnableAutoConfiguration和@ComponentScan的属性。

19. 运行你的应用程序

将应用程序打包成jar并使用嵌入式HTTP服务器的最大优点之一就是可以按照你想用其他任何方式运行应用程序。调试Spring Boot应用程序也很容易; 您不需要任何专门的IDE插件或扩展。

本节仅涵盖基于jar的打包,如果您选择将应用程序打包为war文件,则应参考您的服务器和IDE的文档。

19.1 从IDE运行

您可以从IDE中运行 Spring Boot 应用程序作为一个简单的Java应用程序,但是首先需要导入项目。 导入步骤将根据您的IDE和构建系统而有所不同。 大多数IDE可以直接导入Maven项目,例如Eclipse用户可以从File菜单中选择import…→Existing Maven Projects。

如果您无法将项目直接导入到IDE中,则可以使用构建插件生成IDE元数据。 Maven包括Eclipse和IDEA的插件; Gradle为各种IDE提供插件。

如果您不小心运行了两次Web应用程序,您将看到“Port already in use”中的错误。 使用STS用户可以使用重新启动按钮而不是运行以确保任何现有实例已关闭。

19.2 作为已打包应用程序运行

如果您使用Spring Boot 的 Maven或Gradle插件创建可执行jar,则可以使用java -jar运行应用程序。 例如:

$ java -jar target/myproject-0.0.1-SNAPSHOT.jar

也可以启用远程调试支持运行打包的应用程序。 这允许您将调试器添加到打包的应用程序中:

$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myproject-0.0.1-SNAPSHOT.jar

19.3 使用 Maven 插件

Spring Boot Maven 插件包含一个运行目标(goal ),可用于快速编译和运行应用程序。 应用程序以exploded的形式运行,就像在IDE中一样。

$ mvn spring-boot:run

您可能还需要使用一些有用的操作系统环境变量:

$ export MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128M

19.4 使用Gradle插件

Spring Boot Gradlet插件还包括一个bootRun任务,可用于以exploded 形式运行应用程序。 每当导入spring-boot-gradle-plugin时,都会添加bootRun任务:

$ gradle bootRun

您可能还想使用这个有用的操作系统环境变量:

$ export JAVA_OPTS=-Xmx1024m -XX:MaxPermSize=128M

19.5 热插拔

由于Spring Boot应用程序只是纯Java应用程序,所以JVM热插拔应该是开箱即用的。 JVM热插拔在一定程度上受到可替代的字节码的限制,更完整的解决方案,可以使用 JRebel 或者 Spring Loaded 项目。 spring-boot-devtools模块还支持快速重新启动应用程序。

有关详细信息,请参阅第20章“开发人员工具”部分和热插拔“操作方法”

20. 开发工具

Spring Boot包括一组额外的工具,可以使应用程序开发体验更加愉快。 spring-boot-devtools模块可以包含在任何项目中,以提供额外的开发时功能。 要包含devtools支持,只需将模块依赖关系添加到您的构建中:

Maven:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

Gradle:

dependencies {
compile("org.springframework.boot:spring-boot-devtools")
}

当运行完全打包的应用程序时,开发人员工具将自动禁用。 如果您的应用程序是使用java -jar启动的,或者是使用特殊的类加载器启动,那么它将会被认为是“生产环境的应用程序”。 将开发工具依赖关系标记为可选(optional)是一种最佳做法,可以防止使用项目将devtools传递性地应用于其他模块。 Gradle不支持开箱即用的可选依赖项,因此您可能希望在此期间查看propdeps-plugin

重新打包的jar包默认情况下不包含devtools。 如果要使用某些远程devtools功能,您需要禁用excludeDevtools 构建下的属性以包含devtools。 该属性支持Maven和Gradle插件。

20.1 属性默认值

Spring Boots支持的几个库使用缓存来提高性能。 例如,模板引擎将缓存编译的模板,以避免重复解析模板文件。 此外,Spring MVC可以在返回静态资源时向响应中添加HTTP缓存头。

虽然缓存在生产中非常有益,但它在开发过程中可能会产生反效果,从而阻止您看到刚刚在应用程序中进行的更改。 因此,spring-boot-devtools将默认禁用这些缓存选项。

缓存选项通常由您的application.properties文件中的设置配置。 例如,Thymeleaf提供了spring.thymeleaf.cache属性。 spring-boot-devtools模块不需要手动设置这些属性,而是自动应用更加合理的开发时(development-time)配置。

有关应用的属性的完整列表,请参阅 DevToolsPropertyDefaultsPostProcessor

20.2 自动重启

使用spring-boot-devtools的应用程序将在类路径上的文件发生更改时自动重新启动。 这在IDE中开发时可能是一个有用的功能,因为它为代码更改提供了非常快的反馈循环。 默认情况下,将监视指向文件夹的类路径上的任何条目。 请注意,某些资源(如静态资源和视图模板)不需要重新启动应用程序。

触发重启

当DevTools监视类路径资源时,触发重新启动的唯一方法是更新类路径中的文件时。 导致类路径更新的方式取决于您正在使用的IDE。 在Eclipse中,保存修改的文件将导致类路径被更新并触发重新启动。 在IntelliJ IDEA中,构建项目(Build→Make Project)将具有相同的效果。

只要 forking 被启用,您也可以通过支持的构建插件(即Maven和Gradle)启动应用程序,因为DevTools需要一个单独的应用程序类加载器才能正常运行。Gradle和Maven默认情况下在类路径上检DevTools。

自动重启当与LiveReload一起使用时工作非常好。 详见下文。 如果您使用JRebel,自动重启将被禁用,有利于动态类重新加载。 其他devtools功能仍然可以使用(如LiveReload和属性覆盖)。

DevTools依赖于应用程序上下文的关闭钩子,以在重新启动期间关闭它。 如果禁用了关闭挂钩(SpringApplication.setRegisterShutdownHook(false)),DevTools将无法正常工作。

当判断类路径中的项目是否会在更改时触发重新启动时,DevTools会自动忽略名为spring-boot,spring-boot-devtools,spring-boot-autoconfigure,spring-boot-actuator和spring-boot-start的项目。

重新启动(Restart) vs 重新加载(Reload)

Spring Boot提供的重新启动技术使用两个类加载器。 不会改的类(例如,来自第三方的jar)被加载到基类加载器中。 您正在开发的类被加载到重新启动(restart)类加载器中。 当应用程序重新启动时,重新启动类加载器将被丢弃,并创建一个新的类加载器。 这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为基类加载器已经可以使用。

如果发现重新启动对应用程序不够快,或遇到类加载问题,您可以考虑来自ZeroTurnaround的JRebel等重新加载技术。 这些工作通过在加载类时重写(rewriting)类,使其更适合重新加载。 Spring Loaded提供了另一个选项,但是它在很多框架上不支持,并且不支持商用。

20.2.1 排除资源

在类路径下,某些资源在更改时不一定需要触发重新启动。 例如,Thymeleaf模板可以直接编辑不需重启。
默认情况下,有一些排除项,更改 /META-INF/maven,/META-INF/resources,/resources,/static,/public或/templates中的资源不会触发重新启动,但会触发实时重新加载
如果要自定义这些排除项,可以使用spring.devtools.restart.exclude属性。 例如,要仅排除 /static和 /public,您可以设置:

spring.devtools.restart.exclude=static/**,public/**

如果要保留这些默认值并添加其他排除项,请改用spring.devtools.restart.additional-exclude属性。

20.2.2 监视额外的路径

有时当您对不在类路径中的文件进行更改时,需要重新启动或重新加载应用程序。为此,请使用spring.devtools.restart.additional-paths属性来配置其他路径以监视更改。 您可以使用上述的spring.devtools.restart.exclude属性来控制附加路径下的更改是否会触发完全重新启动或只是实时重新加载

20.2.3 禁用重启

如果不想使用重新启动功能,可以使用spring.devtools.restart.enabled属性来禁用它。 在大多数情况下,您可以在application.properties中设置此项(这仍将初始化重新启动类加载器,但不会监视文件更改)。

例如,如果您需要完全禁用重新启动支持,因为它在一些特定库中不能正常运行,则需要在调用SpringApplication.run(…)之前设置System属性。 例如:

public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}

20.2.4 使用触发文件

如果您使用IDE工具编写代码,更改文件,则您可能希望仅在特定时间触发重新启动。 为此,您可以使用“触发文件”,这是一个特殊文件,当您要实际触发重新启动检查时,必须修改它。 更改文件只会触发检查,只有在Devtools检测到它必须执行某些操作时才会重新启动。 触发文件可以手动更新,也可以通过IDE插件更新。

要使用触发器文件,请使用spring.devtools.restart.trigger-file属性。

您可能希望将spring.devtools.restart.trigger-file设置为全局设置,以使所有项目的行为方式相同。

20.2.5 自定义重新启动类加载器

如上面的 Restart vs Reload 部分所述,重新启动功能是通过使用两个类加载器实现的。 对于大多数应用程序,此方法运行良好,但有时可能会导致类加载问题。

默认情况下,IDE中的任何打开的项目将使用“重新启动”类加载器加载,任何常规.jar文件将使用“base”类加载器加载。 如果您在多模块项目上工作,而不是每个模块都导入到IDE中,则可能需要自定义事件。 为此,您可以创建一个META-INF / spring-devtools.properties文件。

spring-devtools.properties文件可以包含restart.exclude 和 restart.include.prefixed属性。 include元素是应该被拉入“重新启动(restart)”类加载器的项目,排除元素是应该向下推入“基本(base)”类加载器的项目。 属性的值是将应用于类路径的正则表达式模式。

例如:

restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar

所有属性键必须是唯一的。 只要一个属性从restart.include. 或restart.exclude. 开始,将被考虑。

将加载类路径中的所有META-INF/spring-devtools.properties。 您可以在项目中打包文件,或者在项目所使用的库中打包文件。

20.2.6 已知的限制

重新启动功能对于使用标准ObjectInputStream反序列化的对象无效。 如果需要反序列化数据,可能需要使用Spring的ConfigurableObjectInputStream与Thread.currentThread()。getContextClassLoader()组合使用。

不幸的是,几个第三方库在不考虑上下文类加载器的情况下反序列化。 如果您发现这样的问题,您需要向原始作者请求修复。

20.3 LiveReload

spring-boot-devtools模块包括一个嵌入式LiveReload服务器,可以在资源更改时用于触发浏览器刷新。 LiveReload浏览器扩展程序可以从 http://livereload.com 免费获取Chrome,Firefox和Safari的插件。

如果您不想在应用程序运行时启动LiveReload服务器,则可以将spring.devtools.livereload.enabled属性设置为false。

一次只能运行一个LiveReload服务器。 开始应用程序之前,请确保没有其他LiveReload服务器正在运行。 如果从IDE启动多个应用程序,则只有第一个应用程序将支持LiveReload。

20.4 全局设置

您可以通过向 $HOME 文件夹添加名为.spring-boot-devtools.properties的文件来配置全局devtools设置(请注意文件名以“.”开头)。 添加到此文件的任何属性将适用于您的计算机上使用devtools的所有Spring Boot应用程序。 例如,要配置重新启动以始终使用触发器文件,您可以添加以下内容:

~/.spring-boot-devtools.properties.

spring.devtools.reload.trigger-file=.reloadtrigger

20.5远程应用

Spring Boot开发工具不仅限于本地开发。 远程运行应用程序时也可以使用多种功能。 远程支持是可选择的,要使其能够确保重新打包的存档中包含devtools:

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

那么你需要设置一个spring.devtools.remote.secret属性,例如:

spring.devtools.remote.secret=mysecret

在远程应用程序上启用spring-boot-devtools是一种安全隐患。 您不应该在生产部署中启用该支持。

远程devtools支持分为两部分: 有一个接受连接的服务器端和您在IDE中运行的客户端应用程序。 当spring.devtools.remote.secret属性设置时,服务器组件将自动启用。 客户端组件必须手动启动。

20.5.1 运行远程客户端应用程序

远程客户端应用程序旨在从IDE中运行。 您需要使用与要连接的远程项目相同的类路径运行org.springframework.boot.devtools.RemoteSpringApplication。 传递给应用程序的必选参数应该是您要连接到的远程URL。

例如,如果您使用Eclipse或STS,并且有一个名为my-app的项目已部署到Cloud Foundry,则可以执行以下操作:

运行的远程客户端将如下所示:

  .   ____          _                                              __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: 1.5.2.RELEASE

2015-06-10 18:25:06.632 INFO 14938 --- [ main] o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-boot-samples/spring-boot-sample-devtools)
2015-06-10 18:25:06.671 INFO 14938 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043 WARN 14938 --- [ main] o.s.b.d.r.c.RemoteClientConfiguration : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074 INFO 14938 --- [ main] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2015-06-10 18:25:07.130 INFO 14938 --- [ main] o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)

由于远程客户端正在使用与实际应用程序相同的类路径,因此可以直接读取应用程序属性。 这是spring.devtools.remote.secret属性如何读取并传递到服务器进行身份验证。

建议使用https//作为连接协议,以便流量被加密,防止密码被拦截。

如果需要使用代理访问远程应用程序,请配置spring.devtools.remote.proxy.host和spring.devtools.remote.proxy.port属性。

20.5.2 远程更新

远程客户端将以与本地相同的方式监视应用程序类路径的更改。 任何更新的资源将被推送到远程应用程序,并且(如果需要的话)触发重新启动。 如果您正在迭代使用您当地没有的云服务的功能,这可能会非常有用。 通常,远程更新和重新启动比完全重建和部署周期要快得多。

仅在远程客户端运行时才监视文件。 如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。

20.5.3 远程调试隧道

在远程应用程序诊断问题时,Java远程调试非常有用。 不幸的是,当您的应用程序部署在数据中心之外时,并不总是能够进行远程调试。 如果您正在使用基于容器的技术(如Docker),远程调试也可能难以设置。

为了帮助解决这些限制,devtools支持基于HTTP隧道的传输远程调试传输。 远程客户端在端口8000上提供本地服务器,您可以连接远程调试器。 建立连接后,通过HTTP将调试数据发送到远程应用程序。 如果要使用其他端口,可以使用spring.devtools.remote.debug.local-port属性更改。

您需要确保远程应用程序启用远程调试启用。 通常可以通过配置JAVA_OPTS来实现。 例如,使用Cloud Foundry,您可以将以下内容添加到manifest.yml中:

---
env:
JAVA_OPTS: "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n"

请注意,您不需要将 address=NNNN 选项传递给-Xrunjdwp。 如果省略Java将随机选择一个的空闲端口。

通过网络调试远程服务可能很慢,您可能需要在IDE中增加超时时间。 例如,在Eclipse中,您可以从Preferences…中选择Java→Debug ,并将Debugger timeout (ms)更改为更合适的值(大多数情况下,60000可以正常工作)。

当使用IntelliJ IDEA的远程调试隧道时,必须将所有调试断点配置为挂起线程而不是挂起VM。 默认情况下,IntelliJ IDEA中的断点会挂起整个VM,而不是仅挂起触发断点的线程。 这会导致挂起管理远程调试通道的线程等不必要的副作用,导致调试会话冻结。 当使用IntelliJ IDEA的远程调试隧道时,应将所有断点配置为挂起线程而不是VM。 有关详细信息,请参阅IDEA-165769

21. 包装您的应用程序到生产环境

可执行的jar可用于生产部署。 由于它们是相互独立的,它们也非常适合基于云的部署。

对于其他“生产环境准备”功能,如健康,审计和metric REST或JMX端点; 考虑添加spring-boot-actuator。 有关详细信息,请参见第V部分“Spring Boot Actuator:生产环境准备功能”

22. 接下来应该读什么

您现在应该很好地了解如何使用Spring Boot以及您应该遵循的一些最佳做法。 您现在可以深入了解特定的Spring Boot功能,或者您可以跳过这部分,真的阅读Spring Boot的“生产环境准备”方面。

posted @ 2017-12-04 18:21  四川张学友  阅读(994)  评论(0编辑  收藏  举报