Log inside Mono.error 输出两次
Log inside Mono.error gets outputted twice
由于某些奇怪的原因,“未找到用户”日志在我的应用程序日志中输出两次,尽管调用了 findUserById只有一次。
我不确定是什么导致了这个问题。
有没有更好的方法来解决这个问题(记录并抛出异常)?
请注意 findById
调用来自 API。
编辑:
似乎只抛出一次异常。此外,如果我将 Mono.error
替换为 Mono.defer
,日志也会打印两次。
public Mono<User> getUser(String id) {
Mono<User> thisIsEmpty = getNoUser(); // Assume that this is empty
return Mono.defer(() -> thisIsEmpty.switchIfEmpty(Mono.defer(() -> findUserById(id))));
}
public Mono<User> findUserById(String id) {
log.info("This is printed once.");
Mono<User> user = repository.findById(id).switchIfEmpty(Mono.error(() -> { // findById is an API call of a library I use
log.error("User not found (this is printed twice)"); // Gets printed twice
throw new UserException(MY_ERROR_CODE, 401);
}));
user.subscribe(User -> ... // Do something if it is not empty
return user;
}
嗯,来自Mono#error docs:
Create a Mono that terminates with an error immediately after being subscribed to. The Throwable is generated by a Supplier, invoked each time there is a subscription and allowing for lazy instantiation.
首先您的订阅在这里:
user.subscribe(User -> ...
而且我假设您有另一个使用 getUser 的代码订阅。
这就是它打印两次的原因。
正如@Eugene 提到的,您的问题是您可能订阅了两次。
如果你想调用它一次,那么你的方法应该被重写
public Mono<User> findUserById(String id) {
log.info("This is printed once.");
return repository.findById(id)
.switchIfEmpty(Mono.error(() -> { // findById is an API call of a library I use
log.error("User not found (this is printed twice)"); // Gets printed twice
throw new UserException(MY_ERROR_CODE, 401);
}))
.flatMap(user-> {
// do smth here
return Mono.just(user);
});
return user;
}
Reactive 有点不同,所以当你 return mono 时,它不会被执行,直到你订阅它(或者阻止你不应该做,直到你必须)。
所以基本上你第一次“执行”时你的情况发生了什么
user.subscribe(User -> ... // Do something if it is not empty
第二次可能是你有控制器,它是 returning mono 并且 spring boot 正在订阅
此外,您在服务订阅中所做的任何事情都不会发送到它之外。您应该为此使用 flatMap 或任何其他 Reactive 运算符。
由于某些奇怪的原因,“未找到用户”日志在我的应用程序日志中输出两次,尽管调用了 findUserById只有一次。 我不确定是什么导致了这个问题。
有没有更好的方法来解决这个问题(记录并抛出异常)?
请注意 findById
调用来自 API。
编辑:
似乎只抛出一次异常。此外,如果我将 Mono.error
替换为 Mono.defer
,日志也会打印两次。
public Mono<User> getUser(String id) {
Mono<User> thisIsEmpty = getNoUser(); // Assume that this is empty
return Mono.defer(() -> thisIsEmpty.switchIfEmpty(Mono.defer(() -> findUserById(id))));
}
public Mono<User> findUserById(String id) {
log.info("This is printed once.");
Mono<User> user = repository.findById(id).switchIfEmpty(Mono.error(() -> { // findById is an API call of a library I use
log.error("User not found (this is printed twice)"); // Gets printed twice
throw new UserException(MY_ERROR_CODE, 401);
}));
user.subscribe(User -> ... // Do something if it is not empty
return user;
}
嗯,来自Mono#error docs:
Create a Mono that terminates with an error immediately after being subscribed to. The Throwable is generated by a Supplier, invoked each time there is a subscription and allowing for lazy instantiation.
首先您的订阅在这里:
user.subscribe(User -> ...
而且我假设您有另一个使用 getUser 的代码订阅。
这就是它打印两次的原因。
正如@Eugene 提到的,您的问题是您可能订阅了两次。
如果你想调用它一次,那么你的方法应该被重写
public Mono<User> findUserById(String id) {
log.info("This is printed once.");
return repository.findById(id)
.switchIfEmpty(Mono.error(() -> { // findById is an API call of a library I use
log.error("User not found (this is printed twice)"); // Gets printed twice
throw new UserException(MY_ERROR_CODE, 401);
}))
.flatMap(user-> {
// do smth here
return Mono.just(user);
});
return user;
}
Reactive 有点不同,所以当你 return mono 时,它不会被执行,直到你订阅它(或者阻止你不应该做,直到你必须)。
所以基本上你第一次“执行”时你的情况发生了什么
user.subscribe(User -> ... // Do something if it is not empty
第二次可能是你有控制器,它是 returning mono 并且 spring boot 正在订阅
此外,您在服务订阅中所做的任何事情都不会发送到它之外。您应该为此使用 flatMap 或任何其他 Reactive 运算符。