译者注: 本文翻译自Spring Boot 1.4.2.RELEASE 官方参考指南,译者第一次尝试翻译技术文档,如有不当之处还请诸君多多斧正,谢谢!
另:由于翻译工作尚未全部完成,目前译文中的链接均指向原英文文档;后续全部翻译工作完成后将统一替换为译文链接地址。
本节将更加详细地介绍如何使用Spring Boot,包括诸如构建系统、自动配置以及如何运行应用程序等主题,还将介绍一些Spring Boot的最佳实践。虽然Spring Boot并没有什么特异之处(它只是可供选择的另一个库),但仍将使开发过程更为容易。
如果您刚开始接触Spring Boot,在阅读本节前,您可能最好阅读入门指南。
笔者强烈建议您选用一个支持依赖管理(dependency management)的构建系统,以便管理Maven中央仓库中的artifact。笔者建议您选择Maven或者Gradle。通过其他构建系统(如Ant)也能够获得Spring Boot,但对于他们的支持可能不是非常完善。
Spring Boot的每个发布版本都将提供一个所支持依赖的策略表(curated list)。 用户在使用的过程用户无需配置依赖的版本,Spring Boot将完场该工作。当Spring Boot升级时,这些依赖关系也将相应地进行升级。
注
必要的情况下,用户可以指定所需的版本来替代Spring Boot的建议版本。
策略表中包含了Spring Boot可能用到的所有Spring模块和一些第三方库。这份列表可以作为一个标准的材料清单( Bills of Materials)(spring-boot-dependencied
)或者Maven和Gradle的专用附加支持。
警告
Spring Boot的每一个发布版本均与一个Spring框架的基础版本相关联,笔者强烈建议用户不要自行指定这个版本。
Maven用户可以继承spring-boot-starter-parent
项目从而获得合理的默认值。父项目提供以下特性:
spring-boot-dependencies
Pom的、使用户得以省略普通依赖的
标签的依赖管理节点;application.properties
、application.yml
资源的合理过滤(如application-foo.properties
和application-foo.yml
)。 关于最后一点:因为默认的配置文件使用Spring风格的占位符($ {…}
),而Maven过滤器改为使用@..@
占位符(可以通过编辑Maven的resource.delimiter
属性进行修改)。
只需配置parent
节点便可以继承自spring-boot-starter-parent
:
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>1.4.2.RELEASEversion>
parent>
注
只需指定Spring Boot的版本号,之后添加其他启动器时可以安全地省略版本号。
在此基础上,还可以通过修改当前项目的属性的方式来指定特定的依赖版本。例如,升级Spring Data到另一个发布版本系列,需要如下修改pom.xml
文件。
<properties>
<spring-data-releasetrain.version>Fowler-SR2spring-data-releasetrain.version>
properties>
提示
查看spring-boot-dependencies
pom可以看到支持属性的列表。
并非所有用户都愿意继承自spring-boot-starter-parent
POM。可能用户需要继承自企业内部的标准父POM,也可能用户希望能够显示的声明所有的Maven配置。
如果不想使用spring-boot-starter-parent
,通过使用scope=import
依赖,用户仍然可以享受依赖管理(不包括插件管理)的便利:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>1.4.2.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
< /dependencyManagement>
上面这种属性设置并不能修改特定的依赖。如果想要达到相同的效果,需要在应用dependencyManagement
节点中、spring-boot-dependencies
块之前加入新的块。例如,将Spring Data升级到另一个发布版本系列,需要在pom.xml
中加入以下内容:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-releasetrainartifactId>
<version>Fowler-SR2version>
<scope>importscope>
<type>pomtype>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>1.4.2.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
注
在上面的例子中,笔者指定一个BOM,但任何依赖均可以通过这种方式修改。
spring-boot-starter-parent
会比较保守地适配Java的兼容性。笔者推荐用户使用最新的Java版本,需要添加java.version
属性:
<properties>
<java.version>1.8java.version>
properties>
Spring Boot提供了一个可以将工程打包为可执行Jar包的Maven插件。使用时,只需将该插件加入到
一节即可:
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
注
如果使用了Spring Boot的父启动器POM,只需要添加该插件即可,除非希望修改父POM的默认设置,否则无需任何配置。
用户可以在Grad的dependencies
一节直接引入”启动器“。与Maven不同,没有可供共享配置的”超级父节点“。
apply plugin: 'java'
repositories {
jcenter()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.4.2.RELEASE")
}
同样,spring-boot-gradle-plugin
用以创建可以直接运行源码的Jar文件。同时,它还提供了依赖管理的能力,使得在所有Spring功能中,允许省略Spring Boot管理依赖的版本信息。
buildscript {
repositories {
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.2.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
repositories {
jcenter()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
也可以使用Apache Ant和Ivy创建Spring Boot应用程序。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="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>
提示
如果不想使用spring-boot-antlib
模块,请参见80.10 Ant不使用spring-boot-antlib创建可执行文件一节。
启动(starter)是一组表述依赖的符号,以简化用户操作。它为用户提供了Spring以及相关技术的一站式服务(one-stop-shop),使用户无需检索示例代码、复制粘贴大量的依赖描述符号。例如,用户希望开始使用Spring和JPA来管理数据库访问,只需要在项目中加入spring-boot-starter-data-jpa
就可以了。
启动器包含了创建和快速启动程序所需的大量依赖,以及与之相关的、一致的依赖的集合。
名字里的学问
所有官方启动器都遵循一个类似的命名模式spring-boot-starter-*
,其中*
是一个特定类型的应用程序。这种命名结构便于在用户需要查找某个启动器时有所帮助。许多IDE集成的Maven支持用户通过名称检索依赖。例如,在有些Eclipse或STS插件中,用户可以简单的在POM编辑器按Ctrl+空格键
,并输入“spring-boot-starter”便能获得一个完整的列表。
当创建自己的启动器时,第三方启动器的命名不应该以spring-boot
开头,以免与Spring Boot官方的artifact混淆。例如acme
的第三方启动器通常命名为acme-spring-boot-starter
。
以下是Spring Boot提供的、org.springframework.boot
组下的应用程序启动器列表:
表13.1 Spring Boot应用启动器
名称 | 描述 | Pom |
---|---|---|
spring-boot-starter |
Spring Boot的核心启动器,包含了自动配置、日志和YAML。 | Pom |
spring-boot-starter-web |
基于Spring MVC,创建包括RESTFul和应用程序在内的网络服务的启动器。以Tomcat作为默认的嵌入式容器。 | Pom |
spring-boot-starter-jersey |
使用JAX-RS和Jersey构建RESTful网络应用的启动器。是spring-boot-starter-web 的替代方案。 |
Pom |
spring-boot-starter-web-services |
使用Spring Web Services的启动器 | Pom |
spring-boot-starter-ws |
使用Spring Web Services的启动器。 Deprecated as of 1.4 in favor of spring-boot-starter-web-services 【译者注:翻不出,似乎是说在1.4版本的Spring Boot中被另一个取代了。】 |
Pom |
spring-boot-starter-websocket |
使用Spring框架的WebSocket服务构建WebSocket应用的启动器。 | Pom |
spring-boot-starter-hateoas |
基于Spring MVC和Spring HATEOAS实现基于超媒体的RESTful网络应用的启动器。 | Pom |
spring-boot-starter-thymeleaf |
使用Thymeleaf视图构建MVC网站应用的启动器。 | Pom |
spring-boot-starter-groovy-templates |
使用Groovy模板视图构建MVC网站应用的启动器。 | Pom |
spring-boot-starter-freemarker |
使用FreeMarker视图构建MVC网站应用的启动器。 | Pom |
spring-boot-starter-mustache |
使用Mustache视图构建MVC网站应用的启动器。 | Pom |
spring-boot-starter-velocity |
使用Velocity视图构建MVC网站应用的启动器。1.4版本后弃用 | Pom |
spring-boot-starter-jdbc |
基于Tomcat JDBC连接池实现JDBC的启动器。 | Pom |
spring-boot-starter-data-jpa |
使用基于Hibernate的Spring Data JPA的启动器。 | Pom |
spring-boot-starter-jooq |
使用jOOQ访问SQL数据库的启动器。spring-boot-starter-data-jpa 和spring-boot-starter-jdbc 的替代方案。 |
Pom |
spring-boot-starter-data-couchbase |
使用面向文档的数据库Couchbase和Spring Data Couchbase的启动器。 | Pom |
spring-boot-starter-data-mongodb |
使用面向文档数据库MongoDB和Spring Data MongoDB的启动器。 | Pom |
spring-boot-starter-data-redis |
使用键值数据存储Redis、Spring Data Redis和Jedis客户端的启动器。 | Pom |
spring-boot-starter-redis |
使用键值数据存储Redis、Spring Data Redis和Jedis客户端的启动器。Deprecated as of 1.4 in favor of spring-boot-starter-data-redis |
Pom |
spring-boot-starter-data-gemfire |
使用分布式数据存储GemFire和Spring Data Gemfire的启动器。 | Pom |
spring-boot-starter-data-cassandra |
使用分布式数据库Cassandra和Spring Data Cassandra的启动器。 | Pom |
spring-boot-starter-data-neo4j |
使用图形数据库Neo4jSpring Data Neo4j的启动器。 | Pom |
spring-boot-starter-data-elasticsearch |
使用Spring Data Elasticsearch和数据搜索和分析引擎Elasticsearch的启动器。 | Pom |
spring-boot-starter-data-solr |
基于Spring Data Solr使用Apache Solr搜素平台的启动器。 | Pom |
spring-boot-starter-data-rest |
使用Spring Data REST将Spring Data仓库以REST方式暴露出去的启动器。 | Pom |
spring-boot-starter-activemq |
使用Apache ActiveMQ实现JMS消息通讯的启动器。 | Pom |
spring-boot-starter-artemis |
使用Apache Artemis实现JMS消息通讯的启动器。 | Pom |
spring-boot-starter-hornetq |
使用HornetQ实现JMS消息通讯的启动器。Deprecated as of 1.4 in favor of spring-boot-starter-artemis |
Pom |
spring-boot-starter-amqp |
使用Spring AMQP和Rabbit MQ的启动器。 | Pom |
spring-boot-starter-test |
使用JUnit、Hamcrest和Mockito等第三方库测试Spring Boot应用程序的启动器。 | Pom |
spring-boot-starter-mail |
使用Java Mail和Spring框架的邮件发送服务的启动器 | Pom |
spring-boot-starter-integration |
使用Spring Integration的启动器 | Pom |
spring-boot-starter-validation |
基于Hibernate校验器实现Java Bean校验的启动器。 | Pom |
spring-boot-starter-jta-atomikos |
使用Atomikos实现JTA事务管理的启动器。 | Pom |
spring-boot-starter-jta-narayana |
Spring Boot Narayana JTA启动器。 | Pom |
spring-boot-starter-jta-bitronix |
使用Bitronix实现JTA事务管理的启动器。 | Pom |
spring-boot-starter-security |
使用Spring Security的启动器。 | Pom |
spring-boot-starter-batch |
使用Spring Batch的启动器。 | Pom |
spring-boot-starter-mobile |
使用Spring Mobile构建网络应用程序的启动器。 | Pom |
spring-boot-starter-aop |
使用Spring AOP和AspectJ实现面向切面编程的启动器。 | Pom |
spring-boot-starter-cache |
使用Spring框架的缓存服务的启动器。 | Pom |
spring-boot-starter-cloud-connectors |
使用Spring Cloud Connectors的启动器,以简化Cloud Foundry、Heroku等云平台上服务的连接操作。 | Pom |
spring-boot-starter-social-linkedin |
使用Spring Social LinkedIn的启动器。 | Pom |
spring-boot-starter-social-facebook |
使用Spring Social Facebook的启动器。 | Pom |
spring-boot-starter-social-twitter |
使用Spring Social Twitter的启动器。 | Pom |
*译者注:译者根据逻辑关系对表13.1中的条目顺序进行了调整。
作为应用启动器的补充,以下启动器提供了一些生产运营的特性(production ready features):
表13.2 Spring Boot生产起动器
名称 | 描述 | Pom |
---|---|---|
spring-boot-starter-actuator |
使用Spring Boot的Actuator、来提供监控和管理应用等生产运营特性的启动器。 | Pom |
spring-boot-starter-remote-shell |
基于SSH协议、使用CRaSH远程Shell监控和管理应用的启动器。 | Pom |
最后,Spring Boot还提供了一些启动器,以便用户做一些技术方面的排除或替换。
表13.3 Spring Boot技术启动器
名称 | 描述 | Pom |
---|---|---|
spring-boot-starter-tomcat |
以Tomcat作为嵌入式Servlet容器的启动器。spring-boot-starter-web 使用的默认Servlet容器启动器。 |
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-log4j2 |
使用Log4J2记录日志的启动器。spring-boot-starter-logging 的替代方案。 |
Pom |
提示
查阅GitHub上spring-boot-starters
模块的README文件,将看到一份社区贡献的附加启动器列表。
Spring Boot的运行不依赖于任何特定的代码结构,以下是一些可能有所助益的最佳实践。
当一个类没有声明所在的package
时,则认为它位于“默认包”。通常不推荐使用“默认包”,并且应该尽量避免。使用默认包将导致使用@ComponentScan
、@EntityScan
和@SpringBootApplication
注解的Spring Boot程序发生一些特殊的问题,这是因为所有Jar包中的所有类都将被读取。
提示
笔者建议用户遵循Java推荐的包命名规范,使用反序域名(reversed domain)(如,com.example.project
)。
笔者推荐将主应用类(main application class)放在其他类上层的根包之中。@EnableAutoConfiguration
注解通常用来修饰主类,以此确定一个基础的”搜索包“以便识别所有代码项。例如对一个JAP应用而言,@EnableAutoConfiguration
注解修饰类所在的包将作为@Entity
项扫描的范围。
使用根包同时也使得@ComponentScan
注解不再需要指定basePackage
属性。如果主类位于根包之后,也可以使用@SpringBootApplication
注解。
以下是比较典型的代码结构:
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java
Application.java
文件将声明mian
方法,以及基础的@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);
}
}
Spring Boot支持以Java为基础的配置。尽管可以通过XML资源启动SpringApplication.run()
方法,笔者强烈推荐以@Configration
类作为核心的资源。通常使用定义main
方法的类作为主@Configuration
是不错的选择。
提示
许多已经发布在Internet的Spring配置示例都使用了XML配置。一般在可能的情况下,尽量使用基于Java的等效配置。尝试检索enable*
是个不错的入手点。
无需将所有的@Configuration
放在单一的一个类中。@Import
注解可以用于引入额外的配置类。或者,也可以使用@ComponentScan
来自动的扫描所有的Spring组件,包括@Configuration
类。
如果不得不使用基于XML的配置,笔者仍然推荐以@Configuration
启动。这时,可以使用@ImportResource
注解来加载XML配置文件。
Spring Boot的自动配置功能尝试以所添加Jar依赖为基础,自动化地对Spirng应用程序进行配置。例如,如果HSQLDB
位于classpath之上,并且用户没有手动地配置任何数据库连接Bean,那么Spring Boot将自动配置一个内存数据库。
在一个@Configuration
类上加上@EnableAutoConfiguration
或者@SpringBootApplication
注解即可启用自动配置功能。
提示
仅需要添加一个@EnableAutoConfiguration
注释即可,笔者一般建议将其添加在主@Configuration
类之上。
自动配置是非侵入性的(noninvasive),用户随时可以定义自己的配置来替代特定的自动配置。例如,如果用户增加了自己的DataSource
Bean,默认的嵌入式数据将被取缔。
通过--debug
启动应用,便可以查看当前启用了哪些自动配置,以及为什么会启用这些自动配置。这将在控制台打印一些核心的调试日志和自动配置的报告。
用户可以使用@EnablAutoConfiguration
的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.exlude
属性配置(property)来控制禁止自动加载的列表。
提示
用户可以同时使用注解和属性配置(property)来定义排除那些自动配置。
用户可以自由地使用所有标准的Spring框架技术来定义Bean以及他们所注入的依赖。简单起见,一般使用@ComponentScan
来扫描Bean,结合使用@Autowired
构造器注入是不错的选择。
如果按照上述建议的方式组织代码(将主应用程序类放在根包),则@ComponentScan
无须添加任何参数。所有的应用程序组件(@Component
、@Service
、@Repository
、@Controller
等)都将自动注册为Spring Bean。
以下是一个通过构造器注入RiskAssessor
Bean依赖的@Service
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;
}
// ...
}
提示
请注意示例是如何通过构造器为被标记为final
的riskAssessor
字段注入依赖的,这个字段在后续代码中是不允许修改的。
通常,Spring Boot的开发者会使用@Configuration
、@EnableAutoConfigration
和@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
属性的别名。
将应用程序打包为Jar包并通过内置HTTP服务器启动的最大优点在于能够使应用程序像其他方式一样正常地运行。可以很容易地调试程序,也无须任何特定的插件或扩展。
注
本节仅包含了使用Jar方式进行打包的情况,如果用户需要将应用程序打包为War包则最好遵照所用服务器和IDE的文档。
用户可以像运行一个简单的Java程序一样使用IDE运行一个Spring Boot应用程序,但首先需要导入该程序。导入步骤将取决于IDE和构建系统。大多数IDE支持直接导入Maven项目,例如Eclipse用户可以选择导入...
→现有Maven项目
从文件目录中进行选择。
如果不能直接通过IDE导入项目,则需要使用构建插件来生产IDE的元数据。Maven提供了Eclipse和IDEA的插件,Gradle为各种IDE提供了插件。
提示
如果不小心运行一个Web应用程序两次,将出现“端口已经在使用”错误。STS的用户可以以重启
按键来替代运行
,从而确保现有的实例被关闭。
如果使用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
能够快速地编译和运行程序是Spring Boot Maven插件的设计目标之一。应用程序能够以与IDE同样的方式迅速地被执行。
$ mvn spring-boot:run
通过以下方式使用操作系统变量:
$ export MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128M
Spring Boot Gradle插件同样提供了一个bootRun
任务,以便能够快速地运行应用程序。当用户引入spring-boot-gradle-plugin
时便添加了bootRun
任务。
$ gradle bootRun
通过以下方式使用操作系统变量:
$ export JAVA_OPTS=-Xmx1024m -XX:MaxPermSize=128M
&esmp;因为Spring Boot应用程序就是一个简单的Java应用,所以JVM的热切换是开箱即用(Out Of Box)的。JVM热交换是一项可以替换字节码的技术,JRebel或者Spring Loaded程序是更为完整的解决方案。spring-boot-devtools
模块提供了快速重启应用功能。
详情请参见下一章”第20章 开发者工具“和”如何热启动“章节。
Spring Boot提供了一些使开发更为轻松愉快的附加工具。任何工程都可以添加spring-boot-devtools
模块以获得这些开发过程中的(development-time)附加特性。简单地在构建系统中加入该模块的依赖,就可以后的Spring Boot提供的开发工具:
Maven:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
dependencies>
Gradle:
dependencies {
compile("org.springframework.boot:spring-boot-devtools")
}
注
在运行一个完全打包的应用程序时,开发工具会自动禁用。如果应用程序是通过java -jar
加载的、或者通过某种特殊的类装载器启动,它被认为是一个“生产部署的应用”。将该依赖标记为可选的是一个最佳实践,以免开发工具的应用范围扩散到使用当前程序的其他模块。Gradle不支持开箱即用的可选依赖,所以可能需要查阅propdeps-plugin
。提示
默认情况下重打包的归档文件不会包含开发工具。如果希望使用[某些远程开发工具包][]功能,可以使用excludeDevtools
构建属性来完全删除对应的Jar。Maven和Gradle插件均提供了该属性。
有些Spring Boot提供的库可以通过使用缓存来提高性能。例如,Thymeleaf 会缓存模板,以保存反复解析的XML源文件。对于生产环境而言缓存是一项非常有用的技术,但对于开发而言可能恰恰相反。当在IDE中修改一个模板文件时,用户期望能够马上生效。
通常在application.properties
文件中设置缓存选项。例如,Thymeleaf 提供了spring.thymeleaf.cache
属性。sping-boot-devtools
模块会自动地进行开发过程中的配置,所以无需手动设置这些属性。
提示
查阅DevToolsPropertyDefaultsPostProcessor以获得一个完整的属性列表。
当类路径上的文件变更时,使用spring-boot-devtools
的应用程序将自动重启。当时用IDE时这是一个非常有用的特性,因为IDE提供了非常敏捷的代码变更反馈回路(feedback loop)。默认情况下,任何在类路径所指文件夹中的实体的变化都将被监控。值得注意的是,某些资源的更新——如静态资产和视图模板——是不需要重新启动应用程序。
触发启动
DevTools监控类路径上的资源,出发重启的唯一途径是更新类路径。什么操作将更新类路径取决于用户所使用的IDE。对Eclipse而言,保存修改后的文件会导致类路径更新并触发重启。在IntelliJ IDEA中,构建当前工程(Build -> Make Project
)会有相同的效果。
-
注
也可以通过所支持的构建插件(如Maven和Gradle)来启动应用程序,只要分支(forking)是可用的,因为DevToll需要一个独立的应用程序类加载器来正常运行。当Maven和Gradle发现DevTools在类路径上时将按照默认配置来执行。
提示
当启用LiveReload时,自动重启功能将运作的很好。详情请参见下文。如果使用了JRebel,为支持动态类加载,自动重启将被禁用。其他DevTool的功能(如LivereLoad和属性重写)仍然可以使用。
注
在重启的过程中,DevTools需要依赖应用程序上下文的终止钩子来关闭程序。如果用户禁用终止钩子(SpringApplication.setRegisterShutdownHook(false)
),自动重启将无法正常工作。
注
在判断一个类路径上实体变化时是否应该触发重启时,DevTools将自动忽略以spring-boot
、spring-boot-devtools
、spring-boot-autoconfigure
、spring-boot-actuator
和spring-boot-starter
命名的项目。
-
重启与重装
Spring Boot提供的重启技术基于两个类加载器运作。基础类加载器加载不变的类(例如第三方Jar提供的类)。重启类加载器加载用户正在编辑的类。当应用重启时,原有的重启类加载器就将被遗弃并重新创建新的重启类加载器。因为基础类加载器处于就绪状态,所以通过这种方式重启应用通常会比“冷重启”快很多。
如果应用重启得不够快或者遇到类加载相关的问题,用户可以考虑使用诸如ZeroTurnmaround所提供JRebel一类的重加载技术。这些技术将在类被加载的时候重写它们,以使得这些类更适合于重加载。尽管Spring Loaded不支持很多框架也并非商业版本,不过也不失为一种选择。
有些资源无须在它们被修改时触发重启。例如,Thymeleaf模板可以在线(in-place)编辑。默认情况下,位于/ META-INF /maven
、/ META-INF /resources
、/resources/static
、/public
、/templates
位置的资源变化时不会触发重新启动,而是触发一次线上重载(live reload)。用户可以使用spring.devtools.restart.exclude
配置属性来自定义这些排除项。例如,如下配置将只排除/static
和/public
:
spring.devtools.restart.exclude=static/**,public/**Tip
提示
如果用户希望在默认项基础上添加额外的排除项,可以使用spring.devtools.restart.additional-exclude
配置属性。
用户可能希望当不在类路径上的文件变化时也可以重启或重载应用程序。为此,可以配置spring.devtools.restart.additional-paths
配置属性来监控这些路径上的变化。设置上述spring.devtools.restart.exclude
配置属性来控制附加路径上的变化应该触发一次完整地重启还是仅仅触发一次线上重载(live reload)。
如果不想使用重启动功能,使用spring.devtools.restart.enabled
配置属性禁用该功能。通常,可以在application.properties
文件这进行上述设置(这样Spring Boot仍然会初始化启动类装载器,但是这个加载器不会监控文件的变化)。
如果需要彻底禁止重启功能,比如当该功能与某些库不兼容时,则需要在调用SpringApplicaiton.run(...)
方法前设置一个System
配置属性,方法述如下:
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}
如果使用的是连续编译发生变化文件的IDE,用户可能更希望能在特定的时间触发重启。为此,可以使用“触发文件”,这是一个当希望实际出发一次重启检查时必须被修改的特殊文件。修改该文件只触发重启检查,只有当DevTools发现必须有所动作时才会触发重启。触发文件可以手动更新,也可以通过IDE插件修改。
通过spring.devtools.restart.trigger-file
配置属性使用触发文件。
提示
可以将spring.devtools.restart.trigger-file
设定为全局设置,这样所有的项目都将使用相同的配置。
如上重启和重加载章节所述,重启功能是通过两个类加载器实现的。通常这种方式是没有问题的,但也有一些例外。
默认情况下,IDE中打开的工程都将被“重启”类加载器加载,而所有以.jar
命名的文件都将被“基础”类加载器加载。如果在开发一个多模块项目,并且没有将所有的模块导入到IDE中,这时就需要进行一些自定义工作。为此,可以创建一个META-INF / spring-devtools.properties
文件。
spring-devtools.properties
文件包含以restart.exclude.
和restart.include.
为前缀的配置属性。include
元素将被加载到“重启”类加载器,exclude
将被加载到“基础”类加载器。该配置属性的一个值是一个应用于类路径的正则表达式。
例如:
restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar
注
所有以restart.include.
或restart.exclude.
开始的配置属性的键都必须是唯一的。
提示
类路径上的所有META-INF / spring-devtools.properties
都将被加载。用户可以将这些文件打包在自己的工程中,或者包含在该工程使用的库中。
重启功能无法兼容通过标准ObjectInputStream
反序列化的对象。如果需要反序列化数据,需要结合使用Spring的ConfigurableObjectInputStream
和Thread.currentThread().getContextClassloader()
。
不幸的是,有些第三方库在反序列化时没有考虑上下文类加载器。如果发现了类似的问题,可能需要请第三方库的原作者进行修复。
spring-boot-devtools
模块包含了一个嵌入式LiveReload服务器,用以在资源变化时触发一次浏览器刷新。Chrome,Firefox和Safar的LivereLoad浏览器扩展可以从livereload.com免费获得。
如果不希望在应用程序运行时启动LivereLoad服务器,则需要将spring.devtools.livereload.enabled
配置属性设置为false
。
注
同一时间只能运行唯一的一个LivereLoad服务器。在启动应用程序前,需要确保没有其他LivereLoad服务器正在运行。如果在IDE中启动了多个应用程序,则只有第一个程序将具有LivereLoad特性。
可以在$HOME
文件夹中添加一个名为.spring-boot-devtools.properties
的文件来配置全局开发工具配置(注意文件名以“.”开始)。这个文件中的所有配置属性都将应用到当前机器上所有使用开发工具包的Spring Boot应用。例如,希望在大多数情况下使用触发文件配置重启,则需要如下配置:
~/.spring-boot-devtools.properties.
spring.devtools.reload.trigger-file=.reloadtrigger
Spring Boot的开发者工具不只局限于本地开发。在远程运行应用程序时,也可以使用某些功能。远程支持是可选的,需要设置spring.devtools.remote.secret
配置属性来启用它。例如:
spring.devtools.remote.secret=mysecretWarning
注
在远程应用中启用spring-boot-devtools
时有安全风险的。不应该在生产环境中启用该功能。
远程开发工具包分为两个部分:一个端点位于服务器端以接受连接,一个位于IDE中运行的客户端应用程序。当设置了spring.devtools.remote.secret
配置属性时,服务器组建将自动启用。客户端组件必须手动启用。
远程客户端应用程序设计为运行在IDE之中。需要使用与所连接的远程程序相同的类路径来运行org.springframework.boot.devtools.RemoteSpringApplication
。传递给应用程序的非可选参数应该是所连接的远程URL。
如使用Eclipse或STS并且已经在云平台上部署了一个名为my-app
的应用程序,然后如下操作:
Run
菜单选择Run Configurations…`?;Java Application
”launch configuration”;my-app
项目;org.springframework.boot.devtools.remotespringapplication
作为主类;https://myapp.cfapps.io
程序参数(或者其他所需的远程URL)。远程客户端运行如下所示:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: 1.4.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
配置属性。
和本地重启一样,远程客户端将监控应用程序类路径上发生的变化。所有更新的资源都将被推送到远程应用程序,并且在需要的时候触发重启。当使用某些本地没有并且正在迭代中的云端功能时,这一功能将有帮助。远程更新和重启通常比一个完整的重建和部署周期快很多。
注
只有当客户端在运行的时候才会监控文件。如果在启动远程客户端之前更改一个文件,这次更改将不会被推送到远程服务器上。
Java远程调试对于远程应用异常的诊断非常有帮助。不幸的是,如果应用程序部署在数据中心之外,有时候无法进行远程调试。使用诸如Docker等基于容器的技术时,远程调试可能也难于配置。
为了解决这些限制,开发工具包提供了基于HTTP的远程调试流量隧道。远程客户端在端口8000
上提供了一个用以连接远程调试器的本地服务器。一旦连接建立,调试流量是通过HTTP发送到远程应用程序的。如果像使用不同的端口,可以配置spring.devtools.remote.debug.local-port
配置属性。
需要确保远程应用程序启动时配置了启用调试功能。这通常可以通过配置JAVA_OPTS
实现。例如,在云计算中可以在manifest.yml
中添加以下内容:
---
env:
JAVA_OPTS: "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n"
提示
注意,不需要为- Xrunjdwp
指定address=NNNN
选项。省略上述配置,Java会随机选择一个空闲的端口。
注
通过互联网来调试一个远程服务响应可能比较慢,这时则需要延长IDE的超时时间。例如,在Eclipse中选择Preferences...
菜单下的Java
→Debug
,将Debugger timeout(ms)
设置为一个更合适的值(大多数情况60000
比较合适)。
可执行Jar包可以用于生产部署。由于这些Jar包是自包含的,理论上也是适用于基于云的部署的。
如果希望使用REST健康、审计和度量以及JMX端点等附加的“生产运维”特性,可以考虑使用spring-boot-actuator
。详见第五部分 Spring Boot执行器:生产运维功能。
用户应该已经很好地掌握了如何遵循最佳实践来使用Spring Boot的方法。可以顺序学习具体的Spring Boot features,或者直接跳转到阅读Spring Boot生产运维相关内容。