Spring webflux 中的异常处理
Exception Handling in Spring webflux
我正在使用反应流开发一个 Spring webflux 项目。我有一个如下的用例,想知道如何以反应方式完成它。
@RestController
public class Example {
@GetMapping("/greet")
public Mono<String> Test() {
return Mono.just("Tim")
.map(s -> s.toUpperCase())
.map(s -> s.toLowerCase())
.doOnSuccess(s -> validate(s)) // usecase is to validate here in middle of the pipeline
.onErrorResume(ex -> Mono.just("Guest"))
.map(s -> "Hi, "+s);
}
public void validate(String s) {
if(s.length() < 5) {throw new RuntimeException("Name is short");}
}
}
我知道这是一个人为的例子,但我有类似的东西。我认为在命中端点时抛出错误会导致浏览器屏幕出现异常。但令我惊讶的是它转到 onErrorResume()
并且我得到了 Hi, Guest
作为响应。我想当throw
用于在反应管道组装之前抛出异常时,它不会使用onErrorResume()
。我在这里错过了什么?
还有问题 #2,如果我使用 Mono.error(new RuntimeException("Name is short"))
而不是 throw new RuntimeException("Name is short")
,我该如何实现?有人可以回答我的两个问题吗?欢迎提出改进代码的建议。
对于第 1 个问题,您可以在 onErrorResume
中添加谓词
.onErrorResume(e -> !(e instanceof RuntimeException), ex -> Mono.just("Guest"))
这样您就可以过滤出您可以 return 预定义结果的错误。
对于问题 #2,您可以将消费者 doOnSuccess
替换为 flatMap
和 return Mono
for validate
方法:
public Mono<String> Test() {
return Mono.just("Tim")
.map(s -> s.toUpperCase())
.map(s -> s.toLowerCase())
.flatMap(s -> validate(s))
.onErrorResume(e -> !(e instanceof RuntimeException), ex -> Mono.just("Guest"))
.map(s -> "Hi, " + s);
}
public Mono<String> validate(String s) {
return (s.length() < 5) ?
Mono.error(() -> new RuntimeException("Name is short")) :
Mono.just(s);
}
I thought when throw is used to throw an exception before the reactive
pipeline is assembled, it will not use onErrorResume()
Mono::doOnSuccess
在 执行时间 当 Mono
成功完成(管道已经组装)时触发。
请注意,在 doOnNext
或 map
等中间运算符中,您可以自由抛出异常,因为 Reactor 可以将它们转换为正确的错误信号,因为此时 Mono
已经在进步。
how can I achieve this if I'm using Mono.error(new
RuntimeException("Name is short")) instead of throw new
RuntimeException("Name is short")?
您可以将 doOnSuccess
和 map
替换为 handle
运算符:
return Mono.just("Tim")
.handle((name, sink) -> {
if(name.length() < 5){
sink.error(new RuntimeException("Name is short"));
} else {
sink.next(name.toLowerCase());
}
})
我正在使用反应流开发一个 Spring webflux 项目。我有一个如下的用例,想知道如何以反应方式完成它。
@RestController
public class Example {
@GetMapping("/greet")
public Mono<String> Test() {
return Mono.just("Tim")
.map(s -> s.toUpperCase())
.map(s -> s.toLowerCase())
.doOnSuccess(s -> validate(s)) // usecase is to validate here in middle of the pipeline
.onErrorResume(ex -> Mono.just("Guest"))
.map(s -> "Hi, "+s);
}
public void validate(String s) {
if(s.length() < 5) {throw new RuntimeException("Name is short");}
}
}
我知道这是一个人为的例子,但我有类似的东西。我认为在命中端点时抛出错误会导致浏览器屏幕出现异常。但令我惊讶的是它转到 onErrorResume()
并且我得到了 Hi, Guest
作为响应。我想当throw
用于在反应管道组装之前抛出异常时,它不会使用onErrorResume()
。我在这里错过了什么?
还有问题 #2,如果我使用 Mono.error(new RuntimeException("Name is short"))
而不是 throw new RuntimeException("Name is short")
,我该如何实现?有人可以回答我的两个问题吗?欢迎提出改进代码的建议。
对于第 1 个问题,您可以在 onErrorResume
.onErrorResume(e -> !(e instanceof RuntimeException), ex -> Mono.just("Guest"))
这样您就可以过滤出您可以 return 预定义结果的错误。
对于问题 #2,您可以将消费者 doOnSuccess
替换为 flatMap
和 return Mono
for validate
方法:
public Mono<String> Test() {
return Mono.just("Tim")
.map(s -> s.toUpperCase())
.map(s -> s.toLowerCase())
.flatMap(s -> validate(s))
.onErrorResume(e -> !(e instanceof RuntimeException), ex -> Mono.just("Guest"))
.map(s -> "Hi, " + s);
}
public Mono<String> validate(String s) {
return (s.length() < 5) ?
Mono.error(() -> new RuntimeException("Name is short")) :
Mono.just(s);
}
I thought when throw is used to throw an exception before the reactive pipeline is assembled, it will not use onErrorResume()
Mono::doOnSuccess
在 执行时间 当 Mono
成功完成(管道已经组装)时触发。
请注意,在 doOnNext
或 map
等中间运算符中,您可以自由抛出异常,因为 Reactor 可以将它们转换为正确的错误信号,因为此时 Mono
已经在进步。
how can I achieve this if I'm using Mono.error(new RuntimeException("Name is short")) instead of throw new RuntimeException("Name is short")?
您可以将 doOnSuccess
和 map
替换为 handle
运算符:
return Mono.just("Tim")
.handle((name, sink) -> {
if(name.length() < 5){
sink.error(new RuntimeException("Name is short"));
} else {
sink.next(name.toLowerCase());
}
})