Spring Mono<User> 作为构造函数参数 - 如何 "cache" 对象

Spring Mono<User> as constructor param - how to "cache" object

我对如何使用 Spring Boot 在项目反应堆中执行此操作一无所知:

class BakerUserDetails(val bakerUser: Mono<BakerUser>): UserDetails {
    override fun getPassword(): String {
        TODO("Not yet implemented")
        // return ???.password
    }

    override fun getUsername(): String {
        TODO("Not yet implemented")
        // return ???.username
    }

}

我该如何进行这项工作?我是只放 bakerUser.block().passwordbakerUser.block().username 以及所有这些方法,还是有更好的方法来实现这些方法?

目前,我正在做这样的事情,但看起来很奇怪:

    private var _user: BakerUser? = null
    private var user: BakerUser? = null
    get() {
        if(_user == null){
            _user = bakerUser.block()
        }
        return _user
    }

override fun getAuthorities(): MutableCollection<out GrantedAuthority> {
        return mutableSetOf(SimpleGrantedAuthority("USER"))
    }

    override fun getPassword(): String {
        return user!!.password!!
    }

我不太精通 Kotlin,但我可以告诉你,你不应该将 Mono 传递给 UserDetails 对象。

A Mono<T> 有点像 future/promise。这意味着里面什么都没有。所以如果你想从中得到一些东西,你可以 block 这意味着我们等待,直到里面有东西,或者我们订阅,这基本上意味着我们等待 async 直到里面有东西。这可能很糟糕。把它想象成兼职工作。如果您开始一项工作并退出程序会发生什么,那么该工作将不会执行。

或者你做了一些线程化的事情,然后程序 returns/exits,主线程死了,所有线程都死了,什么也没发生。

我们通常在反应世界中谈论 PublishersConsumers。所以 Flux/MonoPublisher 然后你声明一个 pipeline 来说明解决问题时会发生什么。并启动 consumer 需要 subscribeproducer 的过程。

通常在服务器世界中,这意味着发出请求的网页是 consumer 并且它 subscribes 到服务器,在这种情况下是 publisher .

所以我要说的是,您几乎不应该 subscribe 在您的应用程序中,除非您的应用程序是启动消费的应用程序。例如,您的服务器中有一个 cron 作业会占用另一台服务器等。

让我们看看你的问题:

您还没有发布您的代码,所以我要在这里做一些猜测,但我猜您是从数据库中获取用户。

public Mono<BakerUserDetails> loadUserByUsername(String username) {

    Mono<user> user = userRepository.findByUsername(username);
    // Here we declare our pipline, flatMap will map one object to another async
    Mono<BakerUserDetails> bakerUser = user.flatMap(user -> Mono.just(new BakerUserDetails(user));
    return bakerUser;
}

我在没有编译器的情况下写了这篇文章。

所以不要传入 Mono<T> 使用不同的运算符(例如 mapflatMap 等进行转换。除非您的服务器是最终消费者,否则不要订阅您的应用程序。