• SpringCloud-Gateway修改Response响应体,并解决大数据量返回不全等问题


    官网相关案例:

    Spring Cloud Gatewayicon-default.png?t=N7T8https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-modifyresponsebody-gatewayfilter-factory

    ModifyRequestBodyGatewayFilterFactory类:

    https://github.com/spring-cloud/spring-cloud-gateway/blob/3.1.x/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.javaicon-default.png?t=N7T8https://github.com/spring-cloud/spring-cloud-gateway/blob/3.1.x/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java

    相关代码:

    1. import cn.hutool.core.collection.CollUtil;
    2. import cn.hutool.core.util.StrUtil;
    3. import com.alibaba.fastjson.JSONObject;
    4. import lombok.AllArgsConstructor;
    5. import lombok.Data;
    6. import lombok.NoArgsConstructor;
    7. import lombok.SneakyThrows;
    8. import lombok.extern.slf4j.Slf4j;
    9. import org.reactivestreams.Publisher;
    10. import org.springframework.cloud.gateway.filter.GatewayFilter;
    11. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    12. import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
    13. import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
    14. import org.springframework.core.Ordered;
    15. import org.springframework.core.io.buffer.DataBuffer;
    16. import org.springframework.core.io.buffer.DataBufferFactory;
    17. import org.springframework.core.io.buffer.DataBufferUtils;
    18. import org.springframework.core.io.buffer.DefaultDataBufferFactory;
    19. import org.springframework.http.HttpHeaders;
    20. import org.springframework.http.HttpStatus;
    21. import org.springframework.http.MediaType;
    22. import org.springframework.http.server.reactive.ServerHttpResponse;
    23. import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
    24. import org.springframework.stereotype.Component;
    25. import org.springframework.web.server.ServerWebExchange;
    26. import reactor.core.publisher.Flux;
    27. import reactor.core.publisher.Mono;
    28. import java.util.List;
    29. /**
    30. * @Author: meng
    31. * @Description: 自定义返回体 - 借鉴原生类ModifyRequestBodyGatewayFilterFactory实现
    32. * https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the
    33. * -modifyresponsebody-gatewayfilter-factory
    34. * @Date: 2023/4/18 13:37
    35. * @Version: 1.0
    36. */
    37. @Slf4j
    38. @Component
    39. public class ResponseGatewayFilterFactory extends AbstractGatewayFilterFactory {
    40. public ResponseGatewayFilterFactory() {
    41. super(Config.class);
    42. }
    43. @Data
    44. @AllArgsConstructor
    45. @NoArgsConstructor
    46. public static class Config {
    47. // 不需要自定义的接口
    48. List pathExclude;
    49. }
    50. @Override
    51. public GatewayFilter apply(Config config) {
    52. RewriteResponseGatewayFilter rewriteResponseGatewayFilter = new RewriteResponseGatewayFilter(config);
    53. return rewriteResponseGatewayFilter;
    54. }
    55. public class RewriteResponseGatewayFilter implements GatewayFilter, Ordered {
    56. private Config config;
    57. public RewriteResponseGatewayFilter(Config config) {
    58. this.config = config;
    59. }
    60. @Override
    61. public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    62. // 不需要自定义的接口,直接返回
    63. log.info("pathExclude:{}", config.pathExclude);
    64. if (CollUtil.isNotEmpty(config.pathExclude)) {
    65. long count = config.pathExclude.stream()
    66. .filter(uri -> StrUtil.contains(exchange.getRequest().getPath().toString(), uri))
    67. .count();
    68. if (count > 0) {
    69. return chain.filter(exchange);
    70. }
    71. }
    72. String appId = exchange.getRequest().getHeaders().getFirst("X-APPID");
    73. if (StrUtil.isBlank(appId)) {
    74. return buildResponse(exchange, HttpStatus.UNAUTHORIZED.value(), "appId不能为空");
    75. }
    76. ServerHttpResponse originalResponse = exchange.getResponse();
    77. DataBufferFactory bufferFactory = originalResponse.bufferFactory();
    78. try {
    79. ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
    80. @Override
    81. public Mono writeWith(Publisher body) {
    82. if (body instanceof Flux) {
    83. Fluxextends DataBuffer> fluxBody = Flux.from(body);
    84. return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
    85. byte[] newContent = new byte[0];
    86. try {
    87. DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
    88. DataBuffer join = dataBufferFactory.join(dataBuffers);
    89. byte[] content = new byte[join.readableByteCount()];
    90. join.read(content);
    91. DataBufferUtils.release(join);
    92. // 获取响应数据
    93. String responseStr = new String(content, "UTF-8");
    94. // 修改响应数据
    95. JSONObject jsonObject = new JSONObject();
    96. jsonObject.put("code", HttpStatus.UNAUTHORIZED.value());
    97. jsonObject.put("message", "请求成功");
    98. jsonObject.put("data", responseStr);
    99. String message = jsonObject.toJSONString();
    100. newContent = message.getBytes("UTF-8");
    101. originalResponse.getHeaders().setContentLength(newContent.length);
    102. }
    103. catch (Exception e) {
    104. log.error("appId:{}, responseStr exchange error:{}", appId, e);
    105. throw new RuntimeException(e);
    106. }
    107. return bufferFactory.wrap(newContent);
    108. }));
    109. }
    110. return super.writeWith(body);
    111. }
    112. @Override
    113. public Mono writeAndFlushWith(Publisher> body) {
    114. return writeWith(Flux.from(body).flatMapSequential(p -> p));
    115. }
    116. };
    117. return chain.filter(exchange.mutate().response(decoratedResponse).build());
    118. }
    119. catch (Exception e) {
    120. log.error("RewriteResponse error:{}", e);
    121. return Mono.error(new Exception("RewriteResponse fail", e));
    122. }
    123. }
    124. @Override
    125. public int getOrder() {
    126. return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 2;
    127. }
    128. }
    129. @SneakyThrows
    130. public static Mono buildResponse(ServerWebExchange exchange, int code, String message) {
    131. ServerHttpResponse response = exchange.getResponse();
    132. response.setStatusCode(HttpStatus.OK);
    133. response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE);
    134. JSONObject jsonObject = new JSONObject();
    135. jsonObject.put("code", code);
    136. jsonObject.put("message", message);
    137. jsonObject.put("data", "");
    138. byte[] bytes = jsonObject.toJSONString().getBytes("UTF-8");
    139. DataBuffer bodyDataBuffer = response.bufferFactory().wrap(bytes);
    140. return response.writeWith(Mono.just(bodyDataBuffer));
    141. }
    142. }

  • 相关阅读:
    IDEA gradle新增依赖报Could not resolve symbol “XXX“错误
    JVM | 垃圾回收器(GC)- Java内存管理的守护者
    Top 5 免费 PDF 转 Word 转换工具
    C++ 内存泄漏与溢出
    【wpf】 当用了数据模板之后如何获取控件的Item?
    合并k个已排序的链表
    【文末送书——数学经典著作】工科必备的数学思维培养
    数据结构1 -- leetcode练习
    Git基础知识及基本操作
    RedisCluster如何高效率地批量插入数据
  • 原文地址:https://blog.csdn.net/W_Meng_H/article/details/134438310