Spring Boot Webflux 无法返回 application/xml

Posted

技术标签:

【中文标题】Spring Boot Webflux 无法返回 application/xml【英文标题】:SpringBoot Webflux cannot return application/xml 【发布时间】:2019-08-13 19:53:17 【问题描述】:

在我的反应式 REST API 中,我试图返回一个 XML 响应。但是,我总是得到一个JSON,即406 NOT_ACCEPTABLE。知道为什么吗?

@RestController
@RequestMapping(path = "/xml", produces = APPLICATION_XML_VALUE)
public class RestApi 
    @GetMapping(path = "/get")
    public Publisher<ResponseEntity> get() 
        return Mono.just(ResponseEntity.ok().contentType(APPLICATION_XML).body(new Datta("test")));
    

    @PostMapping(path = "/post", consumes = APPLICATION_XML_VALUE)
    public Publisher<ResponseEntity<Datta>> post(@RequestBody Datta datus) 
        datus.setTitle(datus.getTitle() + "!");
        return Mono.just(ResponseEntity.ok().contentType(APPLICATION_XML).body(datus));
    

java.lang.AssertionError: 预期:应用程序/xml 实际:application/json;charset=UTF-8

plugins 
    id 'org.springframework.boot' version '2.1.3.RELEASE'
    id "io.spring.dependency-management" version "1.0.7.RELEASE"

dependencies 
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8"
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

这些是我的 REST controller 和 unit test 的链接。谢谢!

【问题讨论】:

afaik 您应该使用 API 方法上方的 @RequestMapping(produces=APPLICATION_XML_VALUE),而不是 Controller 类。可能将您的方法注释更改为例如@GetMapping(path = "/get",produces = APPLICATION_XML_VALUE) 可以解决问题。 @Gewure 不,不管你把它放在哪里(类或方法级别),尝试检查代码github.com/maslick/fluxish 并自己玩。 【参考方案1】:

显然,jackson-dataformat-xml does not yet 在 WebFlux 中支持 XML Marshalling。至于现在,我看到了两种可能性:

    在类路径中添加org.springframework.boot:spring-boot-starter-web(应该同时存在 starter-webstarter-webflux)。但是,这仅适用于 Servlet 3.1 运行时(例如 Tomcat)。 或者,如果您想要一个成熟的响应式 Web 服务器(例如 Netty)use 来自 JAXB 的 xml 编组(Jaxb2XmlEncoderJaxb2XmlDecoder):

build.gradle

sourceCompatibility = '11'

dependencies 
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    // Java 11 removed these Java EE modules
    implementation "javax.xml.bind:jaxb-api:2.3.1"
    implementation "com.sun.xml.bind:jaxb-core:2.3.0.1"
    implementation "com.sun.xml.bind:jaxb-impl:2.3.2"

    compileOnly "org.projectlombok:lombok"
    annotationProcessor "org.projectlombok:lombok"

POJO

@Data
@AllArgsConstructor
@NoArgsConstructor
@XmlRootElement
public class Datta 
    private String title;

注意 3 个 javax.xml.bind 依赖项(Java 8 不需要这些)和 @XmlRootElement 注释。此解决方案可立即生效,但如果您想要进一步定制,请实施您自己的 WebFluxConfigurer

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer 
    @Override
    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) 
        configurer.registerDefaults(false);
        configurer.customCodecs().decoder(new Jaxb2XmlDecoder());   // <- here
        configurer.customCodecs().encoder(new Jaxb2XmlEncoder());   // <- here

    

Here是源代码的链接。

【讨论】:

以上是关于Spring Boot Webflux 无法返回 application/xml的主要内容,如果未能解决你的问题,请参考以下文章

webflux spring boot 应用程序的过滤器,返回 ResponseEntity<?>

Spring Boot Webflux/Netty - 检测关闭的连接

spring-boot-webflux 中未使用配置的 ObjectMapper

Spring boot - WebFlux - WebTestClient - 将响应转换为 responseEntity

Java Spring Boot Webflux cors 被阻止

Spring Boot v2.0.0.M2 webflux 和执行器