Application Initialization and Termination
您通常需要在应用程序启动时执行自定义操作,并在应用程序停止时清除所有内容。本指南解释了如何:
-
编写带有 main 方法的 Quarkus 应用程序
-
编写运行任务然后终止的命令模式应用程序
-
在应用程序启动时收到通知
-
通知程序停止
Prerequisites
如要完成本指南,您需要:
-
Roughly 15 minutes
-
An IDE
-
安装了 JDK 17+,已正确配置
JAVA_HOME
-
Apache Maven ${proposed-maven-version}
-
如果你想使用 Quarkus CLI, 则可以选择使用
-
如果你想构建一个本机可执行文件(或如果你使用本机容器构建,则使用 Docker),则可以选择安装 Mandrel 或 GraalVM 以及 configured appropriately
Solution
我们建议您遵循接下来的部分中的说明,按部就班地创建应用程序。然而,您可以直接跳到完成的示例。
克隆 Git 存储库: git clone $${quickstarts-base-url}.git
,或下载 $${quickstarts-base-url}/archive/main.zip[存档]。
解决方案位于 lifecycle-quickstart
directory 中。
Creating the Maven project
首先,我们需要一个新项目。使用以下命令创建一个新项目:
quarkus create app {create-app-group-id}:{create-app-artifact-id} \
--no-code
cd {create-app-artifact-id}
要创建一个 Gradle 项目,添加 --gradle
或 --gradle-kotlin-dsl
选项。
有关如何安装和使用 Quarkus CLI 的详细信息,请参见 Quarkus CLI 指南。
mvn {quarkus-platform-groupid}:quarkus-maven-plugin:{quarkus-version}:create \
-DprojectGroupId={create-app-group-id} \
-DprojectArtifactId={create-app-artifact-id} \
-DnoCode
cd {create-app-artifact-id}
要创建一个 Gradle 项目,添加 -DbuildTool=gradle
或 -DbuildTool=gradle-kotlin-dsl
选项。
适用于 Windows 用户:
-
如果使用 cmd,(不要使用反斜杠
\
,并将所有内容放在同一行上) -
如果使用 Powershell,将
-D
参数用双引号引起来,例如"-DprojectArtifactId={create-app-artifact-id}"
它生成:
-
the Maven structure
-
针对
native
和jvm
模式的Dockerfile
示例文件 -
the application configuration file
The main method
默认情况下,Quarkus 将自动生成一个主函数,它将引导 Quarkus,然后等待启动时关闭。让我们提供我们自己的主函数:
package com.acme;
import io.quarkus.runtime.annotations.QuarkusMain;
import io.quarkus.runtime.Quarkus;
@QuarkusMain 1
public class Main {
public static void main(String ... args) {
System.out.println("Running main method");
Quarkus.run(args); 2
}
}
1 | 此注释告诉 Quarkus 将此作为主函数使用,除非在配置中覆盖它 |
2 | This launches Quarkus |
此主类将引导 Quarkus 并运行它,直到它停止。这与自动生成的主类没有区别,但优点是您可以直接从 IDE 启动它,而无需运行 Maven 或 Gradle 命令。
不建议在此主函数中执行任何业务逻辑,因为 Quarkus 尚未设置,并且 Quarkus 可能会在不同的 ClassLoader 中运行。如果您想在启动时执行逻辑,请使用如下所述的 io.quarkus.runtime.QuarkusApplication
。
如果我们想在启动时实际执行业务逻辑(或编写完成任务然后退出的应用程序),我们需要向 run 方法提供一个 io.quarkus.runtime.QuarkusApplication
类。在 Quarkus 启动之后,将调用应用程序的 run
方法。当此方法返回时,Quarkus 应用程序将退出。
如果要在启动时执行逻辑,则应该调用 Quarkus.waitForExit()
,此方法将一直等到请求关闭(来自外部信号,例如在按下 Ctrl+C
时或因为某个线程调用了 Quarkus.asyncExit()
时)。
下面是一个类似示例:
package com.acme;
import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
@QuarkusMain
public class Main {
public static void main(String... args) {
Quarkus.run(MyApp.class, args);
}
public static class MyApp implements QuarkusApplication {
@Override
public int run(String... args) throws Exception {
System.out.println("Do startup logic here");
Quarkus.waitForExit();
return 0;
}
}
}
|
Injecting the command line arguments
可以注入命令行中传递的参数:
@Inject
@CommandLineArguments
String[] args;
可以通过具有 quarkus.args
属性的 -D
标志将命令行参数传递给应用程序:
-
For Quarkus dev mode:include::./_includes/devtools/dev-parameters.adoc[]
-
对于跑步者 jar:
java -Dquarkus.args=<cmd-args> -jar target/quarkus-app/quarkus-run.jar
-
对于本机可执行文件:
./target/lifecycle-quickstart-1.0-SNAPSHOT-runner -Dquarkus.args=<cmd-args>
Listening for startup and shutdown events
在 org.acme.lifecycle
包中创建一个名为 AppLifecycleBean
的新类(或选择另一个名称),并复制以下内容:
package org.acme.lifecycle;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
import org.jboss.logging.Logger;
@ApplicationScoped
public class AppLifecycleBean {
private static final Logger LOGGER = Logger.getLogger("ListenerBean");
void onStart(@Observes StartupEvent ev) { (1)
LOGGER.info("The application is starting...");
}
void onStop(@Observes ShutdownEvent ev) { (2)
LOGGER.info("The application is stopping...");
}
}
1 | 应用程序启动时调用的方法 |
2 | 应用程序终止时调用的方法 |
重新部署的每个事件中也会调用 dev mode 事件。 |
这些方法可以访问注入的 Bean。有关详细信息,请查看 AppLifecycleBean.java 类。 |
What is the difference from @Initialized(ApplicationScoped.class)
and @Destroyed(ApplicationScoped.class)
在 JVM 模式下,除了始终通过 after @Initialized(ApplicationScoped.class)
事件触发 StartupEvent
事件,而 ShutdownEvent
事件通过 before @Destroyed(ApplicationScoped.class)
事件触发外,没有真正的区别。但是,对于一个本地可执行版本,@Initialized(ApplicationScoped.class)
事件作为 part of the native build process 事件触发,而 StartupEvent
事件在执行本地镜像时触发。有关更多详细信息,请参阅 Three Phases of Bootstrap and Quarkus Philosophy。
在 CDI 应用程序中,当应用程序上下文初始化后,会触发带限定符 |
Using @Startup
to initialize a CDI bean at application startup
用 @Startup
注释表示的类、创建者方法或字段的 Bean 在应用程序启动时进行初始化:
package org.acme.lifecycle;
import io.quarkus.runtime.Startup;
import jakarta.enterprise.context.ApplicationScoped;
@Startup (1)
@ApplicationScoped
public class EagerAppBean {
private final String name;
EagerAppBean(NameGenerator generator) { (2)
this.name = generator.createName();
}
}
1 | 对于用 @Startup 注释的每个 Bean,都会生成一个 StartupEvent 的综合观察者。会使用默认优先级。 |
2 | 当应用程序启动时,会调用 Bean 构造函数,并将生成的上下文实例存储在应用程序上下文中。 |
|
如果类用 |
@Startup
注释也可以声明在一个非静态非创建者无参数方法上:
package org.acme.lifecycle;
import io.quarkus.runtime.Startup;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class EagerAppBean {
@Startup
void init() { 1
doSomeCoolInit();
}
}
1 | 此 Bean 在应用程序启动时创建,且 init() 方法在上下文实例上调用。 |
Using @Shutdown
to execute a business method of a CDI bean during application shutdown
@io.quarkus.runtime.Shutdown
注释用于标记一个 CDI Bean 的业务方法,该方法应该在应用程序关闭期间执行。带注释的方法必须为非私有且非静态,且不声明参数。此行为与声明一个 ShutdownEvent
观察者类似。以下示例在功能上是等效的。
import io.quarkus.runtime.Shutdown;
import io.quarkus.runtime.ShutdownEvent;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
class Bean1 {
void onShutdown(@Observes ShutdownEvent event) {
// place the logic here
}
}
@ApplicationScoped
class Bean2 {
@Shutdown
void shutdown() {
// place the logic here
}
}
Package and run the application
使用以下内容运行应用程序:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
会打印日志消息。当应用程序停止时,会打印第二个日志消息。
和往常一样,可以使用以下命令打包应用程序:
quarkus build
./mvnw install
./gradlew build
并使用 java -jar target/quarkus-app/quarkus-run.jar
执行。
您也可以使用以下操作生成本机可执行文件:
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.native.enabled=true
Launch Modes
Quarkus 有 3 种不同的启动模式,NORMAL
(即生产)、DEVELOPMENT
和 TEST
。如果您正在运行 quarkus:dev
,则模式将为 DEVELOPMENT
;如果您正在运行 JUnit 测试,则模式将为 TEST
;否则将为 NORMAL
。
您的应用程序可以通过将 io.quarkus.runtime.LaunchMode
枚举注入到 CDI Bean 中,或通过调用静态方法 io.quarkus.runtime.LaunchMode.current()
,来获取启动模式。
Graceful Shutdown
Quarkus 包括对平稳关机的支持,这允许 Quarkus 等待运行请求完成,直到设定超时。默认情况下,此功能处于禁用状态,但是,您可以通过设置 quarkus.shutdown.timeout
配置属性来配置此功能。当设置此属性后,关机不会在以下时间发生:所有运行的请求都已完成或此超时已过时。
接受请求的扩展需要一个个添加对此功能的支持。现在,仅 HTTP 扩展支持此功能,因此当消息请求处于活动状态时仍可能发生关机。
Quarkus 支持延迟时间,在此延迟期间应用程序实例仍对请求做出响应,但就绪探查失败。这可以给基础设施时间来识别实例正在关闭并停止向实例路由流量。通过将编译时属性 quarkus.shutdown.delay-enabled
设置为 true
,可以启用此功能。然后,可以通过设置运行时属性 quarkus.shutdown.delay
来配置延迟。默认情况下未设置此属性,因此不应用延迟。
要编写持续时间值,需使用标准格式
在其他情况下,简化格式会转换为
|