当前位置: 首页 > 知识库问答 >
问题:

WebFlux返回http。好的。找不到

万明辉
2023-03-14

WebFlux、反应式和处理html" target="_blank">程序的新增功能。我已经让事情“正常”了,但我不明白为什么下面的代码返回“OK”,返回的是空的正文,反之则是“not found”。

澄清:关注的问题在DemoPOJOHandler.getById()的最终返回语句中。“短路”代码按预期工作(即返回“坏请求”状态),但是如果DemoPOJORepo.getById(int)返回Mono.empty(),最终返回语句的“开关”路径似乎不会得到执行。

(注意:我破解了一个基于列表的“repo”,以避免在计算处理程序和http返回类型时处理数据库。)

路由器实现(“/v1”是一组基于注释的RESTfulendpoint)。。。

@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”应该生成的“not found”,但它不会映射到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()));
    }

}

黑客攻击基于列表的repo,以避免在处理处理程序和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();
    }
}

共有2个答案

郑伟彦
2023-03-14

我可以看到代码是正确的。响应代码是坏请求,因为您正试图将“foo”转换为整数,当它抛出异常时,您将返回一个坏请求响应,所以我认为它工作得非常好。如果您使用数据库中不存在的整数标识,那么答案必须是找不到的响应

嵇财
2023-03-14

括号位于错误的位置,导致swithIfEmpy应用于服务器响应。ok()publisher而不是monoDemoPOJO,用这个替换返回,它应该可以工作:

return monoDemoPOJO
                   .flatMap(demoPOJO -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).syncBody(demoPOJO))
                   .switchIfEmpty(ServerResponse.notFound().build());
 类似资料:
  • 请原谅稍微不完整的代码,当我遇到这个问题时,我正在重组它。其要点是,在调用中,编译器表示/*Here*/的地方,编译器强制使用类型,但是当返回时,我希望通过返回204来处理,否则我希望返回200。我怎么才能做到? 理想情况下,我可以在map调用中检查它是否是mono.empty(),但如果它是空的mono,它似乎不会输入map。想过使用optionals,但它们似乎不能很好地使用单音。

  • 我有一个用Kotlin写的WebApplication。这是一种有点不和的聊天。我有一个函数,它做几件事。该函数本身用于删除用户的帐户,但是在这样做的同时,它也删除了他从数据库中注销的消息,他将从数据库中的所有组中删除,在他是管理员的组中选择一个新的管理员。 而这个函数看起来确实是这样的: 我的存储库如下所示: 所以我的函数中的最后2个语句返回一个空单声道。问题是先执行哪条语句并不重要,只执行了两

  • 我正在按照一些教程从头开始建立一个spring mvc项目。最初,我将web应用程序配置为在Tomcat中运行。我编写了一个简单的controller类,请求点击“/”。但tomcat总是向我显示“HTTP状态404-找不到”错误。 我看了很多这样的问题,但那些答案对我都不起作用 删除tomcat安装并重新配置。当点击localhost:8080/时,我将获得tomcat主页。 检查了代码的拼写

  • 更新时间:2019-05-30 13:49:05 节点简介 HTTP返回节点是一个对外输出API的结束节点,你可以通过它配置API的返回值 (注意:“HTTP请求”节点与“HTTP返回”节点必须成对出现)。每个API有且仅有一个HTTP返回节点 , 默认返回前置节点输出。 使用场景 如果您需要使用服务开发工作台开发出一个http接口,那么您就需要使用HTTP请求节点作为起始节点,HTTP返回节点作

  • 我正在做一个简单的项目,它使用Spring Boot 2和使用Kotlin的Spring WebFlux。我为我的处理函数编写了测试(在测试中,我使用Mockito模拟依赖项)。 然而,我的路由函数似乎不会触发处理程序,因为我的所有请求都返回HTTP 404 not FOUND(即使路由是正确的)。 我已经查看了各种其他项目,以了解这些测试应该如何编写(这里,这里),但问题仍然存在。 代码如下(也