Adquisición del valor de respuesta de Spring Cloud Gateway, impresión del registro de la puerta de enlace

1. Filtro de solicitud, guarde el cuerpo de la solicitud en Atributos, resuelva el problema de que el cuerpo de la solicitud solo se puede leer una vez

import com.bzcst.bop.gateway.common.Constant;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 请求过滤器
 *
 * @author 向振华
 * @date 2021/01/30 10:01
 */
@Component
public class RequestFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return DataBufferUtils.join(exchange.getRequest().getBody()).map(dataBuffer -> {
            byte[] bytes = new byte[dataBuffer.readableByteCount()];
            dataBuffer.read(bytes);
            DataBufferUtils.release(dataBuffer);
            return bytes;
        }).defaultIfEmpty(new byte[0])
                .doOnNext(bytes -> {
                    // 将请求体存入Attributes
                    exchange.getAttributes().put(Constant.REQUEST_BODY_CACHE, bytes);
                })
                .then(chain.filter(exchange));
    }

    @Override
    public int getOrder() {
        return -3;
    }
}

2. Filtro de respuesta, analiza el mensaje de respuesta

import com.bzcst.bop.gateway.common.Constant;
import com.google.common.base.Charsets;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR;

/**
 * 响应过滤器
 *
 * @author 向振华
 * @date 2021/01/30 10:01
 */
@Slf4j
@Component
public class ResponseFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            ServerHttpResponse originalResponse = exchange.getResponse();
            DataBufferFactory bufferFactory = originalResponse.bufferFactory();
            ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    Object contentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
                    if (HttpStatus.OK.equals(getStatusCode()) && body instanceof Flux
                            && Constant.CONTENT_TYPES.contains(contentType)) {
                        Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                            DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                            DataBuffer join = dataBufferFactory.join(dataBuffers);
                            byte[] content = new byte[join.readableByteCount()];
                            join.read(content);
                            DataBufferUtils.release(join);
                            String responseMessage = new String(content, Charsets.UTF_8);
                            // responseMessage就是响应消息,这里可以打印出来或做其他业务处理
                            byte[] uppedContent = responseMessage.getBytes(Charsets.UTF_8);
                            return bufferFactory.wrap(uppedContent);
                        }));
                    } else {
                        return chain.filter(exchange);
                    }
                }
            };
            return chain.filter(exchange.mutate().response(decoratedResponse).build());
        } catch (Exception e) {
            log.error("网关响应解析异常:", e);
            return chain.filter(exchange);
        }
    }

    @Override
    public int getOrder() {
        return -2;
    }
}

3. Acepte el filtro y resuelva el error de solicitud POST: solo una conexión recibe el problema del suscriptor permitido

import com.bzcst.bop.gateway.common.Constant;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 接受过滤器(解决POST请求报错:Only one connection receive subscriber allowed)
 *
 * @author 向振华
 * @date 2021/01/30 10:01
 */
@Component
public class ReceiveFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Object requestBodyCache = exchange.getAttribute(Constant.REQUEST_BODY_CACHE);
        DataBufferFactory dataBufferFactory = exchange.getResponse().bufferFactory();
        ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
            @Override
            public Flux<DataBuffer> getBody() {
                byte[] body;
                if (requestBodyCache != null && (body = (byte[]) requestBodyCache).length > 0) {
                    return Flux.just(dataBufferFactory.wrap(body));
                }
                return Flux.empty();
            }
        };
        return chain.filter(exchange.mutate().request(decorator).build());
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

Clase constante

import com.google.common.collect.Lists;

import java.util.List;

/**
 * 常量类
 *
 * @author 向振华
 * @date 2021/01/15 15:52
 */
public class Constant {


    public static final String REQUEST_BODY_CACHE = "requestBodyCache";
    public static final List<String> CONTENT_TYPES = Lists.newArrayList("application/json;charset=UTF-8", "text/plain;charset=UTF-8");

}

 

Supongo que te gusta

Origin blog.csdn.net/Anenan/article/details/113518764
Recomendado
Clasificación