主要是两个问题:
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()); } }
大概的处理方法已经表达清楚,需要处理的部分已经标红,也是看了很多文章后总结的,希望能帮助遇到同样问题的小伙伴。