当前位置: 首页 > 知识库问答 >
问题:

使用Kotlin Coroutines的Spring Boot Rest服务

鱼意远
2023-03-14

我在Kotlin写一个Spring引导Rest服务。我想使用coroutines作为Webflux的替代方案来实现非阻塞异步行为。我正在使用Spring Boot2.1,并且知道我无法实现真正的非阻塞行为,因为我正在controller处阻塞。然而,在Spring Boot2.2普遍可用之前,我现在对此没有意见。

我的应用是三层ie控制器->服务->存储库。在repository中,我正在调用其他服务(即网络调用),并已将该方法标记为Suspend。

我想确保这是正确的方法,另外,调用在resourceService中挂起fun是否会阻塞调用方线程?

此外,在阅读了Roman Elizarov的https://medium.com/@Elizarov/blocking-threads-suspending-coroutines-d33e11bf4761之后,我不确定是否应该使用withcontext以及所有的挂起函数?

package my.springbootapp

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import mu.KotlinLogging
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RestController
import java.util.concurrent.Executors

val logger = KotlinLogging.logger { }

@SpringBootApplication
class App

fun main(args: Array<String>) {
    SpringApplication.run(App::class.java, *args)
}

@RestController
class Controller(private val resourceService: ResourceService) {
    private val dispatcher = Executors.newFixedThreadPool(5).asCoroutineDispatcher()

    @GetMapping("/resource/{id}")
    fun getResource(@PathVariable("id") id: String) = runBlocking(dispatcher) {
        resourceService.get(id).also { logger.info { Thread.currentThread().name + "Returning $it" } }
    }
}

@Service
class ResourceService(private val networkResourceRepository: NetworkResourceRepository) {

    suspend fun get(id: String): Resource {
        logger.info { Thread.currentThread().name + "Getting resource" }
        return networkResourceRepository.get(id)
    }
}

@Repository
class NetworkResourceRepository {
    suspend fun get(id: String): Resource = withContext(Dispatchers.IO) {
        logger.info { Thread.currentThread().name + "Getting resource from n/w" }
        //IO operation
        Resource("resource data")
    }
}

data class Resource(val data: String)

共有1个答案

蒋高杰
2023-03-14

我认为你应该使用coroutines与WebFlux但不是代替WebFlux。要将WebFlux与coroutines一起使用,必须添加WebFlux包装器,使WebFlux可挂起。webflux+coroutine示例本身coroutines不会使您的代码不阻塞,coroutines的目标是它们可以只是挂起。这个包装器只是调用webclient上的一些areyoufinished方法(例如),如果它还没有完成,那么coroutine将挂起,并且它将在将来尝试调用相同的方法(通过在将来的执行中传递未到达的代码)。

 类似资料:
  • 我正在开发一个REST API,使用Spring Boot启动数据Rest。我想与JPA同步的一个类是User类,其中包含有关用户的信息,包括谁被允许访问API。 不幸的是,拥有用户和UserRepository意味着我的用户类在API中公开。我能够删除Id(在configureRepositoryRestConfiguration函数中)、用户名和密码(通过向我的用户类的每个变量添加@JsonI

  • 我有在openshift中运行的springboot和非springboot(Eclipse Microprofile)Rest API。两者都有服务endpoint端口9443 SpringBoot度量路径-/actuator/Prometheus Eclipse micro profile度量路径/度量 Eclipse微配置文件抓取配置 Spring靴刮擦配置 由于MP指标在springboo

  • 我的项目需求是使用SOAP服务,为此我尝试使用Quarkus。我会用什么Quarkusdependecies来解决这个问题?有什么示例应用程序我可以参考吗? 在Spring中,我们可以使用org.springframework.ws.client.core.support.webserviceGateWaysupport在Quarkus中有类似的东西吗。

  • 使用启用的虚拟服务器 创建和创建虚拟服务器尚未使用它。 我们必须明确地将其指定为virtual_server指令的值。

  • 我目前正在开发一个PHP应用程序,它将使用websockets进行客户机-服务器通信。我多次听说PHP不应该用于服务器应用程序,因为缺乏线程机制、内存管理(循环引用)或不方便的套接字库。 到目前为止,一切都工作得相当好。我使用phpws作为websocket库和DBAL来访问不同的数据库系统;PHP版本是5.3.8。服务器最多可服务30个客户端。然而,特别是在最近几天,我读了几篇文章,指出PHP对

  • 部署web服务器首先要创建一个 请求处理器(request handler)。 请求处理器可以是协程方法也可以是普通方法,它只有一个用于接受Request实例对象的参数,之后会返回Response实例对象: from aiohttp import web async def hello(request): return web.Response(text="Hello, world")

  • 问题内容: 我们有一个配置了SSL的网站,可托管WCF服务。服务的绑定具有,并且通信使用JSON序列化。 当我们从http请求此服务时,它返回JSONP,但是当使用HTTPS请求该服务时,它仅返回JSON。无论哪种方式我都需要JSONP,请帮忙。 当前配置是这样的: 问题答案: 如果使用此配置会发生什么: 问题是,如果要同时通过HTTP和HTTPS调用服务,则必须提供两个端点-一个端点用于HTTP

  • 我正在做一个社交媒体应用程序(目前是移动的,不久也会是网络的),它专注于视频。我有两个问题: 1)从android应用程序中,我当前的设计从web服务请求新的提要-->服务器用包括视频url和其他提要数据(内容、日期等)的json数据来响应-->然后我为请求视频的VideoView设置url。现在难道没有更好的方法让我用一个请求获取完整的提要(用一个请求返回数据和视频/音频/图像)吗? 在网上调查