Micronaut Kotlin 支持
Micronaut 的命令行界面包括对 Kotlin 的特殊支持。要创建 Kotlin 应用程序,请使用 kotlin lang 选项。例如:
创建 Micronaut Kotlin 应用程序
$ mn create-app hello-world --lang kotlin
Micronaut 中对 Kotlin 的支持建立在 Kapt 编译器插件之上,其中包括对 Java 注释处理器的支持。要在您的 Micronaut 应用程序中使用 Kotlin,请添加适当的依赖项以在您的 kt 源文件上配置和运行 kapt。 Kapt 为您的 Kotlin 类创建 Java“存根”类,然后可以由 Micronaut 的 Java 注释处理器进行处理。存根不包含在最终编译的应用程序中。
从官方文档中了解有关 kapt 及其功能的更多信息。
使用 Gradle 时,Micronaut 注释处理器在 kapt 范围内声明。例如:
Example build.gradle
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" (1)
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
kapt "io.micronaut:micronaut-inject-java" (2)
kaptTest "io.micronaut:micronaut-inject-java" (3)
...
}
添加 Kotlin 标准库
在kapt作用域下添加micronaut-inject-java依赖,这样src/main中的类就会被处理
在 kaptTest 范围下添加 micronaut-inject-java 依赖项,以便处理 src/test 中的类。
使用与上面类似的 build.gradle 文件,您现在可以使用运行任务(由 Application 插件提供)来运行您的 Micronaut 应用程序:
$ ./gradlew run
下面是一个用 Kotlin 编写的示例控制器:
src/main/kotlin/example/HelloController.kt
package example
import io.micronaut.http.annotation.*
@Controller("/")
class HelloController {
@Get("/hello/{name}")
fun hello(name: String): String {
return "Hello $name"
}
}
Kotlin, Kapt and IntelliJ
在撰写本文时,IntelliJ 的内置编译器不直接支持 Kapt 和注释处理。在运行测试或应用程序类之前,您必须将 Intellij 配置为运行 Gradle(或 Maven)编译作为构建步骤。
首先,编辑测试或应用程序的运行配置,然后选择“运行 Gradle 任务”作为构建步骤:
然后将类任务添加为应用程序或测试 testClasses 任务执行的任务:
现在,当您运行测试或启动应用程序时,Micronaut 将在编译时生成类。
或者,您可以将 IntelliJ 构建/运行操作完全委托给 Gradle:
使用 Gradle 和 Kapt 进行增量注释处理
要使用 Kapt 启用 Gradle 增量注释处理,必须将在使用 Gradle 进行增量注释处理中指定的参数发送到 Kapt。
以下示例演示了如何为您在 com.example 和 io.example 包下定义的注释启用和配置增量注释处理:
Enabling Incremental Annotation Processing in Kapt
kapt {
arguments {
arg("micronaut.processing.incremental", true)
arg("micronaut.processing.annotations", "com.example.*,io.example.*")
}
}
如果您不为您的自定义注释启用处理,它们将被 Micronaut 忽略,这可能会破坏您的应用程序。
Kotlin 和 AOP 建议
Micronaut 提供了一个不使用反射的编译时 AOP API。当您使用任何 Micronaut AOP Advice 时,它会在编译时创建一个子类来提供 AOP 行为。这可能是个问题,因为 Kotlin 类默认是最终的。如果应用程序是使用 Micronaut CLI 创建的,则 Kotlin 全开放插件已配置为在使用 AOP 注释时自动更改类以打开。要自己配置它,请将 Around 类添加到支持的注释列表中。
如果您不想或不能使用全开放插件,则必须声明使用 AOP 注释注释的类是开放的:
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.HttpStatus
import io.micronaut.validation.Validated
import javax.validation.constraints.NotBlank
@Validated
@Controller("/email")
open class EmailController { (1)
@Get("/send")
fun index(@NotBlank recipient: String, (1)
@NotBlank subject: String): HttpStatus {
return HttpStatus.OK
}
}
如果使用@Validated AOP Advice,则需要在类和方法级别使用open。
全开放插件不处理方法。如果在方法上声明 AOP 注释,则必须手动将其声明为打开。
Kotlin 和保留参数名称
与 Java 一样,使用 Kotlin 时,方法参数的参数名称数据不会在编译时保留。如果您没有显式定义参数名称并依赖于已编译的外部 JAR,这对 Micronaut 来说可能是个问题。
要使用 Kotlin 保留参数名称数据,请在 build.gradle 中将 javaParameters 选项设置为 true:
configuration in Gradle
compileTestKotlin {
kotlinOptions {
jvmTarget = '1.8'
javaParameters = true
}
}
如果您使用带有默认方法的接口,请添加 freeCompilerArgs = ["-Xjvm-default=all"] 以便 Micronaut 识别它们。
或者,如果使用 Maven,则相应地配置 Micronaut Maven 插件:
configuration in Maven
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- ... -->
<build>
<plugins>
<!-- ... -->
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<configuration>
<javaParameters>true</javaParameters>
<!-- ... -->
</configuration>
<!-- ... -->
</plugin>
<!-- ... -->
</plugins>
</build>
</project>
协程支持
Kotlin 协程允许您使用命令式代码创建异步应用程序。一个 Micronaut 控制器动作可以是一个挂起函数:
该函数被标记为挂起,但实际上它不会被挂起。
该函数被标记为挂起。
调用延迟以确保挂起函数并从不同的线程返回响应。
当我们只想返回一个状态时,suspend 函数也可以工作。
您还可以将 Flow 类型用于流式传输服务器和客户端。流式控制器可以返回 Flow,例如:
定义了生成 application/x-json-stream 的方法 streamHeadlinesWithFlow
Flow是使用flow创建的
此流发出 100 条消息
使用 emit suspend 函数进行发射
消息之间有一秒的延迟
流媒体客户端可以简单地返回一个 Flow,例如:
@Get 方法定义为处理 APPLICATION_JSON_STREAM 类型的响应
返回类型是 Flow
协程跟踪上下文传播
Micronaut支持跟踪上下文的传播。如果你从控制器动作一直到所有的服务都使用挂起函数,你不需要做任何特别的事情。然而,当你在一个普通的函数中创建了coroutines时,跟踪传播不会自动发生。你必须使用HttpCoroutineContextFactory<CoroutineTracingDispatcher>来创建一个新的CoroutineTracingDispatcher并将其作为CoroutineContext使用。
下面的例子显示了这可能是什么样子的。
@Controller
class SimpleController(
private val coroutineTracingDispatcherFactory: HttpCoroutineContextFactory<CoroutineTracingDispatcher>
) {
@Get("/runParallelly")
fun runParallelly(): String = runBlocking {
val a = async(Dispatchers.Default + coroutineTracingDispatcherFactory.create()) {
val traceId = MDC.get("traceId")
println("$traceId: Calculating sth...")
calculateSth()
}
val b = async(Dispatchers.Default + coroutineTracingDispatcherFactory.create()) {
val traceId = MDC.get("traceId")
println("$traceId: Calculating sth else...")
calculateSthElse()
}
a.await() + b.await()
}
}
反应性上下文传播
Micronaut 支持从 Reactor 上下文到协程上下文的上下文传播。要启用此传播,您需要包含以下依赖项:
Gradle | Maven |
|
|
有关如何使用该库的更多详细信息,您可以在官方文档中找到。
以下示例显示了如何将 Reactor 上下文从 HTTP 过滤器传播到控制器的协程:
通过从协程上下文中检索 ReactorContext 来访问 Reactor 上下文:
可以使用协程 Reactor 集成来使用挂起函数创建过滤器:
更多建议: