我有下面的NodeJS代码:
// req and resp are http request, response objects
var uri = req.getURI()
var pageView = new PageView(uri)
var token = req.token
if (token) {
UserRepository.findByToken(token, function(notFound, user){
if(notFound) { // means user not found by specified token
var newUser = new User('John Doe')
user.foo = 'some value'
processUser(newUser, pageView)
} else { // user found by token
user.foo = 'some value'
processUser(user, pageView)
}
})
} else { // token does not exist
token = new Token('some value')
resp.setToken(token)
var newUser = new User('John Doe')
user.foo = 'some value'
processUser(newUser, pageView)
}
processUser(user, pageView) {
PageViewRepositiry.save(pageView, function(error, savedPageView){
if(error) {
throw 'error'
}
user.pageViews.push(savedPageView)
// save the modified savedUser
UserRepository.save(user , function(error, savedUser){
})
})
}
它使用存储库模式作为数据库层的抽象(与Spring应用程序中的存储库模式相同)。 基本上,它通过传入令牌(从http req对象)找到用户。如果找到用户,则更新用户实体并添加保存的pageView实体并保存修改后的用户。如果没有通过令牌找到用户,则它将创建一个新用户,并使用保存的pageView更新该用户,然后保存该用户。
如何在Spring Project Reactor(Flux)中编写相同的代码?
是否可以在不使用block()的情况下解决此问题?理想情况下,我想要一个不使用block()的解决方案。
答案 0 :(得分:2)
首先,如果不存在令牌,则有一些逻辑可以生成令牌。例如:
private Mono<String> getToken(String token) {
return Mono
.just(token)
.switchIfEmpty(Mono.just("some token"));
}
在这种情况下,使用switchIfEmpty
可能有点过头,但是我认为您生成令牌的过程要复杂一些,否则您可以使用Optional<String>
代替(例如token.orElse("some token")
)。
此外,我们还有一些逻辑,可以按其令牌查找用户,或者如果给定令牌中没有用户,则创建一个新用户:
private Mono<User> findUserByToken(String token) {
return userRepository
.findByToken(token)
.switchIfEmpty(userRepository.save(new User("John Doe", token)));
}
现在有了这些方法,我们可以创建一个PageView
并一路使用这些方法。我开始创建PageView
的原因是,这是整个令牌中的第一个“常量”,无论是否找到令牌/用户:
return Mono
.just(new PageView(uri))
.flatMap(pageViewRepository::save)
.flatMap(pageView -> getToken(token)
.flatMap(this::findUserByToken)
.doOnNext(user -> user.setFoo("foo"))
.doOnNext(user -> user.getPageView().add(pageView)))
.flatMap(userRepository::save)
.map(User::getToken);
现在,由于您需要将令牌添加到响应中,并且我发现令牌以某种方式属于User
对象的一部分(否则UserRepository.findByToken()
无效?),它将只需在末尾使用User::getToken
来获取令牌以传递给响应,就更容易了。
但是请注意,存储库模式在Spring上可以正常使用,但是仅对MongoDB,Cassandra,Couchbase和Redis提供响应式支持。除此之外,rdbc还对PostgreSQL提供了响应式支持,但我不认为Spring数据对此提供支持。