我是一个新的项目Reactor和反应编程一般。
我目前正在编写一段类似于以下内容的代码:
Mono.just(userId)
.map(repo::findById)
.map(user-> {
if(user == null){
throw new UserNotFoundException();
}
return user;
})
// ... other mappings
这两种做法有什么实际区别吗?
有几种方法可以被认为是一种方便的异常抛出方式:
可以简化元素处理的方法之一是运算符handle
。
下面的代码展示了如何使用它来解决我们的问题:
Mono.just(userId)
.map(repo::findById)
.handle((user, sink) -> {
if(!isValid(user)){
sink.error(new InvalidUserException());
} else if (isSendable(user))
sink.next(user);
}
else {
//just ignore element
}
})
Mono.just(userId)
.map(repo::findById)
.concatMap(user-> {
if(!isValid(user)){
return Mono.error(new InvalidUserException());
}
return Mono.just(user);
})
Flux.just(userId1, userId2, userId3)
.map(repo::findById)
.concatMap(user-> {
if(!isValid(user)){
return Flux.error(new InvalidUserException());
}
return Mono.just(user);
})
注意!永远不要检查传入元素的可空性。Reactor项目永远不会为您发送null
值,因为这违反了Reactive Streams规范(参见规则2.13)。因此,如果repo.findbyid
返回null,Reactor将为您抛出NullPointerException。
从本质上讲,FlatMap
被设计为从一次执行的多个子流中合并元素。这意味着flatMap下面应该有异步流,所以它们可能处理多个线程上的数据,或者可能是几个网络调用。随后,这样的期望会对实现产生很大的影响,因此FlatMap
应该能够处理来自多个流(Thread
s)的数据(意味着使用并发数据结构),如果另一个流存在耗尽,则可以进入队列元素(意味着为每个子流的Queue
s)分配额外的内存),并且不违反反应流规范规则(意味着真正复杂的实现)。考虑到所有这些事实,以及我们将普通的map
操作(同步)替换为使用flux/mono.error
抛出异常的更方便的方式,我们不需要如此复杂的运算符,我们可以使用更简单的concatmap
,它是为一次异步处理单个流而设计的,并且为了处理标量冷流进行了一些优化。
因此,当结果为空时引发异常的另一种方法是switchifempty
操作符。下面的代码演示了如何使用这种方法:
Mono.just(userId)
.flatMap(repo::findById)
.switchIfEmpty(Mono.error(new UserNotFoundExeception()))
我们可以看到,在本例中,repo::FindByID
应该将User
的mono
作为返回类型。因此,如果找不到User
实例,结果流将为空。因此,Reactor将调用一个替代的mono
,指定为switchifempty
参数。
它可能被认为是可读性较差的代码或糟糕的实践(我自己的观点),但您可以使用Project Reactor按原样抛出异常(例如.map(v->throw...)
)。尽管如此,在某种程度上,这样做可能会违反Reactive Streams规范(在此上下文中,从语义角度来看是违反的,因为您的运算符是订阅者
链中的订阅者
,因此,语义上,在lambda中抛出异常可以映射到在onnext
方法中抛出异常,这违反了规范的规则2.13)。但是,由于Reactor将为您捕获抛出的异常,然后将其作为onerror
信号传播到下游,因此并不禁止这样做。
问题内容: 我是刚接触Reactor和反应式编程的新手。 我目前正在编写类似于以下代码: 这个例子可能很愚蠢,确实有更好的方法来实现这种情况,但是重点是: 在块中使用异常是错误的还是应该将其替换为? 这两种方式有什么实际区别? 问题答案: 有几种方法可以被视为方便的异常抛出方法: 可以简化可能导致错误或空流的元素处理的一种方法是operator 。 以下代码显示了如何使用它来解决问题: 如我们所见
我使用PowerMock(Mockito)模拟同一类中另一个方法的子调用。更具体地说,我有这样的东西: 现在在我的单元测试中,我能够使用间谍模拟MyMethod2的响应,并做一些类似。但是,当我做这样的事情时,会发生一些奇怪的事情:。当我在测试期间调用myClass.myMethod1()时,它会抛出一个NullPointerException,但奇怪的是,如果我使用调试器并检查,e是MyExce
抛出异常的行为是否可能抛出不同的异常? 为了抛出异常,必须(可选地)分配新对象,并调用其构造函数(隐式调用fillinstacktrace)。在某些情况下,听起来像addSupressed也被称为。那么如果没有足够的内存会发生什么呢?JVM是否需要预分配内置异常?例如,(1/0)会抛出OutOfMemoryError而不是ArithmeticException吗? 此外,构造函数是一个方法调用,因
上一节展示了如何为ListOfNumbers类中的writeList方法编写异常处理程序。 有时,它适合代码捕获可能发生在其中的异常。 但在其他情况下,最好让一个方法进一步推给上层来调用堆栈处理异常。 例如,如果您将ListOfNumbers类提供为类包的一部分,则可能无法预期包的所有用户的需求。 在这种情况下,最好不要捕获异常,并允许一个方法进一步推给上层来调用堆栈来处理它。 如果writeLi
我正试图为一个方法编写一个测试用例,该方法基于特定的逻辑抛出异常。然而,测试用例失败了,因为预期的异常和获得的异常是不同的。 我如何解决这个问题?
请问在Spring webflux中抛出选中的自定义异常的正确方法是什么?我想坚持,这是关于检查自定义异常,如MyException。java,而不是RuntimeException,它是关于抛出异常,而不是处理异常。 我尝试了以下方法: 这是不可能的,因为get秒dStepFromFirstStepAfterCheck方法中存在未处理的异常。 如果我抛出并传播,私有的SecondStep get