提交 html 表单数据到 webflux HandlerFunction
Submit html form data to webflux HandlerFunction
我有一个 html 表单向 HandlerFunction 提交请求。但我收到错误消息,“出现意外错误(类型=不支持的媒体类型,状态=415)。
bodyType=com.reactive.ui.component.SearchQuery
不支持内容类型 'application/x-www-form-urlencoded'
这是表格。
<form
action="#"
th:action="@{/search}"
th:object="${searchQuery}"
method="post">
<table>
<tr>
<td>traveling from</td>
<td><input
type="text"
th:field="*{origin}" /></td>
</tr>
<tr>
<td>going to</td>
<td><input
type="text"
th:field="*{destination}" /></td>
</tr>
<tr>
<td>planning on</td>
<td><input
type="text"
th:field="*{flightDate}" /></td>
</tr>
<tr>
<td></td>
<td><input
type="submit"
value="Submit" /></td>
</tr>
</table>
</form>
这里是 HandlerFunction。
public HandlerFunction<ServerResponse> postSearch = request ->
{
Mono<SearchQuery> sq = request.bodyToMono(SearchQuery.class);
Flux<Flight> flights = this.searchClient.post()
.uri("/search/get/")
.body(BodyInserters.fromPublisher(sq,
SearchQuery.class))
.retrieve()
.bodyToFlux(Flight.class);
Map<String, Flux<Flight>> model = new HashMap<>();
model.put("flights",
flights);
return ServerResponse.ok()
.render("result",
model);
};
这是路线。
@Bean
RouterFunction<ServerResponse> search()
{
RouterFunction<ServerResponse> searchRoutes = RouterFunctions.route(GET("/"),
uiHandler.search)
.andRoute(POST("/search"),
uiHandler.postSearch);
return searchRoutes;
}
遇到这种情况怎么办?我看到了这样的代码 Mono<MultiValueMap<String, String> map = request.body(BodyExtractors.toFormData());
但不知道如何在我的案例中使用它。
我想我已经接近解决方案了。这是我写的代码。但是现在我得到 "Only one connection receive subscriber allowed." 我哪里出错了?
public HandlerFunction<ServerResponse> postSearch = request ->
{
return request.body(BodyExtractors.toFormData())
.map(value ->
{
sq.setOrigin(value.getFirst("origin"));
sq.setDestination(value.getFirst("destination"));
sq.setFlightDate(value.getFirst("flightDate"));
System.out.println(sq);
Flux<Flight> flights = this.searchClient.post()
.uri("/search/get/")
.body(BodyInserters.fromObject(sq))
.retrieve()
.bodyToFlux(Flight.class);
Map<String, Flux<Flight>> model = new HashMap<>();
model.put("flights",
flights);
return model;
})
.flatMap(model -> ServerResponse.ok()
.render("result",
model));
};
终于明白了。一直以来我都在使用 request.body(BodyExtractors.toFormData()),天知道为什么!!但所需要的只是 request.formData()。将代码粘贴到此处以使其他人受益。
一点解释。 request.formData() returns Mono<MultiValueMap<String, String>>
。首先,我将其映射为根据通过 POST 提交的值创建一个 SearchQuery 实例,然后将其平面映射到我调用另一个微服务的位置以获取 Flux<Flight>
,然后将其放入 java.util.Map 和 return 服务器响应。实际上,您可以在单个 flatMap 中完成此操作,而不是先进行映射,然后再进行 flatMapping。
public HandlerFunction<ServerResponse> postSearch = request ->
{
return request.formData()
.map(value ->
{
SearchQuery sq = new SearchQuery();
sq.setOrigin(value.getFirst("origin"));
sq.setDestination(value.getFirst("destination"));
sq.setFlightDate(value.getFirst("flightDate"));
return sq;
})
.flatMap(sq ->
{
Flux<Flight> flights = this.searchClient.post()
.uri("/search/get/")
.body(BodyInserters.fromObject(sq))
.retrieve()
.bodyToFlux(Flight.class);
Map<String, Flux<Flight>> model = new HashMap<>();
model.put("flights",
flights);
return ServerResponse.ok()
.render("result",
model);
});
};
我有一个 html 表单向 HandlerFunction 提交请求。但我收到错误消息,“出现意外错误(类型=不支持的媒体类型,状态=415)。 bodyType=com.reactive.ui.component.SearchQuery
不支持内容类型 'application/x-www-form-urlencoded'这是表格。
<form
action="#"
th:action="@{/search}"
th:object="${searchQuery}"
method="post">
<table>
<tr>
<td>traveling from</td>
<td><input
type="text"
th:field="*{origin}" /></td>
</tr>
<tr>
<td>going to</td>
<td><input
type="text"
th:field="*{destination}" /></td>
</tr>
<tr>
<td>planning on</td>
<td><input
type="text"
th:field="*{flightDate}" /></td>
</tr>
<tr>
<td></td>
<td><input
type="submit"
value="Submit" /></td>
</tr>
</table>
</form>
这里是 HandlerFunction。
public HandlerFunction<ServerResponse> postSearch = request ->
{
Mono<SearchQuery> sq = request.bodyToMono(SearchQuery.class);
Flux<Flight> flights = this.searchClient.post()
.uri("/search/get/")
.body(BodyInserters.fromPublisher(sq,
SearchQuery.class))
.retrieve()
.bodyToFlux(Flight.class);
Map<String, Flux<Flight>> model = new HashMap<>();
model.put("flights",
flights);
return ServerResponse.ok()
.render("result",
model);
};
这是路线。
@Bean
RouterFunction<ServerResponse> search()
{
RouterFunction<ServerResponse> searchRoutes = RouterFunctions.route(GET("/"),
uiHandler.search)
.andRoute(POST("/search"),
uiHandler.postSearch);
return searchRoutes;
}
遇到这种情况怎么办?我看到了这样的代码 Mono<MultiValueMap<String, String> map = request.body(BodyExtractors.toFormData());
但不知道如何在我的案例中使用它。
我想我已经接近解决方案了。这是我写的代码。但是现在我得到 "Only one connection receive subscriber allowed." 我哪里出错了?
public HandlerFunction<ServerResponse> postSearch = request ->
{
return request.body(BodyExtractors.toFormData())
.map(value ->
{
sq.setOrigin(value.getFirst("origin"));
sq.setDestination(value.getFirst("destination"));
sq.setFlightDate(value.getFirst("flightDate"));
System.out.println(sq);
Flux<Flight> flights = this.searchClient.post()
.uri("/search/get/")
.body(BodyInserters.fromObject(sq))
.retrieve()
.bodyToFlux(Flight.class);
Map<String, Flux<Flight>> model = new HashMap<>();
model.put("flights",
flights);
return model;
})
.flatMap(model -> ServerResponse.ok()
.render("result",
model));
};
终于明白了。一直以来我都在使用 request.body(BodyExtractors.toFormData()),天知道为什么!!但所需要的只是 request.formData()。将代码粘贴到此处以使其他人受益。
一点解释。 request.formData() returns Mono<MultiValueMap<String, String>>
。首先,我将其映射为根据通过 POST 提交的值创建一个 SearchQuery 实例,然后将其平面映射到我调用另一个微服务的位置以获取 Flux<Flight>
,然后将其放入 java.util.Map 和 return 服务器响应。实际上,您可以在单个 flatMap 中完成此操作,而不是先进行映射,然后再进行 flatMapping。
public HandlerFunction<ServerResponse> postSearch = request ->
{
return request.formData()
.map(value ->
{
SearchQuery sq = new SearchQuery();
sq.setOrigin(value.getFirst("origin"));
sq.setDestination(value.getFirst("destination"));
sq.setFlightDate(value.getFirst("flightDate"));
return sq;
})
.flatMap(sq ->
{
Flux<Flight> flights = this.searchClient.post()
.uri("/search/get/")
.body(BodyInserters.fromObject(sq))
.retrieve()
.bodyToFlux(Flight.class);
Map<String, Flux<Flight>> model = new HashMap<>();
model.put("flights",
flights);
return ServerResponse.ok()
.render("result",
model);
});
};