spring cloud gateway 读取requestBody,使用全局过滤器的方式。不需要在特定的Route中加readBody缓存predicate

@Component
public class RequestBodyAddCacheGlobalFilter implements GlobalFilter, Ordered {
    @Autowired
    ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    ApplicationContext applicationContext;

    private final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();

    public static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Class inClass = String.class;
        Class outClass = String.class;
        ServerRequest serverRequest = ServerRequest.create(exchange, messageReaders);
        // TODO: flux or mono
        Mono<?> bodyMono = serverRequest
                .bodyToMono(inClass)
                .flatMap(body -> {
                    exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, body);
                    return Mono.just(body);
                });

        BodyInserter bodyInserter = BodyInserters.fromPublisher(bodyMono, outClass);
        HttpHeaders headers = new HttpHeaders();
        headers.putAll(exchange.getRequest().getHeaders());
        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
        return bodyInserter.insert(outputMessage, new BodyInserterContext())
                .then(Mono.defer(() -> {
                    ServerHttpRequest decorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
                        @Override
                        public Flux<DataBuffer> getBody() {
                            return outputMessage.getBody();
                        }
                    };
                    return chain.filter(exchange.mutate().request(decorator).build());
                }));
}

 

posted @ 2020-05-23 21:59  soft.push("zzq")  Views(1663)  Comments(0Edit  收藏  举报