前言
文章主旨: 将返回数据拿出来,然后各种处理。
正文
先看该篇文章的示例接口:
红色框框里面就是返回的 response 数据 。
现在我们想要的就是 在返回给到调用方(前端、第三方等)前,我们抓出来数据,随便改一下东西。
例如: 我要把里面的message 提示语改了。
新建一个全局过滤器:
WrapperResponseGlobalFilter.java
import com.alibaba.fastjson.JSONObject; import com.google.common.base.Joiner; import com.google.common.base.Throwables; import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import org.reactivestreams.Publisher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.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 java.nio.charset.Charset; import java.util.List; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR; /** * @Author JCccc * @Description 拦截返回数据, 修改返回数据 * @Date 2021/8/16 19:22 */ @Component public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered { private static final Logger log = LoggerFactory.getLogger(WrapperResponseGlobalFilter.class); @Override public int getOrder() { // -1 is response write filter, must be called before that return -2; } private static Joiner joiner = Joiner.on(""); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponse originalResponse = exchange.getResponse(); DataBufferFactory bufferFactory = originalResponse.bufferFactory(); ServerHttpResponseDecorator response = new ServerHttpResponseDecorator(originalResponse) { @Override public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) { // 获取ContentType,判断是否返回JSON格式数据 String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR); if (StringUtils.isNotBlank(originalResponseContentType) && originalResponseContentType.contains("application/json")) { Flux<? extends DataBuffer> fluxBody = Flux.from(body); //(返回数据内如果字符串过大,默认会切割)解决返回体分段传输 return super.writeWith(fluxBody.buffer().map(dataBuffers -> { List<String> list = Lists.newArrayList(); dataBuffers.forEach(dataBuffer -> { try { byte[] content = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(content); DataBufferUtils.release(dataBuffer); list.add(new String(content, "utf-8")); } catch (Exception e) { log.info("加载Response字节流异常,失败原因:{}", Throwables.getStackTraceAsString(e)); } }); String responseData = joiner.join(list); System.out.println("responseData:"+responseData); byte[] uppedContent = new String(responseData.getBytes(), Charset.forName("UTF-8")).getBytes(); originalResponse.getHeaders().setContentLength(uppedContent.length); return bufferFactory.wrap(uppedContent); })); } } return super.writeWith(body); } @Override public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) { return writeWith(Flux.from(body).flatMapSequential(p -> p)); } }; return chain.filter(exchange.mutate().response(response).build()); } }
调用接口可以看到,response数据已经被我们拎出来了:
那么我们简单做个处理,
/** * 返回数据处理 * * @param responseData * @return */ private String responseHandle(String responseData) { String responseResultJson = null; try { JSONObject jsonObject = JSONObject.parseObject(responseData); jsonObject.put("message", "JCccc 收藏+关注"); responseResultJson = jsonObject.toJSONString(); } catch (Exception e) { log.info("返回数据处理转化失败,异常信息={}",e.getMessage()); return responseData; } return responseResultJson; }
再次请求,可以看到:
返回数据里面的message已经被我们修改成功了
PS:
还有类似,既然个人信息这么敏感,是不是类似一些接口返回数据需要做统一的加密呢?
如需要,那么也可以通过配置化读取需要加密的ur列表,然后通过exchange把url拿出来做匹对,对responseData 做加密处理。
ServerHttpRequest request = exchange.getRequest(); URI url = request.getURI(); String urlPath = url.getPath(); System.out.println("当前请求url是:"+urlPath);
好了,该篇就到这。