首页 > 解决方案 > 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();
    }
}

标签: functional-programminghttpresponsespring-webflux

解决方案


如我所见,代码是正确的。响应代码是错误请求,因为您正在尝试将“foo”转换为整数,并且当它引发异常时,您将返回错误请求响应,所以我认为它工作得很好。如果您使用数据库中不存在的整数 id,则答案必须是未找到的响应


推荐阅读