目次
6. @SpringBootApplication アノテーションを使用する
8.3.6. カスタム再起動クラスローダー (再起動クラスローダー)
9. アプリケーションをパッケージ化し、実稼働環境にデプロイします。
1. システムの構築
依存関係管理をサポートし、「Maven Central」から依存関係を取得できるビルド システムを選択することを強くお勧めします。Maven または Gradle を選択することをお勧めします。他のビルド システム (Ant など) を選択することもできますが、そのサポートはあまり優れていません。
1.1. 依存関係の管理
Spring Boot の各リリースでは、サポートされる依存関係のリストが提供されます。実際には、Spring Boot がこれを管理するため、ビルド構成でこれらの依存関係のバージョンを宣言する必要はありません。Spring Boot 自体をアップグレードすると、これらの依存関係もアップグレードされます。
依存関係のバージョンを指定して、スプリング ブートのデフォルト バージョンをオーバーライドすることもできます。
この厳選された依存関係のリストには、Spring Boot で使用できるすべての Spring モジュールと、サードパーティ ライブラリのリストが含まれています。このリストは依存関係 ( spring-boot-dependency ) として提供されており、Maven と Gradle で利用できます。
Spring Boot の各リリースは、Spring Framework の基本バージョンに関連しています。Spring のバージョンを変更しないことを強くお勧めします。
1.2. メイビン
Maven は Java プロジェクト用に特別に設計された管理および構築ツールであり、主な機能は次のとおりです。
- 標準化されたプロジェクト構造を提供します。
- 標準化されたビルド プロセス (コンパイル、テスト、パッケージ、リリースなど) を提供します。
- 一連の依存関係管理メカニズムを提供します。
Maven プロジェクトの構造
Maven によって管理される通常の Java プロジェクトのデフォルトのディレクトリ構造は次のとおりです。
a-maven-project
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ ├── java
│ └── resources
└── target
プロジェクトのルート ディレクトリa-maven-project
はプロジェクト名です。プロジェクト説明ファイルがありますpom.xml
。Java ソース コードを格納するディレクトリはsrc/main/java
、リソース ファイルを格納するディレクトリはsrc/main/resources
、テスト ソース コードを格納するディレクトリはsrc/test/java
、テストを格納するディレクトリはです。最後にsrc/test/resources
、コンパイルおよびパッケージ化されたすべてのファイルが生成され、target
ディレクトリに配置されます。これらは、Maven プロジェクトの標準のディレクトリ構造です。
すべてのディレクトリ構造は合意された標準構造であるため、ディレクトリ構造を任意に変更してはなりません。標準構造を使用する場合、特に設定は必要なく、Maven を通常どおり使用できます。
1.3. スターター
Starter は、アプリケーションにインポートできる、すぐに使用できる依存関係のセットです。スターターを通じて、必要なすべての Spring および関連テクノロジーのワンストップ サービスを利用できるため、依存関係をどこにでもコピー アンド ペーストする必要がなくなります。たとえば、データベース アクセスに Spring と JPA の使用を開始したい場合は、プロジェクトに spring-boot-starter-data-jpa 依存関係を直接インポートできます。
Starter には、プロジェクトを迅速に起動して実行するために必要な依存関係の多くが含まれており、サポートされ管理可能な移行依存関係の一貫したセットが含まれています。
スターターのネーミングについて
すべての公式スターターは、同様の命名パターンに従います (spring-boot-starter-* (* は特定の種類のアプリケーション))。この命名構造は、スターターを見つける必要があるときに役立ちます。多くの IDE に Maven が統合されているため、依存関係を名前で検索できます。たとえば、対応する Eclipse または Spring Tools プラグインがインストールされている場合は、POM エディターで Ctrl-Space を押し、「spring-boot-starter」と入力して完全なリストを取得できます。
「独自のスターターの作成」セクションで説明したように、サードパーティのスターターは spring-boot で起動しないでください。これは、公式の Spring Boot コンポーネント用に予約されているためです。対照的に、サードパーティのランチャーは通常、プロジェクト名で始まります。たとえば、 thirdpartyproject という名前のサードパーティ スターター プロジェクトは、通常、 thirdpartyproject-spring-boot-starter という名前になります。
以下は、Spring Boot によって org.springframework.boot の groupId で提供されるスターター コンポーネントです。
表 1. Spring Boot アプリケーション スターター |
|
名前 |
説明 |
スプリングブートスターター |
自動構成サポート、ロギング、YAML を含むコア スターター |
スプリングブートスターターアクティブmq |
Apache ActiveMQ を使用した JMS メッセージングのスターター |
スプリングブートスターターamqp |
Spring AMQP および Rabbit MQ を使用するためのスターター |
スプリングブートスターターAOP |
Spring AOP と AspectJ を使用したアスペクト指向プログラミングのスターター |
スプリングブートスターターアルテミス |
Apache Artemis を使用した JMS メッセージングのスターター |
スプリングブートスターターバッチ |
Spring Batch を使用するためのスターター |
スプリングブートスターターキャッシュ |
Spring Framework のキャッシュ サポートを使用するためのスターター |
スプリングブートスターターデータカサンドラ |
Cassandra 分散データベースと Spring Data Cassandra を使用するためのスターター |
スプリングブートスターターデータカサンドラ反応性 |
Cassandra 分散データベースと Spring Data を使用するためのスターター Cassandra Reactive |
スプリングブートスターターデータカウチベース |
Couchbase ドキュメント指向データベースと Spring Data Couchbase を使用するためのスターター |
スプリングブートスターターデータカウチベースリアクティブ |
Couchbase ドキュメント指向データベースと Spring Data Couchbase Reactive を使用するためのスターター |
スプリングブートスターターデータエラスティックサーチ |
Elasticsearch 検索および分析エンジンと Spring Data Elasticsearch を使用するためのスターター |
スプリングブートスターターデータjdbc |
Spring Data JDBC を使用するためのスターター |
スプリングブートスターターデータjpa |
Hibernate で Spring Data JPA を使用するためのスターター |
スプリングブートスターターデータLDAP |
Spring Data LDAP を使用するためのスターター |
スプリングブートスターターデータモンゴデータベース |
MongoDB ドキュメント指向データベースと Spring Data MongoDB を使用するためのスターター |
spring-boot-starter-data-mongodb-reactive |
MongoDB ドキュメント指向データベースと Spring Data MongoDB Reactive を使用するためのスターター |
スプリングブートスターターデータneo4j |
Neo4j グラフ データベースと Spring Data Neo4j を使用するためのスターター |
スプリングブートスターターデータr2dbc |
Spring Data R2DBC を使用するためのスターター |
スプリングブートスターターデータredis |
Spring Data Redis および Lettuce クライアントで Redis キー/値データ ストアを使用するためのスターター |
スプリングブートスターターデータredis反応性 |
Spring Data Redis リアクティブおよび Lettuce クライアントで Redis キー/値データ ストアを使用するためのスターター |
スプリングブートスターターデータレスト |
Spring Data REST と Spring MVC を使用して REST 経由で Spring Data リポジトリを公開するためのスターター |
スプリングブートスターターフリーマーカー |
FreeMarker ビューを使用して MVC Web アプリケーションを構築するためのスターター |
スプリングブートスターターグラフql |
Spring GraphQL を使用して GraphQL アプリケーションを構築するためのスターター |
Spring-Boot-Starter-groovy-templates |
Groovy テンプレート ビューを使用して MVC Web アプリケーションを構築するためのスターター |
スプリングブートスターターhateoas |
Spring MVC および Spring HATEOAS を使用してハイパーメディアベースの RESTful Web アプリケーションを構築するためのスターター |
スプリングブートスターター統合 |
Spring Integration を使用するためのスターター |
スプリングブートスターターjdbc |
HikariCP 接続プールで JDBC を使用するためのスターター |
スプリングブーツスタータージャージ |
JAX-RS と Jersey を使用して RESTful Web アプリケーションを構築するためのスターター。spring-boot-starter-web の代替手段 |
スプリングブートスタータージョーク |
jOOQ を使用して JDBC で SQL データベースにアクセスするためのスターター。spring-boot-starter-data-jpa または spring-boot-starter-jdbc の代替 |
スプリングブートスターターjson |
json の読み取りと書き込みのためのスターター |
スプリングブートスターターメール |
Java Mail および Spring Framework の電子メール送信サポートを使用するためのスターター |
スプリングブーツスターター口ひげ |
Mustache ビューを使用して Web アプリケーションを構築するためのスターター |
spring-boot-starter-oauth2-authorization-server |
Spring Authorization Server 機能を使用するためのスターター |
スプリングブートスターター-oauth2-クライアント |
Spring Security の OAuth2/OpenID Connect クライアント機能を使用するためのスターター |
spring-boot-starter-oauth2-resource-server |
Starter for using Spring Security’s OAuth2 resource server features |
spring-boot-starter-quartz |
Starter for using the Quartz scheduler |
spring-boot-starter-rsocket |
Starter for building RSocket clients and servers |
spring-boot-starter-security |
Starter for using Spring Security |
spring-boot-starter-test |
Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito |
spring-boot-starter-thymeleaf |
Starter for building MVC web applications using Thymeleaf views |
spring-boot-starter-validation |
Starter for using Java Bean Validation with Hibernate Validator |
spring-boot-starter-web |
Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container |
spring-boot-starter-web-services |
Starter for using Spring Web Services |
spring-boot-starter-webflux |
Starter for building WebFlux applications using Spring Framework’s Reactive Web support |
spring-boot-starter-websocket |
Starter for building WebSocket applications using Spring Framework’s MVC WebSocket support |
除了应用starter外,以下启动器可用于添加 生产就绪 功能。
Table 2. Spring Boot 生产(环境) starter |
|
Name |
Description |
spring-boot-starter-actuator |
Starter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application |
最后,Spring Boot还包括以下starter,如果你想排除或更换特定的技术实现,那么可以使用它们。
Table 3. Spring Boot 技术(实现) starter |
|
Name |
Description |
spring-boot-starter-jetty |
Starter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcat |
spring-boot-starter-log4j2 |
Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging |
spring-boot-starter-logging |
Starter for logging using Logback. Default logging starter |
spring-boot-starter-reactor-netty |
Starter for using Reactor Netty as the embedded reactive HTTP server. |
spring-boot-starter-tomcat |
Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web |
spring-boot-starter-undertow |
Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat |
2. 代码结构
Spring Boot对代码的布局,没有特别的要求。 但是,有一些最佳实践。
2.1. “default” 包
当一个类不包括 package 的声明时,它被认为是在 “default package” 中。 通常应避免使 “default package”。 对于使用了 @ComponentScan, @ConfigurationPropertiesScan, @EntityScan 或者 @SpringBootApplication 注解的Spring Boot应用程序来说,它可能会造成一个问题:项目中的所有jar里面的所有class都会被读取(扫描)。
我们建议你遵循Java推荐的包的命名惯例,使用域名反转作为包名(例如, com.example.project)。
2.2. 启动类的位置
我们通常建议你将你启动类放在一个根package中,高于其他的类,@SpringBootApplication 注解一般都是注解在启动类上的。它默认会扫描当前类下的所有子包。例如,如果你正在编写一个JPA应用程序,你的 @Entity 类只有定义在启动类的子包下才能被扫描加载到。这样的好处也显而易见,@SpringBootApplication 默认只会扫描加载你项目工程中的组件。
如果你不想使用 @SpringBootApplication ,它所导入的 @EnableAutoConfiguration 和 @ComponentScan 注解定义了该行为,所以你也可以使用这些来代替。
一个项目典型的布局如下。
com
+- example
+- myapplication
+- MyApplication.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
MyApplication.java 文件声明了 main 方法,以及标识了基本的 @SpringBootApplication 注解,如下所示。
Java
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
3. Configuration 类
Spring Boot倾向于通过Java代码来进行配置的定义。 虽然也可以使用XML来配置 SpringApplication ,但还是建议你通过 @Configuration 类来进行配置。 通常,可以把启动类是作为主要的 @Configuration 类。
网上有很多关于“通过XML配置Spring”的示例,如果可以的话,还是尽量使用Java代码的方式来实现相同的配置。你可以尝试着搜索 Enable* 注解。
3.1. 导入额外的 Configuration 类
你不需要把所有的 @Configuration 放在一个类中。 @Import 注解可以用来导入额外的配置类。 另外,你可以使用 @ComponentScan 来自动扫描加载所有Spring组件,包括 @Configuration 类。
3.2. 导入 XML Configuration
如果你确实需要使用基于XML的配置,我们建议你仍然从 @Configuration 类开始,然后通过 @ImportResource 注解来加载XML配置文件。
4. 自动装配(配置)
Spring Boot的自动装配机制会试图根据你所添加的依赖来自动配置你的Spring应用程序。 例如,如果你添加了 HSQLDB 依赖,而且你没有手动配置任何DataSource Bean,那么Spring Boot就会自动配置内存数据库。
你需要将 @EnableAutoConfiguration 或 @SpringBootApplication 注解添加到你的 @Configuration 类中,从而开启自动配置功能。
你应该只添加一个 @SpringBootApplication 或 @EnableAutoConfiguration 注解。 建议添加到主要的 @Configuration 类上。
4.1. 逐步取代自动配置
自动配置是非侵入性的。 在任何时候,你都可以开始定义你自己的配置来取代自动配置的特定部分。 例如,如果你添加了你自己的 DataSource bean,默认的嵌入式数据库支持就会“退步”从而让你的自定义配置生效。
如果你想知道在应用中使用了哪些自动配置,你可以在启动命令后添加 --debug 参数。 这个参数会为核心的logger开启debug级别的日志,会在控制台输出自动装配项目以及触发自动装配的条件。
4.2. 禁用指定的自动装配类
如果你想禁用掉项目中某些自动装配类,你可以在 @SpringBootApplication 注解的 exclude 属性中指定,如下例所示。
Java
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {
}
如果要禁用的自动装配类不在classpath上(没有导入),那么你可以在注解的 excludeName 属性中指定类的全路径名称。 exclude 和 excludeName 属性在 @EnableAutoConfiguration 中也可以使用。 最后,你也可以在配置文件中通过 spring.autoconfigure.exclude[] 配置来定义要禁用的自动配置类列表。
你可以同时使用注解 + 配置的方式来禁用自动装配类。
自动配置类一般都是 public 的,除了这个类的名称以外(用来禁用它)的任何东西,例如它的方法和属性,包括嵌套的配置类。都不建议你去使用。 |
5. Spring Bean 和 依赖注入
你可以使用任何标准的Spring技术来定义你的Bean以及依赖注入关系。 推荐使用构造函数注入,并使用 @ComponentScan 注解来扫描Bean。
如果你按照上面的建议构造你的代码(将你的启动类定位在顶级包中),你可以在启动类添加 @ComponentScan 注解,也不需要定义它任何参数, 你的所有应用组件(@Component、@Service、@Repository、@Controller 和其他)都会自动注册为Spring Bean。
也可以直接使用 @SpringBootApplication 注解(该注解已经包含了 @ComponentScan)。
下面的例子展示了一个 @Service Bean,它使用构造器注入的方式注入了 RiskAssessor Bean。
Java
@Service
public class MyAccountService implements AccountService {
private final RiskAssessor riskAssessor;
public MyAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
如果一个Bean有多个构造函数,你需要用 @Autowired 注解来告诉Spring该用哪个构造函数进行注入。
Java
@Service
public class MyAccountService implements AccountService {
private final RiskAssessor riskAssessor;
private final PrintStream out;
@Autowired
public MyAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
this.out = System.out;
}
public MyAccountService(RiskAssessor riskAssessor, PrintStream out) {
this.riskAssessor = riskAssessor;
this.out = out;
}
// ...
}
上面示例中通过构造器注入的 riskAssessor 字段被标识为了 final,表示一旦Bean创建这个字段就不被改变了。这也是我们推荐的做法。 |
6. 使用 @SpringBootApplication 注解
许多Spring Boot开发者希望他们的应用程序能够使用自动配置、组件扫描,并且能够在他们的 "application class "上定义额外的配置。 一个 @SpringBootApplication 注解就可以用来启用这三个功能,如下。
- @EnableAutoConfiguration:启用Spring Boot的自动配置机制。
- @ComponentScan:对应用程序所在的包启用 @Component 扫描(见最佳实践)。
- @SpringBootConfiguration:允许在Context中注册额外的Bean或导入额外的配置类。这是Spring标准的 @Configuration 的替代方案,有助于在你的集成测试中检测配置。
Java
// Same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@SpringBootApplication 也提供了属性别名来定制 @EnableAutoConfiguration 和 @ComponentScan 中的属性。 |
这些功能都不是强制必须的,你可以随时只使用其中任意功能的注解。 例如,你不需要在你的应用程序中使用组件扫描或配置属性扫描。 Java 在这个例子中,MyApplication 和其他Spring Boot应用程序一样,只是不能自动检测到 @Component 和 @ConfigurationProperties 注解的类,而是明确导入用户定义的Bean(见 @Import)。 |
7. 运行你的应用
把应用打包成可执行jar,并且使用嵌入式HTTP服务器的最大优势,就是可以像其他程序一样运行应用。
该样本适用于调试Spring Boot应用程序。 你不需要任何特殊的IDE插件或扩展。
本节只涉及基本的jar打包。 如果你选择将你的应用程序打包成war文件,请参阅你所使用的Server和IDE的文档。 |
7.1. 在IDE中运行应用
你可以在IDE中像运行普通Java程序一样运行你的Spring Boot应用。 不过,你首先需要导入你的项目。 不同的IDE导入方式可能不同, 大多数IDE可以直接导入Maven项目。 例如,Eclipse用户可以从 File 菜单中选择 Import… → Existing Maven Projects 。
如果你不能直接将项目导入IDE,你可以通过构建插件来生成IDE的元数据。包括用于 Eclipse 和 IDEA 的 Maven 插件。Gradle为各种 IDE 都提供了插件。
如果你不小心把一个Web应用程序运行了两次,你会看到 “Port already in use” 这个异常提示。 Spring Tools用户可以使用 Relaunch 按钮而不是 Run 按钮来实现“重启”(如果程序已经在运行,那么会先关闭它再启动)。 |
7.2. 运行打包后的应用
如果你使用Spring Boot的Maven或Gradle插件来创建可执行jar,你可以使用 java -jar 来运行你的打包后应用程序,如下例所示。
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
打包后的jar程序,也支持通过命令行参数开启远程调试服务,如下。
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myapplication-0.0.1-SNAPSHOT.jar
7.3. 使用 Maven 插件
Spring Boot Maven 插件包括一个 run 目标(goal),可用于快速编译和运行你的应用程序。 应用程序以 exploded 的形式运行,就像在IDE中一样。 运行Spring Boot应用的Maven命令如下。
$ mvn spring-boot:run
如果项目的构建需要消耗很大的内存,你可以考虑使用 MAVEN_OPTS 环境变量来修改最大内存,参考如下。
$ export MAVEN_OPTS=-Xmx1024m
7.4. 使用 Gradle 插件
Spring Boot Gradle插件还包括一个 bootRun 任务,可以用来以 exploded 的形式运行你的应用程序。 只要你应用了了 org.springframework.boot 和 java 插件,就会添加 bootRun 任务,如下例所示。
$ gradle bootRun
同上,如果Gradle构建项目出现内存不足,可以通过 JAVA_OPTS 环境变量来增加JVM的内存。
$ export JAVA_OPTS=-Xmx1024m
7.5. 热部署(Hot Swapping)
由于Spring Boot应用程序是普通的Java应用程序,JVM的热替换功能可以直接使用。但是,JVM的热替换能替换的字节码有限。要想获得更完整的解决方案,可以使用 JRebel 。
spring-boot-devtools 模块提供了快速重启应用程序的支持。详情请见 热部署 “How-to”
8. 开发者工具(Developer Tools)
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 {
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
Devtools可能会导致类加载相关的一些问题,特别是在多模块项目中。“ 诊断类加载问题” 解释了如何诊断和解决这些问题。 |
如果你的应用程序是通过 java -jar 启动的,或者是从一个特殊的classloader启动的,那么它就被认为是一个 "生产级别的应用程序",开发者工具会被自动禁用。 你可以通过 spring.devtools.restart.enabled 配置属性来控制这一行为。 要启用devtools,无论用于启动应用程序的类加载器是什么,请设置启动参数 -Dspring.devtools.restart.enabled=true 。 在生产环境中不能这样做,因为运行devtools会有安全风险。 要禁用devtools,请删除该依赖或者设置启动参数 -Dspring.devtools.restart.enabled=false。 |
应该在Maven中把这个依赖的scope标记为 optional,或在Gradle中使用 developmentOnly 配置(如上所示)。以防止使用你的项目的其他模块,传递地依赖了devtools。 |
重新打包的压缩文件默认不包含devtools。如果你想使用某个远程devtool功能,,你需要包含它。使用Maven插件时,将 excludeDevtools 属性设为false。使用Gradle插件时, 配置任务的classpath,使其包括 developmentOnly 配置。 |
8.1. 诊断类加载问题
如 重启 Vs 重载 一节所述,重启功能是通过使用两个classloader实现的。 对于大多数应用程序来说,这种方法效果很好。 然而,它有时会导致类加载问题,特别是在多模块项目中。
为了诊断类加载问题是否确实是由devtools和它的两个类加载器引起的,请试着禁用 restart。如果这能解决你的问题,请定制 restart 类加载器 以包括你的整个项目。
8.2. 属性的默认值
在Spring Boot支持的一些库中,会使用缓存来提高性能。例如,模板引擎会缓存已编译的模板,以避免重复解析模板文件。另外,Spring MVC可以在响应静态资源时往响应中添加HTTP缓存头。
虽然缓存在生产中是非常有益的,但在开发过程中可能会产生反作用,使你无法看到你在应用程序中刚做的改动。 由于这个原因,spring-boot-devtools 默认禁用了缓存选项。
缓存的选项通常是通过 application.properties 文件中的属性来配置的。 例如,Thymeleaf提供了 spring.thymeleaf.cache[] 属性。 与其需要手动设置这些属性,spring-boot-devtools 模块会在开发场景下合理的设置这些属性。
下表列出了所有被设置的属性。
Name |
Default Value |
server.error.include-binding-errors |
always |
server.error.include-message |
always |
server.error.include-stacktrace |
always |
server.servlet.jsp.init-parameters.development |
true |
server.servlet.session.persistent |
true |
spring.docker.compose.readiness.wait |
only-if-started |
spring.freemarker.cache |
false |
spring.graphql.graphiql.enabled |
true |
spring.groovy.template.cache |
false |
spring.h2.console.enabled |
true |
spring.mustache.servlet.cache |
false |
spring.mvc.log-resolved-exception |
true |
spring.reactor.netty.shutdown-quiet-period |
0s |
spring.template.provider.cache |
false |
spring.thymeleaf.cache |
false |
spring.web.resources.cache.period |
0 |
spring.web.resources.chain.cache |
false |
如果你不希望设置属性的默认值,你可以在你的 application.properties 中把 spring.devtools.add-properties[] 设置为 false。 |
在开发Spring MVC和Spring WebFlux应用程序时,你可能需要更多关于Web请求的信息,开发者工具建议你为Web日志组启用DEBUG日志。这将给你提供关于客户端的请求信息,哪个handler正在处理它,响应结果,以及其他细节。如果你希望记录所有的请求细节(包括潜在的敏感信息),你可以打开 spring.mvc.log-request-details[] 或 spring.codec.log-request-details[] 配置。
8.3. 自动重启
使用spring-boot-devtools的应用程序会在classpath上的文件发生变化时自动重启。当在IDE中工作时,这可能是一个有用的功能,因为它为代码变化提供了一个非常快速的反馈。默认情况下,classpath上任何指向目录的条目都会被监测到变化。注意,某些资源,如静态资源和视图模板发生变化时,不需要重启应用程序。
触发重启
由于DevTools监控classpath资源,触发重启的唯一方法是更新classpath。 无论你使用的是IDE还是构建插件,被修改的文件都必须被重新编译以触发重启。 导致更新classpath的方式取决于你所使用的工具。
- 在Eclipse中,保存一个修改过的文件会导致classpath被更新并触发重启。
- 在IntelliJ IDEA中,构建项目( Build +→+ Build Project )有同样的效果。
- 如果使用构建插件,运行Maven的 mvn compile 或Gradle的 gradle build 会触发重启。
如果你用Maven或Gradle的构建插件重启,你必须将 forking 设置为 enabled。 如果你禁用 forking,devtools使用的“应用隔离类加载器(isolated application classloader)”将不会被创建,重启功能将无法正常运行。 |
与LiveReload一起使用时,自动重启的效果非常好。 详见 LiveReload 部分。 如果你使用JRebel,自动重启被禁用,而采用动态类重载。 其他devtools特性(如LiveReload和属性覆盖)仍然可以使用。 |
DevTools依靠应用程序上下文的关机hook来在重启期间关闭它。 如果你禁用了关机钩子( SpringApplication.setRegisterShutdownHook(false) ),它就不能正确工作。 |
DevTools需要定制 ApplicationContext 所使用的 ResourceLoader。 如果你的应用程序已经提供了一个,它将被“包装”(装饰者设计模式)起来。 不支持直接覆盖 ApplicationContext 上的 getResource 方法。 |
在使用AspectJ 切面时,不支持自动重启。 |
重启 vs 重载
Spring Boot通过两个类加载器实现了重启。 不变的类(例如,来自第三方jar的类)被加载到一个 base classloader。 你正在开发的类被加载到 restart classloader中。 当应用程序被重新启动时, restart classloader 被丢弃,并被创建一个新的。 这种方法意味着应用程序的重启通常比 “冷启动” 快得多,因为 base classloader 已经可用并被填充。
如果你发现重启对你的应用程序来说不够快,或者你遇到了类加载相关的问题,你可以考虑重载技术,如ZeroTurnaround的 JRebel。这些技术的工作原理是在类被加载时对其进行重写,使其更容易被重载。
8.3.1. 记录条件评估的变化
默认情况下,每次你的应用程序重新启动时,都会记录一份显示条件评估delta的报告。 该报告显示了你的应用程序的自动配置的变化,因为你做了一些改变,如添加或删除Bean和设置配置属性。
要禁用报告的记录,请设置以下属性。
Properties
Yaml
spring.devtools.restart.log-condition-evaluation-delta=false
8.3.2. 排除资源
某些资源在被改变时不一定需要触发重启。例如,Thymeleaf模板可以就地编辑。默认情况下,改变 /META-INF/maven, /META-INF/resources, /resources, /static, /public, /templates 中的资源不会触发重启,但会触发实时重载.。如果你想自定义这些排除项,可以使用 spring.devtools.restart.exclude 属性。例如,要只排除 /static 和 /public ,你可以设置以下属性。
Properties
Yaml
spring.devtools.restart.exclude=static/**,public/**
如果你想保留这些默认值并增加额外的排除资源,请使用 spring.devtools.restart.extra-exclude 属性来代替。 |
8.3.3. 监控额外的路径
当你对不在classpath上的文件进行修改时,你可能希望你的应用程序被重新启动或重新加载。为此,使用 spring.devtools.restart.extra-paths 属性来配置监控变化的额外路径。你可以使用前面说过的的 spring.devtools.restart.exclude 属性来控制额外路径下的变化是触发完全重启还是实时重载。
8.3.4. 禁止重启
如果你不想使用重启功能,你可以通过使用 spring.devtools.restart.enabled 属性来禁用它。在大多数情况下,你可以在你的 application.properties 中设置这个属性(这样做仍然会初始化restart 类加载器,但它不会监控文件变化)。
如果你需要完全禁用重启支持(例如,因为它不能与特定的库一起工作),你需要在调用 SpringApplication.run(…) 之前将 spring.devtools.restart.enabled 属性设置为 false ,如下面的例子中所示。
Java
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApplication.class, args);
}
}
8.3.5. 使用 trigger file
如果你只想在在特定时间触发重启,你可以使用 “trigger file”,这是一个特殊的文件,当你想实际触发重启检查时,那你就对这个文件进行修改。
对文件的任何更新都会触发检查,但只有当Devtools检测到它有改动发生时,才会实际重新启动。 |
通过属性 spring.devtools.restart.trigger-file 设置trigger file 文件的名称(不包括任何路径)。 trigger file必须在classpath路径上。
例如,如果你有一个结构如下的项目。
src
+- main
+- resources
+- .reloadtrigger
那么你的 “trigger-file” 属性应该设置为如下。
Yaml
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
现在只有当 src/main/resources/.reloadtrigger 被更新时才会重新启动。
你可能想把 spring.devtools.restart.trigger-file 设置为全局设置,这样你的所有项目都会以同样的方式行事。 |
有些IDE有一些功能,使你不需要手动更新你的触发器文件。 Spring Tools for Eclipse 和 IntelliJ IDEA (Ultimate Edition))都有这种支持。对于Spring Tools,你可以使用控制台视图中的 “reload” 按钮(需要把你的 trigger-file 命名为 .reloadtrigger)。对于IntelliJ IDEA,你可以按照其文档中的说明进行操作。
8.3.6. 自定义重启类加载器(Restart Classloader)
正如前面在"Restart vs Reload"所描述的,重启功能是通过使用两个classloader实现的。如果这导致了其他的问题,你可能需要自定义类加载器。
默认情况下,你的IDE中任何打开的项目都是用 “restart” 类加载器加载的,而任何常规的 .jar 文件都是用 “base” 类加载器加载。 如果你使用 mvn spring-boot:run 或 gradle bootRun 也是一样:包含了 @SpringBootApplication 的项目用 “restart” 类加载器加载,其他都用 “base” 类加载器。
你可以通过创建 META-INF/spring-devtools.properties 文件来指定Spring Boot用不同的类加载器来加载你的项目的不同部分。 spring-devtools.properties 文件可以包含以 restart.exclude 和 restart.include 开头的属性。 include 元素是应该被“拉”到 “restart” 类加载器中的项目,而 exclude 元素是应该被“推”到 “base” 类加载器中的项目。 该属性的值是一个基于classpath的正则表达式,如以下例子所示。
Yaml
restart:
exclude:
companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar"
include:
projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
所有的key必须是唯一的。只要一个属性以 restart.include. 或 restart.exclude. 开头,就会被考虑进去。 |
所有在classpath的 META-INF/spring-devtools.properties 都会被加载。 你可以把它打包到你的项目中,或者打包进你项目依赖的项目中。 |
8.3.7. 已知的限制
如果你使用标准的 ObjectInputStream 来反序列化对象,那么重启功能的效果可能并不好。 如果你需要反序列化数据,你可能需要使用到Spring的 ConfigurableObjectInputStream 与 Thread.currentThread().getContextClassLoader()。
不幸的是,一些第三方库在反序列化时没有考虑到上下文的类加载器。 如果你发现这样的问题,你需要向原作者请求修复。
8.4. LiveReload
spring-boot-devtools 模块包括一个内嵌的LiveReload服务器,可以用来在资源发生变化时触发浏览器刷新。LiveReload浏览器扩展可以从 livereload.com免费获得,支持Chrome、Firefox和Safari。
如果你不想在应用程序运行时启动LiveReload服务器,你可以将 spring.devtools.livereload.enabled 属性设置为 false 。
你一次只能运行一个LiveReload服务器。 在启动你的应用程序之前,确保没有其他LiveReload服务器正在运行。 如果你从你的IDE启动多个应用程序,只有第一个有LiveReload支持。 |
为了在文件变化时触发LiveReload,必须启用 “自动重启”。 |
8.5. 全局设置
你可以通过在 $HOME/.config/spring-boot 目录下添加以下任何文件来配置全局的devtools设置。
- spring-boot-devtools.properties
- spring-boot-devtools.yaml
- spring-boot-devtools.yml
添加到这些文件中的任何属性都适用于你机器上使用devtools的 所有 Spring Boot应用程序。 例如,如果要将重启配置为总是使用trigger file,你可以在 spring-boot-devtools 文件中添加以下属性。
Yaml
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
默认情况下,$HOME 是用户的主目录。 要自定义这个位置,请设置 SPRING_DEVTOOLS_HOME 环境变量或 spring.devtools.home 系统属性。
如果在 $HOME/.config/spring-boot 中找不到devtools配置文件,则会在 $HOME 目录的根部搜索是否有 .spring-boot-devtools.properties 文件。 这允许你与那些不支持 $HOME/.config/spring-boot 位置的旧版Spring Boot的应用程序共享devtools全局配置。 |
devtools properties/yaml文件中不支持Profiles。 任何在 .spring-boot-devtools.properties 中激活的Profiles都不会影响指定配置文件的加载。不支持在YAML和Properties文件中配置Profiles(形式为 spring-boot-devtools-<profile>.properties )和 spring.config.activate.on-profile。 |
8.5.1. 配置文件系统的监控
FileSystemWatcher 的工作方式是以一定的时间间隔轮询类的变化,然后等待一个预定义的安静期,以确保不再有变化。 由于Spring Boot完全依赖IDE来编译并将文件复制到Spring Boot可以读取的位置,你可能会发现有时devtools重新启动应用程序时,某些变化并没有反映出来(没有立即生效)。 如果你经常观察到这样的问题,可以尝试增加 spring.devtools.restart.poll-interval 和 spring.devtools.restart.quiet-period 参数到适合你开发环境的值。
Yaml
spring:
devtools:
restart:
poll-interval: "2s"
quiet-period: "1s"
受监控的classpath目录现在每2秒轮询一次变化,并保持1秒的安静期以确保没有额外的类变化。
8.6. 远程应用
Spring Boot的开发者工具并不局限于本地开发。 你也可以在远程运行应用程序时使用一些功能。 远程支持是可选的,因为启用它可能会有安全风险。 只有在受信任的网络上运行时,或在用SSL保护时,才应启用它。 如果这两个选项对你来说都不可用,你就不应该使用DevTools的远程支持。 你更不应该在生产环境中启用它。
要启用它,你需要确保 devtools 包含在重新打包的归档文件(jar)中,如以下所示。
<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 属性。 就像任何重要的密码或密钥一样,这个值应该是唯一的和足够强大的,以至于它不能被猜到或被暴力破解。
Remote devtools support is provided in two parts: a server-side endpoint that accepts connections and a client application that you run in your IDE. The server component is automatically enabled when the spring.devtools.remote.secret property is set. The client component must be launched manually.
远程devtools支持由两部分组成:一个接受连接的服务器端端点和一个你在IDE中运行的客户端应用程序。 当 spring.devtools.remote.secret 属性被设置时,服务器组件会自动启用。 客户端组件必须手动启动。
Spring WebFlux应用程序不支持远程devtools。 |
8.6.1. 运行远程客户端程序
远程客户端应用程序被设计成可以在你的IDE中运行。 你需要运行 org.springframework.boot.devtools.RemoteSpringApplication ,其classpath与你所连接的远程项目相同。 该应用程序的唯一必要参数是它所连接的远程URL。
例如,如果你使用的是 Eclipse 或 Spring Tools,并且你有一个名为 my-app 的项目,并已将其部署到 Cloud Foundry,你可以执行以下操作。
- 从 Run 菜单中选择 Run Configurations…。
- 创建一个新的 Java Application “launch configuration”。
- 浏览 my-app 项目。
- 使用 org.springframework.boot.devtools.RemoteSpringApplication 作为main类。
- 在 Program arguments 中添加 https://myapp.cfapps.io(或者你的远程URL)。
一个正在运行的远程客户端可能类似于如下。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: (v3.2.0-SNAPSHOT)
2023-06-26T13:23:55.928+08:00 INFO 12660 --- [ main] o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication v3.2.0-SNAPSHOT using Java 17 with PID 12660 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/3.2.0-SNAPSHOT/spring-boot-devtools-3.2.0-SNAPSHOT.jar started by myuser in /opt/apps/)
2023-06-26T13:23:55.935+08:00 INFO 12660 --- [ main] o.s.b.devtools.RemoteSpringApplication : No active profile set, falling back to 1 default profile: "default"
2023-06-26T13:23:56.300+08:00 INFO 12660 --- [ main] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2023-06-26T13:23:56.333+08:00 INFO 12660 --- [ main] o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 0.978 seconds (process running for 1.753)
因为远程客户端使用的是与真实应用程序相同的classpath,它可以直接读取应用程序属性。 spring.devtools.remote.secret 属性就是这样被读取并传递给服务器进行验证的。 |
始终建议使用 https:// 作为连接协议,这样流量会被加密,密码也不会被截获。 |
如果你需要使用代理来访问远程应用程序,可以配置 spring.devtools.remote.proxy.host 和 spring.devtools.remote.proxy.port 属性。 |
8.6.2. 远程更新
远程客户端以与本地 restart相同的方式监控你的应用程序classpath的变化。任何更新的资源都会被推送到远程应用程序,并(如果需要)触发重启。如果你在一个云服务上进行功能迭代,而你在本地没有云服务,这可能会很有帮助。一般来说,远程更新和重启要比完整的重建和部署周期快得多。
在一个较慢的开发环境中,可能会发生“等待时间”不够的情况,类的变化可能被分成几批。 在第一批类的变化被上传后,服务器被重新启动。 下一批则不能被发送到应用程序,因为服务器正在重启。
这通常表现为 RemoteSpringApplication 日志中的警告,即未能上传一些类,并随之重试。 但它也可能导致应用程序代码不一致,以及在第一批修改上传后无法重新启动。 如果你经常观察到这样的问题,可以尝试增加 spring.devtools.restart.poll-interval 和 spring.devtools.restart.quiet-period 参数到适合你开发环境的值。 参见"配置文件系统监听器"一节,以配置这些属性。
文件只在远程客户端运行时被监控。 如果你在启动远程客户端之前改变了一个文件,它不会被推送到远程服务器上。 |
9. 打包应用,部署到生产环境
可执行jar可以用于生产环境,由于它们是独立的,非常适合部署到云服务中。