Spring Cloud Gateway 过滤器获取 POST 请求体 (不使用 Lambda)

在 Spring Cloud Gateway 过滤器中获取 POST 方法的请求体,可以通过继承 AbstractGatewayFilterFactory 类并重写 filter 方法来实现。以下是一个示例代码:

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
@Slf4j
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> {

    public CustomGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();
            MediaType mediaType = request.getHeaders().getContentType();
            if (request.getMethod() == HttpMethod.POST && mediaType != null
                    && mediaType.isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED)) {
                // 获取 POST 请求体
                Mono<MultiValueMap<String, String>> formDataMono = request
                        .getBody()
                        .flatMap(body -> new ServerRequestWrapper(exchange,
                                HandlerStrategies.withDefaults().messageReaders())
                                .formData()
                                .defaultIfEmpty(MultiValueMap.empty()));
                return formDataMono.flatMap(formData -> {
                    // 对请求体进行处理
                    // ...

                    // 重新设置请求体
                    BodyInserter<Mono<MultiValueMap<String, String>>, ReactiveHttpOutputMessage> bodyInserter =
                            BodyInserters.fromPublisher(formDataMono, new ParameterizedTypeReference<MultiValueMap<String, String>>() {});
                    CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, exchange.getResponse().getHeaders());
                    return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
                        ServerHttpRequest decorator = request.mutate()
                                .headers(httpHeaders -> httpHeaders.putAll(outputMessage.getHeaders()))
                                .body(outputMessage.getBody())
                                .build();
                        return chain.filter(exchange.mutate().request(decorator).build());
                    }));
                });
            }
            return chain.filter(exchange);
        };
    }

    public static class Config {
        // 配置项
    }
}

在这个示例中,我们首先通过 ServerHttpRequestgetBody 方法获取请求体,然后利用 ServerRequestWrapper 类封装 ServerHttpRequest,再利用 HandlerStrategies.withDefaults().messageReaders() 创建 ServerRequest 对象,最后通过 formData 方法获取 POST 请求的表单数据。

接下来,我们可以对请求体进行处理,并且重新设置请求体,然后将请求传递给下一个过滤器(或者服务)。

Spring Cloud Gateway 过滤器获取 POST 请求体 (不使用 Lambda)

原文地址: https://www.cveoy.top/t/topic/Nof 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录