如何在 Controller 方法中创建协程以调用挂起函数
how create a coroutine inside a Controller method in order to call a suspend function
目标:我的微服务必须使用另一个 Rest 端点,我正在尝试遵循 Coroutines (Async)。
这是我在服务中编码以使用另一个休息端点的方式
服务
suspend fun getCoroutine(){
val someData = getData()
print(someData)
}
suspend fun getData(): String {
val client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.authenticator(Authenticator.getDefault())
.build();
val request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:3000/employees"))
.build();
val response = client.sendAsync(request, BodyHandlers.ofString());
return response.get().body() // suspend and return String not a Future
}
我想从我的控制器调用“suspend fun getCoroutine()”方法
package com.tolearn.endpoint
import com.tolearn.DemoGrpcKafkaReply
import com.tolearn.DemoGrpcKafkaRequest
import com.tolearn.DemoGrpcKafkaServiceGrpc
import com.tolearn.service.DemoService
import io.grpc.stub.StreamObserver
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class DemoEndpoint : DemoGrpcKafkaServiceGrpc.DemoGrpcKafkaServiceImplBase(){
@Inject
lateinit var demoService: DemoService
override fun send(request: DemoGrpcKafkaRequest?, responseObserver: StreamObserver<DemoGrpcKafkaReply>?) {
demoService.getCoroutine()
}
}
我是协程的新手。我了解到挂起函数只能从另一个挂起函数或协程中调用,所以在我的例子中,我想创建一个协程。谷歌搜索后我尝试了
override fun send(request: DemoGrpcKafkaRequest?, responseObserver: StreamObserver<DemoGrpcKafkaReply>?) {
val tryingCoroutine = runBlocking { demoService.getCoroutine() }
但是无法解决runBlocking
我也试过基于docs reference也是lauch无法解决
override fun send(request: DemoGrpcKafkaRequest?, responseObserver: StreamObserver<DemoGrpcKafkaReply>?) {
launch( demoService.getCoroutine() ) { // not confined -- will work with main thread
}
这里是build.gradle
plugins {
id("org.jetbrains.kotlin.jvm") version "1.4.10"
id("org.jetbrains.kotlin.kapt") version "1.4.10"
id("org.jetbrains.kotlin.plugin.allopen") version "1.4.10"
id("com.github.johnrengelman.shadow") version "6.1.0"
id("io.micronaut.application") version "1.2.0"
id("com.google.protobuf") version "0.8.13"
}
version = "0.1"
group = "com.tolearn"
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
micronaut {
testRuntime("junit5")
processing {
incremental(true)
annotations("com.tolearn.*")
}
}
dependencies {
implementation("io.micronaut:micronaut-validation")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
implementation("io.micronaut.kotlin:micronaut-kotlin-runtime")
implementation("io.micronaut:micronaut-runtime")
implementation("io.micronaut.grpc:micronaut-grpc-runtime")
implementation("javax.annotation:javax.annotation-api")
implementation("io.micronaut.kafka:micronaut-kafka")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:'1.4.2")
runtimeOnly("ch.qos.logback:logback-classic")
runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin")
testImplementation("io.micronaut:micronaut-http-client")
}
application {
mainClass.set("com.tolearn.ApplicationKt")
}
java {
sourceCompatibility = JavaVersion.toVersion("11")
}
tasks {
compileKotlin {
kotlinOptions {
jvmTarget = "11"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "11"
}
}
}
sourceSets {
main {
java {
srcDirs("build/generated/source/proto/main/grpc")
//srcDirs 'build/generated/source/proto/main/grpckt'
srcDirs("build/generated/source/proto/main/java")
}
}
}
protobuf {
protoc { artifact = "com.google.protobuf:protoc:3.14.0" }
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.33.1" }
//grpckt { artifact = "io.grpc:protoc-gen-grpc-kotlin:1.0.0" }
}
generateProtoTasks {
all()*.plugins {
grpc {}
//grpckt {}
}
}
}
主要问题:我需要做什么才能从我的控制器方法中调用挂起函数?第二个问题,我是否在尝试从 Controller 方法调用挂起函数?在这种情况下,我尝试利用协程是不是错了?
*** 编辑 1
val tryingCoroutine = runBlocking {
coroutineScope { // Creates a coroutine scope
launch {
demoService.getCoroutine()
println("Task from nested launch")
}
}
}
println(tryingCoroutine.isCompleted)
您需要添加 kotlinx-coroutines-core
依赖项来解析作用域 (runBlocking/launch)。
这里是 link 到 maven 仓库:
https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core
将范围添加到项目后,您应该能够 运行 在非暂停 block.Also 中暂停功能,您可以使用 CoroutineExceptionHandler
来处理错误。
https://kotlinlang.org/docs/reference/coroutines/exception-handling.html#coroutineexceptionhandler
从技术上讲,控制器应该将任何长运行宁操作移交给另一个线程,并return适当的响应。所以你在做任何奇怪的事情。
目标:我的微服务必须使用另一个 Rest 端点,我正在尝试遵循 Coroutines (Async)。
这是我在服务中编码以使用另一个休息端点的方式
服务
suspend fun getCoroutine(){
val someData = getData()
print(someData)
}
suspend fun getData(): String {
val client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.authenticator(Authenticator.getDefault())
.build();
val request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:3000/employees"))
.build();
val response = client.sendAsync(request, BodyHandlers.ofString());
return response.get().body() // suspend and return String not a Future
}
我想从我的控制器调用“suspend fun getCoroutine()”方法
package com.tolearn.endpoint
import com.tolearn.DemoGrpcKafkaReply
import com.tolearn.DemoGrpcKafkaRequest
import com.tolearn.DemoGrpcKafkaServiceGrpc
import com.tolearn.service.DemoService
import io.grpc.stub.StreamObserver
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class DemoEndpoint : DemoGrpcKafkaServiceGrpc.DemoGrpcKafkaServiceImplBase(){
@Inject
lateinit var demoService: DemoService
override fun send(request: DemoGrpcKafkaRequest?, responseObserver: StreamObserver<DemoGrpcKafkaReply>?) {
demoService.getCoroutine()
}
}
我是协程的新手。我了解到挂起函数只能从另一个挂起函数或协程中调用,所以在我的例子中,我想创建一个协程。谷歌搜索后我尝试了
override fun send(request: DemoGrpcKafkaRequest?, responseObserver: StreamObserver<DemoGrpcKafkaReply>?) {
val tryingCoroutine = runBlocking { demoService.getCoroutine() }
但是无法解决runBlocking
我也试过基于docs reference也是lauch无法解决
override fun send(request: DemoGrpcKafkaRequest?, responseObserver: StreamObserver<DemoGrpcKafkaReply>?) {
launch( demoService.getCoroutine() ) { // not confined -- will work with main thread
}
这里是build.gradle
plugins {
id("org.jetbrains.kotlin.jvm") version "1.4.10"
id("org.jetbrains.kotlin.kapt") version "1.4.10"
id("org.jetbrains.kotlin.plugin.allopen") version "1.4.10"
id("com.github.johnrengelman.shadow") version "6.1.0"
id("io.micronaut.application") version "1.2.0"
id("com.google.protobuf") version "0.8.13"
}
version = "0.1"
group = "com.tolearn"
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
micronaut {
testRuntime("junit5")
processing {
incremental(true)
annotations("com.tolearn.*")
}
}
dependencies {
implementation("io.micronaut:micronaut-validation")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
implementation("io.micronaut.kotlin:micronaut-kotlin-runtime")
implementation("io.micronaut:micronaut-runtime")
implementation("io.micronaut.grpc:micronaut-grpc-runtime")
implementation("javax.annotation:javax.annotation-api")
implementation("io.micronaut.kafka:micronaut-kafka")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:'1.4.2")
runtimeOnly("ch.qos.logback:logback-classic")
runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin")
testImplementation("io.micronaut:micronaut-http-client")
}
application {
mainClass.set("com.tolearn.ApplicationKt")
}
java {
sourceCompatibility = JavaVersion.toVersion("11")
}
tasks {
compileKotlin {
kotlinOptions {
jvmTarget = "11"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "11"
}
}
}
sourceSets {
main {
java {
srcDirs("build/generated/source/proto/main/grpc")
//srcDirs 'build/generated/source/proto/main/grpckt'
srcDirs("build/generated/source/proto/main/java")
}
}
}
protobuf {
protoc { artifact = "com.google.protobuf:protoc:3.14.0" }
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.33.1" }
//grpckt { artifact = "io.grpc:protoc-gen-grpc-kotlin:1.0.0" }
}
generateProtoTasks {
all()*.plugins {
grpc {}
//grpckt {}
}
}
}
主要问题:我需要做什么才能从我的控制器方法中调用挂起函数?第二个问题,我是否在尝试从 Controller 方法调用挂起函数?在这种情况下,我尝试利用协程是不是错了?
*** 编辑 1
val tryingCoroutine = runBlocking {
coroutineScope { // Creates a coroutine scope
launch {
demoService.getCoroutine()
println("Task from nested launch")
}
}
}
println(tryingCoroutine.isCompleted)
您需要添加 kotlinx-coroutines-core
依赖项来解析作用域 (runBlocking/launch)。
这里是 link 到 maven 仓库: https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core
将范围添加到项目后,您应该能够 运行 在非暂停 block.Also 中暂停功能,您可以使用 CoroutineExceptionHandler
来处理错误。
https://kotlinlang.org/docs/reference/coroutines/exception-handling.html#coroutineexceptionhandler
从技术上讲,控制器应该将任何长运行宁操作移交给另一个线程,并return适当的响应。所以你在做任何奇怪的事情。