SpringBoot参考指南
Part III. 使用SpringBoot(Using Spring Boot)
本节将更详细地介绍如何使用SpringBoot。它涵盖了构建系统、自动配置以及如何运行应用程序等主题。我们还介绍了一些SpringBoot最佳实践。尽管SpringBoot没有什么特别之处(它只是另一个您可以使用的库),但是有一些建议可以让您的开发过程更容易一些。
如果您刚开始使用Spring Boot,那么在进入本部分之前,您可能应该阅读入门指南。
13. 构建系统(Build Systems)
强烈建议您选择一个支持依赖关系管理的构建系统,可以使用它发布到“Maven Central”库。我们建议您选择Maven或Gradle。也可以让SpringBoot与其他构建系统(例如Ant)一起工作,但是它并没有得到很好的支持。
13.1 依赖管理(Dependency Management)
SpringBoot的每个版本都提供了它所支持的依赖项列表。实际上,您不需要为构建配置中的任何依赖项提供版本,因为SpringBoot为您管理这些依赖项。当您升级SpringBoot本身时,这些依赖项也以一致的方式升级。
如果你需要,可以指定配置项版本覆盖SpringBoot的默认模块版本。
依赖列表包含spring所有模块,你也可以使用第三方的库来代替SpringBoot的默认库。这个列表可以作为标准的依赖清单(spring-boot-dependencies
),它可以与Maven和Gradle一起使用。
SpringBoot的每个版本都与Spring框架的一个基本版本相关联。我们强烈建议您不要指定它的版本。
13.2 Maven
Maven用户可以从spring-boot-starter-parent
项目继承,以获得合理的默认值。父项目提供以下功能:
- Java 1.8作为默认编译级别
- 源码采用utf-8编码格式
-
依赖项管理部分,继承自
spring-boot-dependencies
pom,用于管理公共的依赖项的版本。当您在自己的pom中使用这些依赖项时,这种依赖项管理允许您省略这些依赖项的<version>标记。 - 带有
repackage
执行id的repackage
目标。 - 合理的资源过滤。
- 合理的插件配置(exec插件、Git提交ID和shade)。
- 对
application.properties
和application.yml
进行合理的资源筛选,包括特定于概要文件的文件(例如:application-dev.properties
和application-dev.yml
)
注意: 由于application.properties
和application.yml
文件接受Spring风格的占位符(${…}
),所以Maven过滤符号改为使用@..@
占位符。(您可以通过设置Maven属性resource.delimiter
来覆盖它。)
13.2.1 继承 Starter Parent(Inheriting the Starter Parent)
配置你的应用程序继承spring-boot-starter-parent
,如下:
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
您应该只需要在此依赖项上指定Spring引导版本号。如果您导入其他启动程序,您可以安全地省略版本号。
通过该设置,您还可以通过覆盖自己项目中的属性来覆盖单个依赖项。例如,要升级到另一个SpringData发布系列,您需要在pom.xml
中添加以下内容:
<properties>
<spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>
浏览
spring-boot-dependencies
POM查看支持的依赖配置项列表。
13.2.2 不继承父POM使用SpringBoot(Using Spring Boot without the Parent POM)
不是所有的人都希望从继承spring-boot-starter-parent
POM 来使用SpringBoot,您可能需要使用自己的公司标准父类,或者您可能更喜欢显式声明所有Maven配置。
如果您不想使用spring-boot-starter-parent
,可以使用如下配置引入SpringBoot,如下所示:
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
如上所述,前面的示例设置不允许使用属性覆盖单个依赖项。为了达到相同的结果,您需要在项目的dependencyManagement中添加一个条目,然后再添加spring-boot-dependencies条目。例如,要升级到另一个SpringData发布系列,您可以向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>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在前面的示例中,我们指定了一个BOM,但是可以以相同的方式覆盖任何依赖类型。
13.2.3 使用SpringBoot Maven插件(Using the Spring Boot Maven Plugin)
Spring Boot包括一个Maven插件,它可以将项目打包为可执行jar。如果你想使用的话,可以将这个插件添加到你的<plugins>部分,如下面的例子所示:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果使用SpringBoot启动程序的父pom,只需要添加插件。没有必要对其进行配置,除非您想要更改父组件中定义的设置。
13.3 Gradle
要了解如何使用带Gradle的Spring Boot,请参考Spring Boot的Gradle plugin的文档:
13.4 Ant
可以使用Apache Ant+Ivy构建一个SpringBoot项目。spring-boot-antlib“AntLib”模块也可以帮助Ant创建可执行jar。
要声明依赖项,需要声明一个典型的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="2.1.1.RELEASE" />
<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>
如果您不想使用spring-boot-antlib模块,请参阅91.9节“从Ant构建可执行的归档文件,而不使用spring-boot-antlib”“How-to”。
13.5 启动项(Starters)
Starters是一组方便的依赖描述符,您可以在应用程序中包含它们。您可以一站式引入所需的所有Spring和相关技术,而不必自己一个个去引入。例如,如果您希望开始使用Spring和JPA进行数据库访问,那么可以在项目中引入spring-boot-starter-data-jpa
依赖项。
你可以依赖某一组依赖项来快速的启动一个项目,这样可以使用一组一致的、受支持的托管传递依赖项。
名字的由来:
所有正式的`starters`都遵循类似`spring-boot-starter-* `的命名模式,其中* 是一种特殊类型的应用程序。这种命名结构是为了在您需要找到`starter`时提供帮助。许多ide中的Maven集成允许您按名称搜索依赖项。例如,安装了适当的Eclipse或STS插件后,您可以在POM编辑器中按ctrl-space并键入“`spring-boot-starter`”以获得完整的列表。
正如在“创建您自己的启动程序”一节中所描述,第三方启动程序不应该从spring-boot作为命名前缀,因为它是为官方Spring Starters保留的。相反,第三方启动程序通常以项目名称开始。例如,一个名为`thirdpartyproject`的第三方启动项目通常被命名为`thirdpartyproject-spring-boot-starter`。
以下应用程序启动程序是由SpringBoot在org.springframework下提供的:
** Table 13.1. Spring Boot application starters **
名称 | 描述 | POM |
---|---|---|
spring-boot-starter |
核心启动器,包括自动配置支持、日志记录和YAML | pom |
spring-boot-starter-activemq |
使用Apache ActiveMQ启动JMS消息传递 | pom |
spring-boot-starter-amqp |
用于使用Spring AMQP和Rabbit MQ | pom |
spring-boot-starter-aop |
用于使用Spring AOP和AspectJ进行面向方面的编程 | pom |
spring-boot-starter-artemis |
对于使用Apache Artemis的JMS消息传递 | pom |
spring-boot-starter-batch |
使用批处理 | pom |
spring-boot-starter-cache |
用于使用Spring Framework的缓存支持 | pom |
spring-boot-starter-cloud-connectors |
用于使用Spring Cloud连接器,它简化了与Cloud Foundry和Heroku等云平台服务的连接 | pom |
spring-boot-starter-data-cassandra |
用于使用Cassandra分布式数据库和Spring Data Cassandra | pom |
spring-boot-starter-data-cassandra-reactive |
用于使用Cassandra分布式数据库和Spring Data Cassandra Reactive | pom |
spring-boot-starter-data-couchbase |
用于使用Couchbase面向文档的数据库和Spring Data Couchbase | pom |
spring-boot-starter-data-couchbase-reactive |
用于使用Couchbase面向文档的数据库和Spring Data Cassandra Reactive | pom |
spring-boot-starter-data-elasticsearch |
用于使用elasticsearch搜索、分析引擎和Spring Data Elasticsearch | pom |
spring-boot-starter-data-couchbase-reactive |
用于使用Couchbase面向文档的数据库和Spring数据的Couchbase响应 | pom |
spring-boot-starter-data-elasticsearch |
用于使用弹性搜索,搜索和分析引擎和Spring数据弹性搜索 | pom |
spring-boot-starter-data-jdbc |
用于使用SpringDataJDBC | pom |
spring-boot-starter-data-jpa |
用于在Hibernate中使用SpringDataJPA | pom |
spring-boot-starter-data-ldap |
用于使用 Spring Data LDAP | pom |
spring-boot-starter-data-mongodb |
用于使用MongoDB面向文档的数据库和Spring Data MongoDB | pom |
spring-boot-starter-data-mongodb-reactive |
用于使用MongoDB面向文档的数据库和Spring Data MongoDB Reactive | pom |
spring-boot-starter-data-neo4j |
用于使用Neo4j图数据库和Spring Data Neo4j | pom |
spring-boot-starter-data-redis |
用于将Redis键值数据存储与Spring Data Redis 和Lettuce 客户端 | pom |
spring-boot-starter-data-redis-reactive |
用于将Redis键值数据存储与Spring Data Redis Reactive和 Lettuce 客户端 | pom |
spring-boot-starter-data-rest |
用于使用SpringDataREST在REST之上发布Spring数据存储库 | pom |
spring-boot-starter-data-solr |
用于使用带有SpringDataSolr的ApacheSolr搜索平台 | pom |
spring-boot-starter-freemarker |
用于使用FreeMarker视图构建MVCweb应用程序 | pom |
spring-boot-starter-groovy-templates |
用于使用Groovy模板视图构建MVCweb应用程序 | pom |
spring-boot-starter-hateoas |
用于使用SpringMVC和SpringHATEOAS构建基于超媒体的RESTfulweb应用程序 | pom |
spring-boot-starter-integration |
用于使用SpringIntegration | pom |
spring-boot-starter-jdbc |
用于与HikariCP连接池一起使用JDBC | pom |
spring-boot-starter-jersey |
用于使用JAX-RS和Jersey构建RESTfulweb应用程序。替代spring-boot-starter-web的方法 | pom |
spring-boot-starter-jooq |
用于使用jOOQ访问SQL数据库。spring-boot-start-data-jpa或spring-boot-start-jdbc的替代方案 | pom |
spring-boot-starter-json |
用于读取和写入json | pom |
spring-boot-starter-jta-atomikos |
对于使用atomiko的JTA事务 | pom |
spring-boot-starter-jta-bitronix |
对于使用Bitronix的JTA事务 | pom |
spring-boot-starter-mail |
用于使用JavaMail和SpringFramework的电子邮件发送支持 | pom |
spring-boot-starter-mustache |
用于使用Mustache视图构建web应用程序 | pom |
spring-boot-starter-oauth2-client |
用于使用SpringSecurity的OAuth2/OpenIDConnect客户端特性 | pom |
spring-boot-starter-oauth2-resource-server |
用于使用SpringSecurity的OAuth2资源服务器特性 | pom |
spring-boot-starter-quartz |
用于使用石英调度器 | pom |
spring-boot-starter-security |
用于使用SpringSecurity | pom |
spring-boot-starter-test |
用于测试带有JUnit、Hamcrest和Mockito等库的Spring引导应用程序 | pom |
spring-boot-starter-thymeleaf |
用于使用Thymeleaf视图构建MVCweb应用程序 | pom |
spring-boot-starter-validation |
用于在Hibernate验证器中使用JavaBean验证 | pom |
spring-boot-starter-web |
用于使用SpringMVC构建web(包括RESTful)应用程序。使用Tomcat作为默认的嵌入式容器 | pom |
spring-boot-starter-web-services |
用于使用SpringWeb服务 | pom |
spring-boot-starter-webflux |
用于使用Spring框架的反应性Web支持构建WebFlux应用程序 | pom |
spring-boot-starter-websocket |
用于使用SpringFramework的WebSocket支持构建WebSocket应用程序 | pom |
除了应用程序启动器之外,还可以使用以下启动器添加生产就绪特性:
** Table 13.2. Spring Boot production starters **
名称 | 描述 | POM |
---|---|---|
spring-boot-starter-actuator |
用于使用SpringBoot的执行器,它提供了生产就绪的特性,帮助您监视和管理应用程序 | pom |
最后,Spring Boot还包括以下启动程序,如果您希望排除或交换特定的技术方面,可以使用这些启动程序:
** Table 13.3. Spring Boot technical starters **
名称 | 描述 | POM |
---|---|---|
spring-boot-starter-jetty |
用于使用Jetty作为嵌入式servlet容器。一个替代spring-boot-starter-tomcat 的方法 |
pom |
spring-boot-starter-log4j2 |
用于使用Log4j2进行日志记录。一个替代spring-boot-starter-logging 的方法 |
pom |
spring-boot-starter-logging |
用于使用Logback进行日志记录。默认的日志起动器 | pom |
spring-boot-starter-reactor-netty |
用于将Reactor Netty用作嵌入式响应式HTTP服务器。 | pom |
spring-boot-starter-tomcat |
用于使用Tomcat作为嵌入式servlet容器。spring-boot-starter-web 使用的缺省servlet容器启动器 |
pom |
spring-boot-starter-undertow |
用于使用Undertow作为嵌入式servlet容器。一个替代spring-boot-starter-tomcat 的方法 |
pom |
有关社区提供的其他启动器的列表,请参阅GitHub上
spring-boot-starters
文件。
14. 构建你的代码(Structuring Your Code)
SpringBoot不需要任何特定的代码布局就可以工作。然而,有一些最佳实践可以为你提供帮助。
14.1 使用“默认”包(Using the “default” Package)
当一个类没有包声明时,它被认为是“默认包”。通常不鼓励使用“默认包”,应该避免使用。它可能会给使用@ComponentScan
、@EntityScan
或@SpringBootApplication
注释的SpringBoot应用程序带来问题。
我们建议您遵循Java推荐的反向域名进行包命名(例如
com.example.project
)。
14.2 定位主应用程序类(Locating the Main Application Class)
我们建议您将主应用程序类放在根包中,而不是其他类中。@SpringBootApplication
注释通常放在您的主类上,它隐式地为某些项定义了一个基本的“搜索包”。例如,如果您正在编写JPA应用程序,那么@SpringBootApplication
注释类的包将用于搜索@Entity
项。
如果您不想使用
@SpringBootApplication
,那么它导入的@EnableAutoConfiguration
和@ComponentScan
将起到相同的作用,因此您也可以使用这两个注解。
下面的清单显示了一个典型的布局:
com
+- example
+- myapplication
+- Application.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
Application.java
文件将声明main
方法,以及基本的@SpringBootApplication
,如下所示:
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
15. 配置类(Configuration Classes)
SpringBoot支持基于java的配置。虽然可以将SpringApplication与XML源一起使用,但是我们通常建议你使用单个@Configuration类。
在Internet上已经发布了许多使用XML配置的Spring配置示例。如果可能,请始终尝试使用等效的基于java的配置。你可以通过搜索Enable* 来进行查看和修改。
15.1 导入其他配置类(Importing Additional Configuration Classes)
您不需要将所有@Configuration放到一个类中。@Import
注释可以用来导入其他配置类。或者,您可以使用@ComponentScan
自动获取所有Spring组件,包括@Configuration
类。
15.2导入XML配置(Importing XML Configuration)
如果您坚决要使用基于XML的配置,我们建议您仍然从@Configuration
类开始。然后可以使用@ImportResource
注释加载XML配置文件。
16. 自动化配置(Auto-configuration)
SpringBoot自动化配置试图根据你添加的jar依赖关系自动配置Spring应用程序。例如,如果HSQLDB
在您的类路径中,并且您没有手动为它配置任何数据库连接Bean,那么SpringBoot将自动配置内存中的数据库。
您需要通过向@Configuration
类添加@EnableAutoConfiguration
或@SpringBootApplication
注释来开启自动配置。
您应该只添加
@SpringBootApplication
或EnableAutoConfiguration
中的一个注释。我们通常建议您只向@Configuration
类添加其中一个注解。
16.1 逐渐取代自动配置(Gradually Replacing Auto-configuration)
自动化配置是非侵入性的。在任何时候,您都可以定义自己的配置来替换自动配置的特定部分。例如,如果您添加自己的DataSource
Bean,默认配置将会被覆盖。
如果您需要了解当前正在应用什么自动配置,以及原因,请使用--debug
开关启动应用程序。这样做可以为选择的核心日志记录器创建调试日志,并将条件报告记录到控制台。
16.2 禁用特定的自动配置类(Disabling Specific Auto-configuration Classes)
如果您发现不希望应用的特定自动配置类,可以使用@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
属性并指定完全限定名。最后,您还可以使用spring.autoconfigure.exclude
来控制要排除的自动配置类的列表来排除属性。
您可以在注释级别和通过使用属性定义排除。
17. Spring Bean 和依赖注入(Spring Beans and Dependency Injection)
您可以自由地使用任何标准Spring框架技术来定义bean及其注入的依赖项。为了简单起见,我们发现使用@ComponentScan
(查找bean)和使用@Autowired
(执行构造函数注入)工作得很好。
如果您按照上面的建议构建代码(将应用程序类定位到根包中),您可以添加@ComponentScan
,而不需要任何参数。您的所有应用程序组件(@Component
、@Service
、@Repository
、@Controller
等)都自动被注册为SpringBean。
下面的例子显示了一个@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注解* (Using the @SpringBootApplication Annotation)
许多SpringBoot开发人员喜欢他们的应用程序使用自动配置、组件扫描,并能够在“应用程序类”上定义额外的配置。可以使用一个@SpringBootApplication注释来启用这三个特性,即:
-
@EnableAutoConfiguration
: 启用SpringBoot的自动配置机制 -
@ComponentScan
: 在应用程序所在的包上启用@Component
扫描(请参阅最佳实践)
-@Configuration
: 允许在上下文中注册额外的bean或导入其他配置类
@SpringBootApplication注释等价于使用带有默认属性的@Configuration、@EnableAutoConfiguration和@ComponentScan,如下例所示:
package com.example.myapplication;
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的属性。
这些特性都不是必须的,您可以选择用它支持的任何特性替换这个注释。例如,您可能不希望在应用程序中使用组件扫描:
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@EnableAutoConfiguration
@Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
在本例中,应用程序与任何其他SpringBoot应用程序一样,只是@component
-annotation类不会自动检测到,而且用户定义的bean被显式导入(请参考@Import
)。
19. 运行你的应用(Running Your Application)
将应用程序打包为jar并使用嵌入式HTTP服务器的最大优点之一是,可以像运行其他应用程序一样运行应用程序。调试SpringBoot应用程序也很容易。您不需要任何特殊的IDE插件或扩展。
本节只讨论基于jar的打包。如果选择将应用程序打包为war文件,则应该参考服务器和IDE文档。
19.1 使用IDE运行应用程序
您可以从IDE作为一个简单的Java应用程序运行SpringBoot应用程序。然而,您首先需要导入您的项目。导入步骤取决于IDE和构建系统。大多数ide可以直接导入Maven项目。
如果不能直接将项目导入IDE,则可以使用构建插件生成IDE元数据。Maven包括Eclipse和IDEA的插件。Gradle提供了各种ide的插件。
如果您不小心运行了两次web应用程序,您会看到一个“已经在使用中的端口”错误。STS用户可以使用Relaunch按钮而不是Run按钮来确保关闭之前的实例。
19.2 运行打包好的应用(Running as a Packaged Application)
如果使用Spring Boot Maven或Gradle插件创建可执行jar,可以使用java -jar
运行应用程序,如下例所示:
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
还可以运行启用远程调试支持的打包应用程序。这样做可以将调试器附加到打包的应用程序上,如下面的示例所示:
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myapplication-0.0.1-SNAPSHOT.jar
19.3 使用Maven插件运行应用(Using the Maven Plugin)
Spring Boot Maven插件包含一个RUN
目标,可用于快速编译和运行应用程序。应用程序以分解的形式运行,就像在IDE中那样。下面的例子显示了一个典型的Maven命令来运行一个SpringBoot应用程序:
$ mvn spring-boot:run
您可能还希望使用MAVEN_OPTS
操作系统环境变量,如下面的示例所示:
$ export MAVEN_OPTS=-Xmx1024m
19.4 使用gradle插件(Using the Gradle Plugin)
Spring Boot Gradle插件还包含一个bootRun
任务,可以使用它以分解的形式运行应用程序。每当您应用org.springframework.boot
和java
插件时,都会添加bootRun
任务,如下面的示例所示:
$ gradle bootRun
您可能还想使用JAVA_OPTS操作系统环境变量,如下例所示:
$ export JAVA_OPTS=-Xmx1024m
19.5 热插拔(Hot Swapping)
由于SpringBoot应用程序只是普通的Java应用程序,所以JVM热交换应该是开箱即用的。JVM热交换在某种程度上受到它可以替换的字节码的限制。对于更完整的解决方案,可以使用JRebel。
spring-boot-devtools
模块还支持快速重启应用程序。有关详细信息,请参阅本章后面的第20章Developer Tools部分和热交换“是如何实现的”。
20. 开发者工具(Developer Tools)
Spring Boot包含一组额外的工具,可以使应用程序开发体验更加愉快。spring-boot-devtools模块可以包含在任何项目中,以提供额外的开发时特性。要包含devtools支持,请将模块依赖关系添加到构建中,如下Maven和Gradle的清单所示:
Maven:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Gradle:
configurations {
developmentOnly
runtimeClasspath {
extendsFrom developmentOnly
}
}
dependencies {
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
在运行完全打包的应用程序时,开发人员工具将自动禁用。如果您的应用程序是从
java -jar
启动的,或者是从一个特殊的类加载器启动的,那么它就被认为是一个“生产应用程序”。在Maven中将依赖项标记为可选的,或者在Gradle中使用自定义的developmentOnly
配置(如上所示)是一种最佳实践,它可以防止devtools被临时应用到依赖您的项目的其他项目。
重新打包的归档文件默认情况下不包含devtools。如果您想使用某个远程devtools特性,您需要禁用
excludeDevtools
构建属性来包含它。Maven和Gradle插件都支持该属性。
20.1 属性默认值(Property Defaults)
SpringBoot支持的一些库使用缓存来提高性能。例如,模板引擎缓存已编译的模板,以避免重复解析模板文件。此外,SpringMVC还可以在提供静态资源时向响应添加HTTP缓存标头。
虽然缓存在生产中非常有用,但在开发过程中可能会适得其反,使您无法看到刚刚在应用程序中所做的更改。因此,spring-boot-devtools
在默认情况下禁用缓存选项。
缓存选项通常由application.properties
文件中的设置配置。例如,Thymeleaf提供了spring.thymeleaf.cache
属性。spring-boot-devtools
模块不需要手动设置这些属性,而是自动应用合理的开发时配置。
由于在开发SpringMVC和SpringWebFlux应用程序时需要更多关于web
请求的信息,开发人员工具将为web日志组启用DEBUG
日志。这将提供关于传入请求的信息、正在处理它的处理程序、响应结果等。如果希望记录所有请求详细信息(包括可能敏感的信息),可以打开spring.http.log-request-details
配置项。
如果不希望应用属性默认值,可以在
application.properties
中将spring.devtools.add-properties
设置为false。
有关devtools应用的属性的完整列表,请参见DevToolsPropertyDefaultsPostProcessor。
20.2 自动重启(Automatic Restart)
当classpath
的文件发生变化是,使用spring-boot-devtools
的应用程序将自动重启。当在IDE中工作时,这可能是一个有用的特性,因为它为代码更改提供了一个非常快速的反馈机制。默认情况下,classpath
中指向文件夹的任何条目都将被监视。请注意,某些资源,例如静态资产和视图模板更改时,不需要重启应用程序。
Triggering a restart
当DevTools监视类路径资源时,触发重启的惟一方法是更新类路径。更新类路径的方式取决于所使用的IDE。在Eclipse中,保存修改后的文件会更新类路径并触发重启。在IntelliJ IDEA中,构建项目(Build -> Build project)具有相同的效果。
只要启用了分叉,您还可以通过使用支持的构建插件(Maven和Gradle)启动应用程序,因为DevTools需要一个独立的应用程序类加载器才能正常运行。默认情况下,Gradle和Maven在检测类路径上的DevTools时就会这样做。
当与
LiveReload
一起使用时,自动重启非常有效。有关详细信息,请参阅LiveReload
部分。如果您使用JRebel
,自动重启将被禁用,以支持动态类重载。devtools的其他特性(如页面加载和属性重写)仍然可以使用。
DevTools依赖于应用程序上下文的
shutdown hook
在重新启动时关闭它。如果禁用了shutdown hook
,则无法正常工作(SpringApplication.setRegisterShutdownHook(false)
)
当决定类路径上的条目在发生更改时是否应该触发重新启动时,DevTools会自动忽略名为
spring-boot
,spring-boot-devtools
,spring-boot-autoconfigure
,spring-boot-actuator
,spring-boot-starter
的项目
DevTools需要定制
ApplicationContext
使用的ResourceLoader
。如果您的应用程序已经提供了一个,它将被包装。不支持在ApplicationContext
上直接重写getResource
方法。
重启 VS 重载
SpringBoot通过使用两个类加载器来提供的重启技术。不更改的类(例如来自第三方jar的类)被加载到基类加载器中,正在开发的类被加载到重启类加载器中。当应用程序重新启动时,重新启动类加载器将被丢弃,并创建一个新的类加载器。这种方法意味着应用程序重启通常比“冷启动”快得多,因为基类加载器已经可用并已填充。
如果您发现重新启动对于您的应用程序来说不够快,或者您遇到了类加载问题,您可以考虑重新加载技术,例如JRebel from ZeroTurnaround。通过在加载类时重写它们,使它们更易于重新加载。
20.2.1 记录条件评估的变化(Logging changes in condition evaluation)
默认情况下,每次应用程序重启时,都会记录一个显示条件评估增量的报告。该报告显示在进行更改(如添加或删除bean和设置配置属性)时对应用程序自动配置的更改。
若要禁用报告的日志记录,请设置以下属性:
spring.devtools.restart.log-condition-evaluation-delta=false
20.2.2 排除资源(Excluding Resources)
某些资源在更改时不一定需要重新启动。例如,可以就地编辑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.3 监控额外的路径(Watching Additional Paths)
您可能希望在对不在类路径上的文件进行更改时重新启动或重新加载应用程序。为此,请使用spring.devtools.restart.additional-paths
属性配置其他路径以监视更改,你可以使用前面描述的spring.devtools.restart.exclude
属性来控制附加路径下的更改是触发完全重启还是实时重新加载。
20.2.4 禁用重启(Disabling Restart)
如果您不想使用restart特性,可以使用spring.devtools.restart.enabled
属性禁用它。在大多数情况下,您可以在您的application.properties
中设置此属性(这样做仍然会初始化restart classloader,但它不会监视文件的更改)。
如果您需要完全禁用重启支持(例如,因为它不能与特定的库一起工作),您需要在调用SpringApplication.run(…)
之前将spring.devtools.restart.enabled
系统属性设置为false
,如下例所示:
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}
20.2.5 使用触发器文件(Using a Trigger File)
如果您使用的IDE持续编译更改的文件,您可能更喜欢只在特定时间触发重启。为此,您可以使用“触发器文件”,这是一个特殊的文件,当您希望实际触发重启检查时,必须修改它。更改文件只会触发检查,并且只有在Devtools检测到它必须执行某些操作时才会重新启动。触发器文件可以手动更新,也可以使用IDE插件更新。
若要使用触发器文件,请将spring.devtools.restart.trigger-file
属性设置为触发器文件的路径。
您可能希望将
spring.devtools.restart.trigger-file
设置为全局设置,以便所有项目都以相同的方式运行。
20.2.6 Customizing the Restart Classloader
正如前面在Restart vs Reload一节中描述的,重启功能是通过使用两个类加载器实现的。对于大多数应用程序,这种方法工作得很好。然而,它有时会导致类加载问题。
默认情况下,IDE中任何打开的项目都是用“restart”类加载器加载的,任何常规.jar
文件都是用“base”类加载器加载的。如果您在一个多模块项目上工作,并且不是每个模块都被导入到IDE中,那么您可能需要定制一些东西。为此,您可以创建一个META-INF/spring-devtools.properties
文件。
spring-devtools.properties
文件可以包含以restart.exclude
和restart.include
为前缀的属性:include
元素是应该拉到“restart”类加载器中的项,而exclude
元素是应该下推到“base”类加载器中的项。属性的值是应用于类路径的regex模式,如下面的示例所示:
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.7 已知的限制(Known Limitations)
对于使用标准ObjectInputStream
反序列化的对象,重新启动功能不能很好地工作。如果需要反序列化数据,可能需要将Spring的ConfigurableObjectInputStream
与Thread.currentThread().getcontextclassloader()
结合使用。
不幸的是,一些第三方库在不考虑上下文类加载器的情况下反序列化。如果发现这样的问题,需要向原始作者请求修复。
20.3 LiveReload
spring-boot-devtools
模块包括一个嵌入式的LiveReload服务器,可以在资源更改时触发浏览器刷新。可以从livereload.com免费获得Chrome、Firefox和Safari浏览器扩展。
如果您不想在应用程序运行时启动LiveReload服务器,可以将spring.devtools.livereload.enabled
属性设置为false
。
一次只能运行一个LiveReload服务器。在启动应用程序之前,确保没有其他的liverload服务器在运行。如果从IDE启动多个应用程序,则只有第一个应用程序支持LiveReload。
20.4 全局设置(Global Settings)
您可以通过向$HOME
文件夹中添加一个名为.spring-boot-devtools.properties
的文件来配置全局devtools设置(注意文件名以“.”开头)。添加到该文件中的任何属性都适用于机器上使用devtools的所有SpringBoot应用程序。例如,要将restart配置为始终使用触发器文件,需要添加以下属性:
** ~/.spring-boot-devtools.properties **
spring.devtools.reload.trigger-file=.reloadtrigger
在.spring-boot-devtools.properties中激活的概要文件不会影响特定于概要文件的配置文件的加载。
20.5 Remote Applications
Spring Boot developer工具并不局限于本地开发。您还可以在远程运行应用程序时使用一些特性。远程支持是可选的。要启用它,您需要确保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 Running the Remote Client Applica
tion
远程客户端应用程序被设计为在IDE中运行。您需要使用与所连接的远程项目相同的类路径运行org.springframe .boot.devtools. remotespringapplication
。应用程序唯一需要的参数是它连接到的远程URL。
例如,如果您使用Eclipse或STS,有一个名为my-app
的项目,并且已经将其部署到Cloud Foundry,那么您将执行以下操作:
- 从
Run
菜单中选择Run Configurations…
- 创建一个新的
Java Application
“启动配置” - 访问
my-app
项目。 - 使用
org.springframework.boot.devtools.RemoteSpringApplication
作为主类 - 添加
https://myapp.cfapps.io
到Program arguments
(或任何你的远程URL)。
正在运行的远程客户机可能类似于以下清单:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: 2.1.1.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 Remote Update
远程客户端以与本地重启相同的方式监视应用程序类路径的更改。任何更新的资源都会被推送到远程应用程序,并且(如果需要的话)会触发重新启动。如果您在使用本地没有的云服务的特性上进行迭代,那么这将非常有用。通常,远程更新和重启要比完整的重新构建和部署周期快得多。
只有在远程客户机运行时才会监视文件。如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。
21. 为生产环境打包应用程序(Packaging Your Application for Production)
可执行jar可以用于生产部署。由于它们是自包含的,所以非常适合基于云的部署。
对于额外的“生产就绪”特性,例如健康、审计和度量REST或JMX端点,考虑添加spring-boot-actuator。有关详细信息,请参见第五部分“Spring Boot Actuator:产品化特性”。
22. 接下的内容(What to Read Next)
现在您应该了解了如何使用SpringBoot以及应该遵循的一些最佳实践。现在,您可以继续深入了解具体的SpringBoot特性,或者跳过前面的内容,阅读有关SpringBoot的“产品就绪”方面的内容。
网友评论