• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

springboot gateway 记录请求和响应日志

武飞扬头像
xiawenquan
帮助1

        spring cloud gateway是基于webflux的项目,因而不能跟使用spring mvc一样直接获取request body,因此需要重新构造再转发。

        如果我们在spring cloud gateway 封装之前读取了一次request body,比如打印request body日志,在下游获取数据的时候会出现错误:[spring cloud] [error] java.lang.IllegalStateException: Only one connection receive subscriber allowed. 因为request body只能读取一次,它是属于消费类型的。

        出现这样的原因是InputStream的read()方法内部有一个postion,标志当前流被读取到的位置,每读取一次,该标志就会移动一次,如果读到最后,read()会返回-1,表示已经读取完了。如果想要重新读取则需要调用reset()方法,position就会移动到上次调用mark的位置,mark默认是0,所以就能从头再读了。调用reset()方法的前提是已经重写了reset()方法,当然能否reset也是有条件的,它取决于markSupported()方法是否返回true,InputStream默认不实现reset(),并且markSupported()默认也是返回false。综上,InputStream默认不实现reset的相关方法,而ServletInputStream也没有重写reset的相关方法,这样就无法重复读取流,这就是我们从request对象中获取的输入流就只能读取一次的原因。

直接上代码

1.实体类

  1.  
    import lombok.Data;
  2.  
     
  3.  
    import java.io.Serializable;
  4.  
    import java.util.Date;
  5.  
     
  6.  
    @Data
  7.  
    public class GatewayLog implements Serializable {
  8.  
    private static final long serialVersionUID = 1983879536575766072L;
  9.  
    /**访问实例*/
  10.  
    private String targetServer;
  11.  
    /**请求路径*/
  12.  
    private String requestPath;
  13.  
    /**请求方法*/
  14.  
    private String requestMethod;
  15.  
    /**协议 */
  16.  
    private String schema;
  17.  
    /**请求体*/
  18.  
    private String requestBody;
  19.  
    /**响应体*/
  20.  
    private String responseData;
  21.  
    /**请求ip*/
  22.  
    private String ip;
  23.  
    /**请求时间*/
  24.  
    private Date requestTime;
  25.  
    /**响应时间*/
  26.  
    private Date responseTime;
  27.  
    /**执行时间*/
  28.  
    private long executeTime;
  29.  
    /**返回码*/
  30.  
    private long code;
  31.  
    /**返回数据类型*/
  32.  
    private String responseContentType;
  33.  
    /**请求数据类型*/
  34.  
    private String requestContentType;
  35.  
    /**请求用户id*/
  36.  
    private String userId;
  37.  
     
  38.  
    }
学新通

2.Service

  1.  
    public interface AccessLogService {
  2.  
    void saveAccessLog(GatewayLog gatewayLog);
  3.  
    }

3.AccessLogFilter

  1.  
    import cn.hutool.core.collection.CollectionUtil;
  2.  
    import com.shouwei.gateway.entity.GatewayLog;
  3.  
    import com.shouwei.gateway.service.AccessLogService;
  4.  
    import com.shouwei.gateway.utils.IpUtils;
  5.  
    import lombok.extern.slf4j.Slf4j;
  6.  
    import org.apache.commons.lang.StringUtils;
  7.  
    import org.reactivestreams.Publisher;
  8.  
    import org.springframework.beans.factory.annotation.Autowired;
  9.  
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
  10.  
    import org.springframework.cloud.gateway.filter.GlobalFilter;
  11.  
    import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
  12.  
    import org.springframework.cloud.gateway.route.Route;
  13.  
    import org.springframework.cloud.gateway.support.BodyInserterContext;
  14.  
    import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
  15.  
    import org.springframework.core.Ordered;
  16.  
    import org.springframework.core.ResolvableType;
  17.  
    import org.springframework.core.io.buffer.*;
  18.  
    import org.springframework.http.HttpHeaders;
  19.  
    import org.springframework.http.MediaType;
  20.  
    import org.springframework.http.codec.HttpMessageReader;
  21.  
    import org.springframework.http.codec.multipart.FormFieldPart;
  22.  
    import org.springframework.http.codec.multipart.Part;
  23.  
    import org.springframework.http.server.reactive.ServerHttpRequest;
  24.  
    import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
  25.  
    import org.springframework.http.server.reactive.ServerHttpResponse;
  26.  
    import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
  27.  
    import org.springframework.stereotype.Component;
  28.  
    import org.springframework.util.LinkedMultiValueMap;
  29.  
    import org.springframework.util.MultiValueMap;
  30.  
    import org.springframework.web.reactive.function.BodyInserter;
  31.  
    import org.springframework.web.reactive.function.BodyInserters;
  32.  
    import org.springframework.web.reactive.function.server.HandlerStrategies;
  33.  
    import org.springframework.web.reactive.function.server.ServerRequest;
  34.  
    import org.springframework.web.server.ServerWebExchange;
  35.  
    import org.springframework.web.util.UriComponentsBuilder;
  36.  
    import reactor.core.publisher.Flux;
  37.  
    import reactor.core.publisher.Mono;
  38.  
     
  39.  
    import java.io.UnsupportedEncodingException;
  40.  
    import java.nio.charset.StandardCharsets;
  41.  
    import java.util.*;
  42.  
    import java.util.regex.M
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfikifh
系列文章
更多 icon
同类精品
更多 icon
继续加载