diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/GatewayModifyResponseGatewayFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/GatewayModifyResponseGatewayFilter.java index ca72a59c..e6a13901 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/GatewayModifyResponseGatewayFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/GatewayModifyResponseGatewayFilter.java @@ -5,6 +5,7 @@ import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.result.ResultExecutor; import org.apache.commons.lang3.StringUtils; import org.reactivestreams.Publisher; +import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter; @@ -12,12 +13,16 @@ import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutput import org.springframework.cloud.gateway.support.BodyInserterContext; import org.springframework.cloud.gateway.support.DefaultClientResponse; import org.springframework.core.Ordered; +import org.springframework.core.codec.AbstractDataBufferDecoder; +import org.springframework.core.codec.Decoder; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.client.reactive.ClientHttpResponse; +import org.springframework.http.codec.DecoderHttpMessageReader; +import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.server.reactive.ServerHttpResponseDecorator; import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserter; @@ -35,6 +40,8 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.O */ public class GatewayModifyResponseGatewayFilter implements GlobalFilter, Ordered { + @Value("${spring.codec.max-in-memory-size:262144}") + private int maxInMemorySize; @Override @SuppressWarnings("unchecked") @@ -60,7 +67,7 @@ public class GatewayModifyResponseGatewayFilter implements GlobalFilter, Ordered //this will prevent exception in case of using non-standard media types like "Content-Type: image" httpHeaders.add(HttpHeaders.CONTENT_TYPE, originalResponseContentType); ResponseAdapter responseAdapter = new ResponseAdapter(body, httpHeaders); - DefaultClientResponse clientResponse = new DefaultClientResponse(responseAdapter, ExchangeStrategies.withDefaults()); + DefaultClientResponse clientResponse = new DefaultClientResponse(responseAdapter, getExchangeStrategies()); //TODO: flux or mono Mono modifiedBody = clientResponse.bodyToMono(inClass) @@ -97,6 +104,22 @@ public class GatewayModifyResponseGatewayFilter implements GlobalFilter, Ordered return chain.filter(exchange.mutate().response(responseDecorator).build()); } + private ExchangeStrategies getExchangeStrategies() { + ExchangeStrategies exchangeStrategies = ExchangeStrategies.withDefaults(); + // 修复返回大文本数据报org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144 + for (HttpMessageReader messageReader : exchangeStrategies.messageReaders()) { + if (messageReader instanceof DecoderHttpMessageReader) { + DecoderHttpMessageReader reader = (DecoderHttpMessageReader) messageReader; + Decoder decoder = reader.getDecoder(); + if (decoder instanceof AbstractDataBufferDecoder) { + AbstractDataBufferDecoder dataBufferDecoder = (AbstractDataBufferDecoder)decoder; + dataBufferDecoder.setMaxInMemorySize(maxInMemorySize); + } + } + } + return exchangeStrategies; + } + @Override public int getOrder() { return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1; diff --git a/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1001_BaseController.java b/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1001_BaseController.java index e056c99e..65c18392 100644 --- a/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1001_BaseController.java +++ b/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1001_BaseController.java @@ -1,5 +1,7 @@ package com.gitee.sop.storyweb.controller; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.gitee.sop.servercommon.annotation.BizCode; import com.gitee.sop.servercommon.annotation.Open; import com.gitee.sop.storyweb.controller.param.CategoryParam; @@ -18,9 +20,12 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 签名验证通过后,到达这里进行具体的业务处理。 @@ -163,4 +168,19 @@ public class Example1001_BaseController { return parent; } + private static String json = "{\"flightDate\":\"2020-09-01\",\"flightNo\":\"HO1705\",\"departureAirport\":\"ZSCN\",\"arrivalAirport\":\"ZPLJ\",\"ycy\":\"11521\",\"lcy\":\"4354\",\"cr\":\"145\",\"et\":\"1\",\"ye\":\"0\",\"td\":\"0\",\"gw\":\"0\",\"ew\":\"146\",\"xl\":\"1018\",\"yj\":\"0\",\"hw\":\"635\"}"; + // 返回大数据 + @Open(value = "bigdata.get") + @RequestMapping("/bigdata/v1") + public Map bigData(StoryParam param) { + int len = 2000; + List list = new ArrayList<>(len); + for (int i = 0; i < len; i++) { + list.add(JSON.parseObject(json)); + } + Map map = new HashMap<>(); + map.put("data", list); + return map; + } + } diff --git a/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java b/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java index 3ac7f602..cae5bd1b 100644 --- a/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java +++ b/sop-test/src/test/java/com/gitee/sop/test/AllInOneTest.java @@ -275,6 +275,25 @@ public class AllInOneTest extends TestBase { client.execute(requestBuilder); } + /** + * 测试返回大json数据 + */ + public void testLargeResponseJson() { + Client.RequestBuilder requestBuilder = new Client.RequestBuilder() + .method("bigdata.get") + .version("1.0") + .bizContent(new BizContent().add("id", "1").add("name", "葫芦娃")) + .httpMethod(HttpTool.HTTPMethod.GET) + .callback((requestInfo, responseData) -> { + int size = JSON.parseObject(responseData) + .getJSONObject("bigdata_get_response") + .getJSONArray("data").size(); + Assert.assertEquals(size, 2000); + }); + + client.execute(requestBuilder); + } + static class BizContent extends HashMap { public BizContent add(String key, Object value) { this.put(key, value);