关于springcloud gateway的一些使用心得

主要是两个问题:

1. 如何忽略全局过滤器

2. 处理响应数据过长,导致response处理多次

 

----------分割线----------

springboot版本:2.1.10.RELEASE

springcloud版本:Greenwich.SR4

 

伴随着一些需求,有一些接口是不用认证就可以访问并且得到数据的情况下,不需要全局过滤器拦截。

全局过滤器部分代码:

@Slf4j
@Component
public class WrapperRequestGlobalFilter implements GlobalFilter, Order {

    final static String REQUEST_IGNORE_GLOBAL_FILTER = "@ignoreGlobalFilter";

    @Override
    public Class<? extends Annotation> annotationType() {
        return null;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //跳过全局拦截器,不做拦截
        if (exchange.getAttribute(REQUEST_IGNORE_GLOBAL_FILTER) != null) {
            return chain.filter(exchange);
        } else {
            log.info("request = {}", JSONArray.toJSONString(exchange.getRequest()));
            // TODO 处理个人业务。。。。。。
        }
    }

忽略全局过滤器部分代码:

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class IgnoreGlobalFilterFactor extends AbstractGatewayFilterFactory<IgnoreGlobalFilterFactor.Config> {

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

    @Override
    public GatewayFilter apply(Config config) {
        return this::filter;
    }

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(WrapperRequestGlobalFilter.REQUEST_IGNORE_GLOBAL_FILTER, true);
        return chain.filter(exchange);
    }

    public static class Config {

    }

application.yml的配置

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
        #demo
        - id: route_demo
          uri: lb://clt-business-demo
          predicates:
            - Path=/xxooqqq/**
          filters:
            - StripPrefix=1   #表示转发是去掉route_demo
            - RewritePath=/xxooqqq/(?<segment>.*), /demo/$\{segment}    #将xxooqqq转发时替换demo,后面的请求不变
            - IgnoreGlobalFilter    #为该路由忽略全局过滤器

 

----------分割线---------

我们在做响应数据加密处理时,发现gateway的response方法执行了多次,并且返回的加密数据不能正常的解密,总是失败,debug后发现返回的数据过长,导致分了多次执行response的全局过滤器。

部分代码:

@Component
@Slf4j
public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered {
    //将 List 数据以""分隔进行拼接
    private static Joiner joiner = Joiner.on("");
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        AESHelper instance = AESHelper.getInstance();
        if (exchange.getAttribute(RESPONSE_IGNORE_GLOBAL_FILTER) != null) {
            return chain.filter(exchange);
        } else {
            DataBufferFactory bufferFactory = originalResponse.bufferFactory();
            ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
                        Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                            return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                                // 用list接受多次返回的数据,最后在拼接成string
                                List<String> list = new ArrayList<>();
                                dataBuffers.forEach(dataBuffer -> {
                                    byte[] content = new byte[dataBuffer.readableByteCount()];
                                    dataBuffer.read(content);
                                    DataBufferUtils.release(dataBuffer);
                                    try {
                                        list.add(new String(content, "utf-8"));
                                    } catch (Exception e) {
                                        log.error("--list.add--error",e);
                                    }
                                });
                                String responseData = joiner.join(list);
                                String encodeStr = instance.encrypt(responseData);
                                byte[] bytes = Base64.encode(encodeStr).getBytes();
                                return bufferFactory.wrap(bytes);

                    }));
                    } else {
                        log.error("响应code异常:{}", getStatusCode());
                    }
                    return super.writeWith(body);
                }
            };
            return chain.filter(exchange.mutate().response(decoratedResponse).build());
        }
    }

大概的处理方法已经表达清楚,需要处理的部分已经标红,也是看了很多文章后总结的,希望能帮助遇到同样问题的小伙伴。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值