簡體   English   中英

從 ServerWebExchange/ServerHttpRequest 獲取正文作為原始字符串

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM