获取SpringCloud gateway响应的response的并进行修改

一、需求说明:

由于公司的项目接入了几个几个服务进来,因为这几个服务接口返回的结果对象没有统一,前端需要后端将返回结果对象统一。

二、解决方案:

在网关写一个全局过滤器去对接口返回结果对象进行重构然后返回给前端。

三、代码实现

package com.jzt.zyy.gateway.filter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.Data;
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.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.io.Serializable;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @description:
 * 	全局拦截器,作用所有的微服务
 * 	处理原因:因为目前各个服务比较杂,有java、.net和php项目,
 * 	并且接口返回的结果结构不统一,所以需要在网关进行统一一下。
 *
 * @author: sukang
 * @date: 2020-08-24 11:24
 */
@Slf4j
@Component
public class ZyyResponseGlobalFilter implements GlobalFilter, Ordered {

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		ServerHttpResponse originalResponse = exchange.getResponse();
		DataBufferFactory bufferFactory = originalResponse.bufferFactory();
		ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
			@Override
			public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
				if (body instanceof Flux) {
					Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
					return super.writeWith(fluxBody.map(dataBuffer -> {
						// probably should reuse buffers
						byte[] content = new byte[dataBuffer.readableByteCount()];
						dataBuffer.read(content);
						//释放掉内存
						DataBufferUtils.release(dataBuffer);
						String s = new String(content, Charset.forName("UTF-8"));
						//修改response之后的字符串
						String lastStr = s;
						//修改response的值
						if(StrUtil.containsIgnoreCase(s, "code") && JSONUtil.isJson(s)){
							GlobalResponse globalResponse = getGlobalResponse(originalResponse, s);
							if(globalResponse != null){
								log.info("修改之后的Response:{}", globalResponse);
								lastStr = JSONUtil.toJsonStr(globalResponse);
							}
						}

						byte[] uppedContent = lastStr.getBytes();
						return bufferFactory.wrap(uppedContent);
					}));
				}
				// if body is not a flux. never got there.
				return super.writeWith(body);
			}
		};
		// replace response with decorator
		return chain.filter(exchange.mutate().response(decoratedResponse).build());
	}

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


	private GlobalResponse getGlobalResponse(ServerHttpResponse originalResponse, String originalResponseStr){
		log.info("原始Response:{}", originalResponseStr);
		JSONObject jsonObject = JSONUtil.parseObj(originalResponseStr, false);
		if(jsonObject.containsKey("code")){
			if(jsonObject.getInt("code") == 200 || jsonObject.getInt("code") == 0){
				GlobalResponse globalResponse = new GlobalResponse();
				globalResponse.setCode(HttpStatus.OK.value());
				globalResponse.setMsg("成功");
				globalResponse.setSuccess(true);

				if(jsonObject.containsKey("count")){
					Map<String, Object> map = new HashMap<>();
					map.put("total", jsonObject.getInt("count"));
					map.put("list", Optional.ofNullable(jsonObject.getObj("data")).orElse("[]"));
					globalResponse.setData(map);
				}else{
					globalResponse.setData(Optional.ofNullable(jsonObject.getObj("data")).orElse("[]"));
				}
				return globalResponse;
			}else{
				GlobalResponse globalResponse = new GlobalResponse();
				if(jsonObject.getInt("code") == 401){
					globalResponse.setCode(403);
					globalResponse.setMsg("处方平台token失效");
					globalResponse.setData("[]");
				}else{
					globalResponse.setCode(originalResponse.getStatusCode().value());
					globalResponse.setMsg(Optional.ofNullable(jsonObject.getStr("msg")).orElse(""));
					globalResponse.setData(Optional.ofNullable(jsonObject.getObj("data")).orElse("[]"));
				}
				return globalResponse;
			}
		}

		if(jsonObject.containsKey("Code")){
			if(jsonObject.getInt("Code") == 200){
				GlobalResponse globalResponse = new GlobalResponse();
				globalResponse.setCode(HttpStatus.OK.value());
				globalResponse.setMsg("成功");
				globalResponse.setSuccess(true);

				if(jsonObject.containsKey("Count") || jsonObject.containsKey("DataTotal")){
					int total = 0;
					if(jsonObject.containsKey("Count")){
						total = jsonObject.getInt("Count");
					}
					if(jsonObject.containsKey("DataTotal")){
						total = jsonObject.getInt("DataTotal");
					}

					Map<String, Object> map = new HashMap<>();
					map.put("total", total);
					map.put("list", Optional.ofNullable(jsonObject.getObj("Data")).orElse("[]"));
					globalResponse.setData(map);
				}else{
					globalResponse.setData(Optional.ofNullable(jsonObject.getObj("Data")).orElse("[]"));
				}
				return globalResponse;
			}else{
				GlobalResponse globalResponse = new GlobalResponse();
				if(jsonObject.getInt("Code") == 401){
					globalResponse.setCode(403);
					globalResponse.setMsg("处方平台token失效");
					globalResponse.setData("[]");
				}else{
					globalResponse.setCode(originalResponse.getStatusCode().value());
					globalResponse.setMsg(Optional.ofNullable(jsonObject.getStr("Msg")).orElse("处方平台查询失败"));
					globalResponse.setData(Optional.ofNullable(jsonObject.getObj("Data")).orElse("[]"));
				}
				return globalResponse;
			}
		}

		return null;
	}

	/**
	 * @description:
	 * 		返回给前端的统一格式
	 * @param
	 * @return:
	 * @author: sukang
	 * @date: 2020/8/24 15:36
	 */
	@Data
	private class GlobalResponse implements Serializable{
		private static final long serialVersionUID = 1L;

		private int code;

		private boolean success = false;

		private String msg = "";

		private Object data;
	}
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Cloud Gateway提供了一种全局响应处理的机制,可以在所有路由处理完成后进行统一的响应处理。具体实现方式是通过实现`GlobalFilter`接口来实现全局过滤器,并在其中处理响应。以下是一个简单的示例代码: ```java @Component public class CustomGlobalFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange).then(Mono.fromRunnable(() -> { ServerHttpResponse response = exchange.getResponse(); HttpStatus statusCode = response.getStatusCode(); if (statusCode == HttpStatus.UNAUTHORIZED) { response.getHeaders().setContentType(MediaType.APPLICATION_JSON); String body = "{\"message\": \"Unauthorized\"}"; DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8)); return response.writeWith(Flux.just(buffer)); } })); } } ``` 在上述代码中,我们通过实现`GlobalFilter`接口并重写`filter`方法,在方法中调用`chain.filter(exchange)`代表继续执行后续的过滤器和路由处理。在其后面通过`then`方法调用`Mono.fromRunnable`,并在其中处理响应。例如,如果响应状态码为`UNAUTHORIZED`,我们可以设置响应头和响应体,然后将其写入响应流中。 需要注意的是,在全局过滤器中处理响应时,需要调用`ServerHttpResponse.writeWith`或`ServerHttpResponse.writeAndFlushWith`方法来写入响应流,而不能使用`ServerHttpResponse.getBody`方法来直接写入响应体。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值