Я сделал небольшой тестовый проект с самой последней версией Spring-Boot V2.2.5 и стартером WebFlux.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- ... -->
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- ... -->
В этом проекте я создал действительно простой @RestController для разбора x- www-form-urlencoded, подобный этому :
@RestController
public class MyController {
/*
This worked in Tomcat stack, but it's unfortunately too old-school for WebFlux...
java.lang.IllegalStateException: In a WebFlux application, form data is accessed via ServerWebExchange.getFormData().
at org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver.readBody(AbstractMessageReaderArgumentResolver.java:158) ~[spring-webflux-5.2.4.RELEASE.jar:5.2.4.RELEASE]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ HTTP POST "/" [ExceptionHandlingWebHandler]
Stack trace:
...
@PostMapping
public Map<String, String> test(@RequestBody MultiValueMap<String, String> formData) {
String formDataTest = formData.getFirst("test");
String result = Objects.requireNonNullElse(formDataTest, "you failed!");
return Map.of("result", result);
}
*/
@PostMapping
public Map<String, String> test(ServerWebExchange serverWebExchange) {
MultiValueMap<String, String> formData = getFormData(serverWebExchange);
String formDataTest = formData.getFirst("test");
String result = Objects.requireNonNullElse(formDataTest, "you failed!");
return Map.of("result", result);
}
private static MultiValueMap<String, String> getFormData(ServerWebExchange serverWebExchange) {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
serverWebExchange.getFormData().subscribe(formData::addAll);
return formData;
}
}
Чтобы проверить это, я написал следующее ...
@WebFluxTest(controllers = MyController.class)
class MyControllerTest {
@Autowired
private WebTestClient webClient;
@Test
void test() {
webClient.post()
.uri("/")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(BodyInserters.fromFormData("test", "testing-test"))
.exchange()
.expectStatus().is2xxSuccessful()
.expectBody()
.jsonPath("$.result").isEqualTo("testing-test");
}
}
... и этот тест станет зеленым. Отличный материал!
К сожалению, для реальных данных это не получается. Протестировано в Postman и curl - этот запрос должен работать, насколько я понимаю, но ...
➜ ~ curl --location --request POST 'localhost:8080' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'test=testing-test'
{"result":"you failed!"}%
Я что-то здесь не так сделал? Почему исходные данные не анализируются при запросе curl?