![](/img/trans.png)
[英]Get request body string from ServerHttpRequest / Flux<DataBuffer>
[英]Get body as raw string from ServerWebExchange/ServerHttpRequest
我需要在我的 controller 中將請求正文作為原始 JSON 字符串獲取。 我正在使用 Spring WebFlux。 如果我可以更改@PostMapper function 簽名,那么使用“ @RequestBody String rawStudent ”獲取原始 JSON 將非常容易。 但我不能這樣做,因為它是自動生成的並且會影響其他處理程序,而且“ @RequestBody Student ”已經存在,我們不能有兩個@RequestBody。
@RestController
public class StudentController {
@PostMapping("/student")
private void newStudent(@RequestBody Student student,
ServerWebExchange exchange) {
String rawStudent = ServerExchangeUtils.getRequestRawBody(exchange); //idealy like this
System.out.println(rawStudent);
}
}
我正在尋找類似“getRequestRaw(exchange)”的東西
我遇到了同樣的問題,我無法更改簽名,因為它是由 openapi 生成器生成的
我通過將正文緩存在 WebFilter 中的字符串中找到了解決方案:
@Slf4j
public class CachingBodyServerHttpRequestDecorator extends ServerHttpRequestDecorator {
private final StringBuilder cachedBody = new StringBuilder();
public CachingBodyServerHttpRequestDecorator(ServerHttpRequest delegate) {
super(delegate);
}
@Override
public Flux<DataBuffer> getBody() {
return super.getBody().doOnNext(this::cache);
}
@SneakyThrows
private void cache(DataBuffer buffer) {
cachedBody.append(UTF_8.decode(buffer.asByteBuffer()));
}
public String getCachedBody() {
return cachedBody.toString();
}
}
public final class CachingBodyServerWebExchangeDecorator extends ServerWebExchangeDecorator {
private final ServerHttpRequestDecorator requestDecorator;
public CachingBodyServerWebExchangeDecorator(ServerWebExchange delegate) {
super(delegate);
this.requestDecorator = new CachingBodyServerHttpRequestDecorator(delegate.getRequest());
}
@Override
public ServerHttpRequest getRequest() {
return requestDecorator;
}
}
@Component
@Slf4j
public class SetRequestBodyAttribute implements WebFilter {
private static ServerHttpRequestPredicate requestsToServe =
MethodServerHttpRequestPredicate.of(HttpMethod.POST)
.and(PathServerHttpRequestPredicate.of("/contacts/import"))
.or(MethodServerHttpRequestPredicate.of(HttpMethod.PATCH)
.and(PathServerHttpRequestPredicate.of("/contacts/{contact_id}")));
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
if (requestsToServe.test(exchange.getRequest())) {
return chain.filter(new CachingBodyServerWebExchangeDecorator(exchange));
}
return chain.filter(exchange);
}
}
@UtilityClass
public class ServerHttpRequestUtils {
public Mono<String> getBodyAsString(ServerHttpRequest request) {
return Mono.just(((CachingBodyServerHttpRequestDecorator)exchange.getRequest()).getCachedBody())
}
}
public interface ServerHttpRequestPredicate {
boolean test(ServerHttpRequest request);
@NotNull
default ServerHttpRequestPredicate and(@NotNull ServerHttpRequestPredicate other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
@NotNull
default ServerHttpRequestPredicate negate() {
return (t) -> !test(t);
}
@NotNull
default ServerHttpRequestPredicate or(@NotNull ServerHttpRequestPredicate other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
}
@Value
public class PathServerHttpRequestPredicate implements ServerHttpRequestPredicate {
public static PathServerHttpRequestPredicate of(String path) {
return new PathServerHttpRequestPredicate(path);
}
PathPattern pathPattern;
public PathServerHttpRequestPredicate(String path) {
Assert.notNull(path, "path should not be null!");
this.pathPattern = PathPatternParser.defaultInstance.parse(path);
}
@Override
public boolean test(ServerHttpRequest request) {
PathContainer pathContainer = request.getPath().pathWithinApplication();
PathPattern.PathMatchInfo info = this.pathPattern.matchAndExtract(pathContainer);
return info != null;
}
}
@Value(staticConstructor = "of")
public class MethodServerHttpRequestPredicate implements ServerHttpRequestPredicate{
HttpMethod httpMethod;
public MethodServerHttpRequestPredicate(HttpMethod httpMethod) {
Assert.notNull(httpMethod, "httpMethod should not be null!");
this.httpMethod = httpMethod;
}
@Override
public boolean test(ServerHttpRequest request) {
return request.getMethod() == httpMethod;
}
}
在 controller 處理程序中,即使它被注入為 Object,我們也可以將主體作為字符串
Mono<String> bodyAsStringMono = ServerHttpRequestUtils .getBodyAsString(exchange);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.