functional-programming - WebFlux 返回 http.okay 副 http.notFound
问题描述
WebFlux、反应式和处理程序的新手。我有一些“工作”的东西,但我不明白为什么下面的代码会返回“好的”,但“没有找到”。
澄清:关注的问题在DemoPOJOHandler.getById()的最终返回语句中。“短路”代码按预期工作(即返回“错误请求”状态),但如果DemoPOJORepo.getById(int)返回Mono.empty,则最终返回语句的“switchIfEmpty”路径似乎没有得到执行()。
(注意:我已经破解了一个基于列表的“repo”,以避免在确定处理程序和 http 返回类型时处理数据库。)
路由器实现(“/v1”是一组基于注释的 RESTful 端点)...
@Configuration
public class DemoPOJORouter {
@Bean
public RouterFunction<ServerResponse> route(DemoPOJOHandler requestHandler) {
return nest(path("/v2"),
nest(accept(APPLICATION_JSON),
RouterFunctions.route(RequestPredicates.GET("/DemoPOJO"), requestHandler::getAll)
.andRoute(RequestPredicates.GET("/DemoPOJO/{id}"), requestHandler::getById)
.andRoute(RequestPredicates.POST("/DemoPOJO"), requestHandler::add)));
}
}
处理程序的实现已被“精简”到只有有问题的代码。我有一种感觉,大部分风格“仍然是必要的”,但我试图将反应性的东西放在“最有意义”的地方。
如果我在 URI 上提供了错误的值(即“foo”),那么我会返回 http“错误请求”。但是,如果提供了有效格式化的 int 值,似乎永远不会得到应该由“ switchIfEmpty ”生成的“未找到”,但它不会映射到 repo 中的条目。
@Component
public class DemoPOJOHandler {
public static final String PATH_VAR_ID = "id";
private DemoPOJORepo repo = null;
public Mono<ServerResponse> getById(ServerRequest request) {
Mono<DemoPOJO> monoDemoPOJO = null;
Map<String, String> pathVariables = request.pathVariables();
int id = -1;
checkRepoRef(); // part of the list hack
// short-circuit if request doesn't contain id (should never happen)
if ((pathVariables == null)
|| (!pathVariables.containsKey(PATH_VAR_ID))) {
return ServerResponse.badRequest().build();
}
// short-circuit if bad id value
try {
id = Integer.parseInt(pathVariables.get(PATH_VAR_ID));
} catch(NumberFormatException e) {
return ServerResponse.badRequest().build();
}
// get entity by keyValue
monoDemoPOJO = repo.getById(id);
return monoDemoPOJO
.flatMap(demoPOJO -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.syncBody(demoPOJO)
.switchIfEmpty(ServerResponse.notFound().build()));
}
}
破解基于列表的存储库,以避免在处理处理程序和 http 返回类型时处理数据/API。
// local hack to avoid a database for testing
public class DemoPOJORepo {
private static DemoPOJORepo fpRepo = null;
private static int NUM_ROWS = 100;
private Map<Integer, DemoPOJO> fooPOJOMap;
private DemoPOJORepo() {
initMap();
}
public static DemoPOJORepo getInstance() {
if (fpRepo == null) {
fpRepo = new DemoPOJORepo();
}
return fpRepo;
}
public Mono<DemoPOJO> getById(int id) {
Mono<DemoPOJO> monoDP;
if (fooPOJOMap.containsKey(id)) {
monoDP = Mono.just(fooPOJOMap.get(id));
} else {
monoDP = Mono.empty();
}
return monoDP;
}
private Mono<Void> initMap() {
fooPOJOMap = new TreeMap<Integer, DemoPOJO>();
int offset = -1;
for(int ndx=0; ndx<NUM_ROWS; ndx++) {
offset = ndx + 1;
fooPOJOMap.put(offset, new DemoPOJO(offset, "foo_" + offset, offset+100));
}
return Mono.empty();
}
}
解决方案
如我所见,代码是正确的。响应代码是错误请求,因为您正在尝试将“foo”转换为整数,并且当它引发异常时,您将返回错误请求响应,所以我认为它工作得很好。如果您使用数据库中不存在的整数 id,则答案必须是未找到的响应
推荐阅读
- reporting-services - SSRS 上传报告所有者名称错误时
- angular - 如何在角度* ngFor循环中制作最小表格第3行
- omnet++ - 节点如何从传感器接收数据包,另一方面将它们发送到 Mobile Elements?
- azure - Azure 自定义视觉 API predict_image 无效状态码
- python - Python中的实时离线语音识别
- php - 来自 ActiveDataProvider 的 Yii2 ListView 已排序但顺序相反
- c++ - 是否可以使用基类和派生类来实现 Qt 应用程序插件?
- rubymine - ActiveRecord::Migration[5.2] 阻止 RubyMine 自动完成
- javascript - 获取未收到来自 Node Js 的错误消息
- wpf - 在 WPF 中使用 ReactiveUI V8+ RoutedViewHost