Как использовать kotlin сопрограммы с данными реактивной пружины - PullRequest
0 голосов
/ 25 марта 2020

Я пытаюсь перенести какой-то проект из Spring Reactor в kotlin сопрограммы. У меня есть контроллер на основе пружинного webflux, например:

@RestController
class Controller(val productRepository: ProductsRepository) {

    @GetMapping("/product")
    fun find(@RequestParam id: String): Mono<Product> {
        return productRepository.findById(id)
    }
}

Этот контроллер использует хранилище данных реактивной пружины:

@Repository
interface ProductsRepository : ReactiveMongoRepository<Product, String>

Согласно этой официальной документации - https://docs.spring.io/spring/docs/5.2.0.M1/spring-framework-reference/languages.html#how - реактивные-переводы-сопрограммы , моя функция find в контроллере должна быть переведена в suspend fun, и эта функция должна возвращать экземпляр класса Product вместо реактивной моно-оболочки Product. Примерно так:

@RestController
class Controller(val productRepository: ProductsRepository) {

    @GetMapping("/product")
    suspend fun find(@RequestParam id: String): Product {
        return productRepository.findById(id)
    }
}

Но мой репозиторий product имеет дело с Mono и Flux, а не с приостановленными функциями. Как правильно использовать абстракцию данных Spring в этом случае?

1 Ответ

1 голос
/ 25 марта 2020

Этого можно достичь с помощью полезной вспомогательной библиотеки kotlinx-coroutines-reactor, которая предоставляет полезные методы расширений для реакторов проекта Publisher, помогающие конвертировать Mono или Flux в kotlin сопрограммы.

First добавить зависимость от

 <dependency>
     <groupId>org.jetbrains.kotlinx</groupId>
     <artifactId>kotlinx-coroutines-reactor</artifactId>
 </dependency>

(если вы используете spring-boot, вам не нужно указывать версию, поскольку она управляет вами)

Теперь вы можете использовать kotlinx.coroutines.reactive.awaitFirstOrNull для преобразования от Mono<Product> до Product? и «ждите» результата.

@RestController
class Controller(val productRepository: ProductsRepository) {

    @GetMapping("/product")
    suspend fun find(@RequestParam id: String): Product? {
        return productRepository.findById(id).awaitFirstOrNull()
    }
}
...