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

Spring Boot Webflux处理程序在将XML请求正文内容解码为Mono或Flux对象时出错

宇文卓
2023-03-14

我一直在尝试实现Spring反应式路由器和处理程序,而不是MVC控制器。看起来很简单,但是我的WebTestClient测试失败了,有500个内部服务器错误。测试的短代码versoin。

@ContextConfiguration(classes = {FooRouter.class, FooServiceConfig.class, FoonHandler.class})
@WebFluxTest
public class FooHandlerTest {

@Test
public void testFooPost()  {
    webTestClient.post()
            .uri("/foot")
            .contentType(MediaType.APPLICATION_XML)
            .accept(MediaType.APPLICATION_XML)
            .body(Mono.just(foo), Foo.class)
            .exchange()
            .expectStatus().isCreated()
            .expectBody(Bar.class)
            .isEqualTo(bar);
}

在测试过程中,路由器工作正常,并调用处理程序。当处理程序试图从请求主体创建Mono时:

Mono<Foo> fooMono = request.bodyToMono(Foo.class);

该行终止单元测试,WebTestClient收到一个500状态代码。在调试期间,尽管mime类型是application/xml,并且它确实映射了Java类,但BodyExtractor正在过滤解码器,并匹配类和mime类型。对于Json,它正在查看Java类,并试图在比较mime类型之前从中获取映射。在debug的深处,当它仍在尝试将类映射到对象映射器时,它会崩溃。

我目前正在使用Spring Boot版本2.3.4-RELEASE和Java8。文档中提到,如果类路径中有JaxB,那么对于XML,它应该使用Jaxb2XmlDecoder,对于默认编解码器使用Endoder。如果你的类路径上有Jackson,它也会使用Jackson。我碰巧两者都有,但没有jackson dataformat xml依赖项。我很确定这是我的测试配置,也可以是WebFluxConfiger,我尝试为JAXB2解码器和编码器设置默认的编解码器。我还尝试添加jackson dataformat xml依赖项,但这也不起作用。这是我尝试使用的webconfig,但在尝试用Json解码器解码mime类型的application/xml时仍然失败。以下是网络配置:

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

    @Override
    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
        configurer.registerDefaults(false);
        configurer.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder(MediaType.APPLICATION_XML));
        configurer.defaultCodecs().jaxb2Encoder(new Jaxb2XmlEncoder());
    }
}

我一直在调试和打印请求对象消息阅读器,Jaxb2XmlEncoder是xml mime类型的编解码器之一。以下是JSON和XML解码器的打印消息:

Message Reader: org.springframework.http.codec.DecoderHttpMessageReader@5b2cea27
    DecoderHttpMessageReader Decoder: org.springframework.http.codec.json.Jackson2JsonDecoder@87b7472
        Mime Type: application/json
        Mime Type: application/*+json
Message Reader: org.springframework.http.codec.DecoderHttpMessageReader@198a86e1
    DecoderHttpMessageReader Decoder: org.springframework.http.codec.xml.Jaxb2XmlDecoder@50cb41d0
        Mime Type: application/xml
        Mime Type: text/xml
        Mime Type: application/*+xml

当在BodyExtrators类中的readSusMessageReaders方法中,函数中有一个过滤器,它遍历消息读取器和解码器。当它到达DecoderHttpMessageReader,Jackson2JsonDecoder时,它开始尝试解码请求。不确定为什么,因为调试器中的mime类型显示为Application/xml。

有人对如何调试这段代码有什么建议吗:

Mono<Foo> fooMono = request.bodyToMono(Foo.class);

这就是它在使用上述代码进行单元测试时死亡的地方。我已经试过调试,但当我太深时,它会停止测试。我只知道,当它试图匹配编解码器时,它正在经历Java类型。大多数编解码器都会立即返回,但Json和XML解码器正试图获取Java类属性,结果令人窒息。该类是一个带有所有正确注释的JaxB类。WebTestClient可以将类编码为XML进行测试。那么为什么处理程序不能把身体转换成单声道呢?没有从该代码语句中抛出任何内容。

共有1个答案

盖高畅
2023-03-14

我知道这是我的设置和单元测试没有显示正确的问题。

在获取正文内容时,实际上是我的返回语句导致了错误。

旧的返回声明:

return created(URI.create(response.getDocument().getPath()))
    .bodyValue(Mono.just(response));

新的返回声明:

return created(URI.create(response.getDocument().getPath()))
    .body(Mono.just(response), Response.class);

看到bodyValue和just body的区别了吗?这导致请求主体无法转换为单声道。

 类似资料:
  • 我想从Flux/Mono中获取对象。我使用 我会这样做: 我有错误: 为什么?有什么不同的方法来获取对象? 在反应式编程中,如何做到:在RequestBody中,您有UserDto。 如果不创建用户,请检查数据库中是否存在电子邮件。

  • 如何将flux 转换为mono 对象?

  • 问题内容: 我正在创建具有flux体系结构的react.js应用程序,并且试图弄清楚应该何时何地从服务器请求数据。有这个例子吗?(不是TODO应用!) 问题答案: 我强烈支持将异步写入操作放在动作创建者中,而将异步读取操作放在商店中。目标是将商店状态修改代码保留在完全同步的动作处理程序中;这使他们易于推理,并且易于进行单元测试。为了防止对同一端点的多个同时请求(例如,重复读取),我将把实际的请求处

  • 我正在发送一个json请求,并在python flask服务中捕获请求参数以进一步处理。但是,当我json转储请求并试图从中收集特定的参数值时,它会给我带来错误 “字符串索引必须是整数,而不是字符串” 这是我在python flask中解析的json: 我不知道我做错了什么。 下面是我的python烧瓶代码:

  • 更新: 一点我想要实现的内容。我有两个服务--一个通过Http返回me,另一个通过Redis返回。对于这两种情况,我有完全相同的功能-10-15个操作符链,我想要实现的是避免重复代码。 例如:

  • 问题内容: 我有一个看起来像这样的XML文件: 我想将其读入python对象,类似于字典列表。因为标记是绝对固定的,所以我很想使用正则表达式(我非常擅长使用那些正则表达式)。但是,我想我会检查是否有人知道如何在此处轻松避免使用正则表达式。我对SAX或其他解析没有太多经验,但是我愿意学习。 我期待向您展示如何在不使用regexes的情况下快速完成此操作。谢谢你的帮助! 问题答案: 如果您认为正则表达