我正在Kotlin中编写Spring Boot Rest Service。我想使用协程作为Webflux的替代方案,以实现非阻塞异步行为。我正在使用Spring Boot 2.1,并且知道我无法实现真正的非阻塞行为,因为我在Controller
处进行了阻塞。但是,我可以接受,直到Spring Boot 2.2普遍可用为止。
我的应用程序是三层的,即Controller-> Service-> Repository。在存储库中,我正在调用其他服务,即网络调用,并将该方法标记为“暂停”。
我想确保这是正确的方法,此外,调用ResourceService
内的暂停乐趣会阻塞调用线程吗?
还在阅读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)
答案 0 :(得分:0)
您是否检查了how to use co-routines上的新文档?
您感兴趣的是带有@Controller的类支持以下内容:
所以我认为您可以使用暂停
final Reader in = new FileReader("counties.csv");
final Iterable<CSVRecord> records = CSVFormat.DEFAULT.parse(in);
for (final CSVRecord record : records) { // Simply iterate over the records via foreach loop. All the parsing is handler for you
String populationString = record.get(7); // Indexes are zero-based
String populationString = record.get("population"); // Or, if your file has headers, you can just use them
… // Do whatever you want with the population
}
答案 1 :(得分:0)
我认为您应该将协程与WebFlux一起使用,但不能代替WebFlux。要将WebFlux与协程一起使用,必须添加WebFlux-Wrapper,这会使WebFlux可挂起。 WebFlux+Coroutine example
协程本身不会使您的代码无阻塞,协程的目标是它们只能暂停。该包装器仅在areYouFinished
上调用了某个WebClient
方法(例如),如果尚未完成,协程暂停,它将在将来尝试调用相同的方法(通过在将来执行时传递未到达的代码)。