SpringBoot Webflux не может вернуть application / xml

В моем реактивном 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: Ожидаемый: application / 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 контроллер и модульный тест. Спасибо!


person maslick    schedule 22.03.2019    source источник
comment
afaik вы должны использовать @RequestMapping (производит = APPLICATION_XML_VALUE) над API-методами, а не класс контроллера. Вероятно, изменение ваших аннотаций метода, например, @GetMapping (путь = / получить, производит = APPLICATION_XML_VALUE) сделает свое дело.   -  person Gewure    schedule 23.03.2019
comment
@Gewure нет, неважно, где вы его поместили (уровень класса или метода), попробуйте проверить код github .com / maslick / fluxish и поиграйте с ним сами.   -  person maslick    schedule 23.03.2019


Ответы (1)


Очевидно, jackson-dataformat-xml еще не поддерживает маршалинг XML в WebFlux. На данный момент я вижу две возможности:

  1. Либо добавьте org.springframework.boot:spring-boot-starter-web в путь к классам (должны быть и starter-web, и starter-webflux). Однако это будет работать только со средами выполнения Servlet 3.1 (например, Tomcat).
  2. Или, если вам нужен полноценный реактивный веб-сервер (например, Netty), используйте xml из JAXB (Jaxb2XmlEncoder и Jaxb2XmlDecoder):

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

    }
}

Вот ссылка на исходный код.

person maslick    schedule 23.03.2019