SpringCloud Gateway 中想要获取请求体数据,这里介绍一种优雅的处理方法,就是使用 框架自带的 ModifyRequestBodyGatewayFilterFactory
使用
新建类 RequestLogFilter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| @Slf4j @Component @AllArgsConstructor public class RequestLogFilter implements GlobalFilter, Ordered {
private final ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory;
private final AsyncRequestHandler asyncRequestHandle;
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { if (Utils.isUploadRequest(exchange)) { process(exchange, null); return chain.filter(exchange); } ModifyRequestBodyGatewayFilterFactory.Config modifyRequestConfig = new ModifyRequestBodyGatewayFilterFactory.Config() .setRewriteFunction(byte[].class, byte[].class, (e, bytes) -> { process(e, bytes); return Mono.justOrEmpty(bytes); }); return modifyRequestBodyGatewayFilterFactory.apply(modifyRequestConfig).filter(exchange, chain); }
@Override public int getOrder() { return -100; }
private void process(ServerWebExchange exchange, byte[] bytes) { exchange.getAttributes().put(Constant.REQUEST_START_TIME_ATTR, System.currentTimeMillis()); exchange.getAttributes().put(Constant.ACCESS_LOG_REQUEST_FUTURE_ATTR, asyncRequestHandle.handle(exchange, bytes)); } }
|
1 2 3 4 5 6 7 8 9
|
public static boolean isUploadRequest(ServerWebExchange exchange){ return MediaType.MULTIPART_FORM_DATA.isCompatibleWith(requestContentType(exchange)); }
|
新建 AsyncRequestHandler 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| @Component @Slf4j @AllArgsConstructor public class AsyncRequestHandler { @Async("logTaskPool") public Future<AccessLog> handle(ServerWebExchange exchange, byte[] bytes) { return new AsyncResult<>(wrapperAccessLog(exchange, bytes)); }
private AccessLog wrapperAccessLog(ServerWebExchange exchange, byte[] bytes) { ServerHttpRequest request = exchange.getRequest(); AccessLog accessLog = new AccessLog(); accessLog.setToken(Utils.getToken(exchange)); accessLog.setTime(LocalDateTime.now()); accessLog.setApplication(getApplicationName(exchange)); accessLog.setIp(Utils.getIp(exchange)); accessLog.setUri(request.getURI().toString()); accessLog.setHttpMethod(HttpMethod.valueOf(request.getMethodValue())); accessLog.setTakenTime((long) exchange.getAttributes().get(Constant.REQUEST_START_TIME_ATTR)); accessLog.setRequestHeaders(request.getHeaders().toSingleValueMap().toString()); if(Utils.isUploadRequest(exchange)) { accessLog.setRequest("二进制文件"); } Optional.ofNullable(bytes).ifPresent(bs -> { if (bytes.length <= DataSize.ofKilobytes(256).toBytes()) { accessLog.setRequest(new String(bytes, StandardCharsets.UTF_8)); } else { accessLog.setRequest("报文过长"); } }); return accessLog; }
private String getApplicationName(ServerWebExchange exchange) { String routingId = (String) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_PREDICATE_MATCHED_PATH_ROUTE_ID_ATTR); if (routingId.startsWith(Constant.MODULE_SUB_PREFIX)) { return routingId.substring(Constant.MODULE_SUB_PREFIX.length()); } else { return routingId; } }
}
|
AccessLog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| public class AccessLog extends AbstractLog {
private String application;
private String ip;
private String uri;
private HttpMethod httpMethod;
private Long takenTime;
private Integer httpCode;
private String request;
private String response;
private String requestHeaders;
private String responseHeaders;
public String getApplication() { return application; }
public void setApplication(String application) { this.application = application; }
public String getIp() { return ip; }
public void setIp(String ip) { this.ip = ip; }
public String getUri() { return uri; }
public void setUri(String uri) { this.uri = uri; }
public HttpMethod getHttpMethod() { return httpMethod; }
public void setHttpMethod(HttpMethod httpMethod) { this.httpMethod = httpMethod; }
public Long getTakenTime() { return takenTime; }
public void setTakenTime(Long takenTime) { this.takenTime = takenTime; }
public Integer getHttpCode() { return httpCode; }
public void setHttpCode(Integer httpCode) { this.httpCode = httpCode; }
public String getRequest() { return request; }
public void setRequest(String request) { this.request = request; }
public String getResponse() { return response; }
public void setResponse(String response) { this.response = response; }
public String getRequestHeaders() { return requestHeaders; }
public void setRequestHeaders(String requestHeaders) { this.requestHeaders = requestHeaders; }
public String getResponseHeaders() { return responseHeaders; }
public void setResponseHeaders(String responseHeaders) { this.responseHeaders = responseHeaders; } }
|
AbstractLog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| public abstract class AbstractLog {
private String id;
private String token;
private String userid;
private String username;
private String name;
private LocalDateTime time;
private OriginType originType;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getToken() { return token; }
public void setToken(String token) { this.token = token; }
public String getUserid() { return userid; }
public void setUserid(String userid) { this.userid = userid; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public LocalDateTime getTime() { return time; }
public void setTime(LocalDateTime time) { this.time = time; }
public OriginType getOriginType() { return originType; }
public void setOriginType(OriginType originType) { this.originType = originType; } }
|
注意:
这里对请求的数据进行了拦截并包装成日志对象存储在 exchange 的一个 ACCESS_LOG_REQUEST_FUTURE_ATTR 属性中,后面再拿到响应时,在从 exchange 拿回请求数据和响应数据一并使用