diff --git a/pom.xml b/pom.xml
index 3af5481..63cac39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -96,6 +96,13 @@
1.18.30
+
+
+ com.alibaba
+ fastjson
+ 1.2.83
+
+
diff --git a/src/main/java/com/sczx/gateway/component/DynamicRouteScheduler.java b/src/main/java/com/sczx/gateway/component/DynamicRouteScheduler.java
index 3889dca..673ebad 100644
--- a/src/main/java/com/sczx/gateway/component/DynamicRouteScheduler.java
+++ b/src/main/java/com/sczx/gateway/component/DynamicRouteScheduler.java
@@ -1,11 +1,13 @@
package com.sczx.gateway.component;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
+@Slf4j
@Component
public class DynamicRouteScheduler {
@@ -15,6 +17,7 @@ public class DynamicRouteScheduler {
// 每30秒刷新一次路由(可按需调整)
@Scheduled(fixedRate = 30_000)
public void refreshRoutes() {
+ log.info("refreshRoutes");
publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
diff --git a/src/main/java/com/sczx/gateway/config/CustomRouteConfig.java b/src/main/java/com/sczx/gateway/config/CustomRouteConfig.java
index 504db30..f847ea9 100644
--- a/src/main/java/com/sczx/gateway/config/CustomRouteConfig.java
+++ b/src/main/java/com/sczx/gateway/config/CustomRouteConfig.java
@@ -30,6 +30,9 @@ public class CustomRouteConfig {
.route("sczx_store", r -> r.path("/zc/store/**")
.filters(f -> f.rewritePath("/zc/store/(?.*)", "/${segment}"))
.uri(uriWithCustomLoadBalance("sczx_store")))
+ .route("sczx_car", r -> r.path("/zc/car/**")
+ .filters(f -> f.rewritePath("/zc/car/(?.*)", "/${segment}"))
+ .uri(uriWithCustomLoadBalance("sczx_car")))
.build();
// .route("sczx_user", r -> r.path("/zc/user/**")
// .uri("lb://sczx_user"))
diff --git a/src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java b/src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java
index c028f1e..2a6e9ee 100644
--- a/src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java
+++ b/src/main/java/com/sczx/gateway/filter/LoggingGlobalFilter.java
@@ -25,7 +25,7 @@ import java.nio.charset.StandardCharsets;
* 适用于 Spring Boot 2.3.x + Spring Cloud Hoxton.SR12 环境。
*/
@Slf4j
-@Component
+//@Component
public class LoggingGlobalFilter implements GlobalFilter, Ordered {
@Override
diff --git a/src/main/java/com/sczx/gateway/filter/RequestLogGlobalFilter.java b/src/main/java/com/sczx/gateway/filter/RequestLogGlobalFilter.java
new file mode 100644
index 0000000..34efd69
--- /dev/null
+++ b/src/main/java/com/sczx/gateway/filter/RequestLogGlobalFilter.java
@@ -0,0 +1,96 @@
+package com.sczx.gateway.filter;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedHashSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Configuration
+@Slf4j
+public class RequestLogGlobalFilter implements GlobalFilter, Ordered {
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ ServerHttpRequest request = exchange.getRequest();
+ URI uri = request.getURI();
+ //String path = request.getPath().value();
+ String path = request.getPath().pathWithinApplication().value();//打印请求路径
+ String requestUrl = this.getOriginalRequestUrl(exchange);//打印请求url
+ String method = request.getMethodValue();
+ //cors
+ HttpHeaders headers = request.getHeaders();
+
+ log.info("--> method: {} url: {} header: {}", method, requestUrl, headers);
+ if ("POST".equals(method)) {
+ return DataBufferUtils.join(exchange.getRequest().getBody())
+ .flatMap(dataBuffer -> {
+ byte[] bytes = new byte[dataBuffer.readableByteCount()];
+ dataBuffer.read(bytes);
+ String bodyString = new String(bytes, StandardCharsets.UTF_8);
+ log.info("--> {}", bodyString);
+ //log.info("--> {}", formatStr(bodyString)); //formData
+ exchange.getAttributes().put("POST_BODY", bodyString);
+ DataBufferUtils.release(dataBuffer);
+ Flux cachedFlux = Flux.defer(() -> {
+ DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
+ return Mono.just(buffer);
+ });
+
+ ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(request) {
+ @Override
+ public Flux getBody() { return cachedFlux; }
+ };
+
+ return chain.filter(exchange.mutate().request(mutatedRequest).build());
+ });
+ } else if ("GET".equals(method)) {
+ MultiValueMap queryParams = request.getQueryParams();
+ log.info("请求参数:" + queryParams);
+ return chain.filter(exchange);
+ }
+ return chain.filter(exchange);
+ }
+ private String getOriginalRequestUrl(ServerWebExchange exchange) {
+ ServerHttpRequest req = exchange.getRequest();
+ LinkedHashSet uris = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
+ URI requestUri = uris.stream().findFirst().orElse(req.getURI());
+ MultiValueMap queryParams = req.getQueryParams();
+ //打印 /api/rest/feign/order/detail
+ // return UriComponentsBuilder.fromPath(requestUri.getRawPath()).queryParams(queryParams).build().toUriString();
+
+ return requestUri.toString(); // http://localhost:8091/api/rest/feign/order/detail
+ }
+
+ @Override
+ public int getOrder() {
+ return Ordered.LOWEST_PRECEDENCE;
+ }
+ /**
+ * 去掉FormData 空格,换行和制表符
+ */
+ private static String formatStr(String str){
+ if (str != null && str.length() > 0) {
+ Pattern p = Pattern.compile("\\s*|\t|\r|\n");
+ Matcher m = p.matcher(str);
+ return m.replaceAll("");
+ }
+ return str;
+ }
+}
diff --git a/src/main/java/com/sczx/gateway/filter/ResponseLogGlobalFilter.java b/src/main/java/com/sczx/gateway/filter/ResponseLogGlobalFilter.java
new file mode 100644
index 0000000..a6fb91e
--- /dev/null
+++ b/src/main/java/com/sczx/gateway/filter/ResponseLogGlobalFilter.java
@@ -0,0 +1,101 @@
+package com.sczx.gateway.filter;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.serializer.ValueFilter;
+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.context.annotation.Configuration;
+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.core.io.buffer.DefaultDataBufferFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Configuration
+public class ResponseLogGlobalFilter implements GlobalFilter, Ordered {
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ try {
+ ServerHttpResponse originalResponse = exchange.getResponse();
+ DataBufferFactory bufferFactory = originalResponse.bufferFactory();
+ HttpStatus statusCode = originalResponse.getStatusCode();
+ if (statusCode != HttpStatus.OK) {
+ return chain.filter(exchange);//降级处理返回数据
+ }
+ ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
+ @Override
+ public Mono writeWith(Publisher extends DataBuffer> body) {
+ if (body instanceof Flux) {
+ Flux extends DataBuffer> fluxBody = Flux.from(body);
+
+ return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
+
+ // 合并多个流集合,解决返回体分段传输
+ DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
+ DataBuffer buff = dataBufferFactory.join(dataBuffers);
+ byte[] content = new byte[buff.readableByteCount()];
+ buff.read(content);
+ DataBufferUtils.release(buff);//释放掉内存
+
+ //排除Excel导出,不是application/json不打印。若请求是上传图片则在最上面判断。
+ MediaType contentType = originalResponse.getHeaders().getContentType();
+ if (!MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) {
+ return bufferFactory.wrap(content);
+ }
+
+ // 构建返回日志
+ String joinData = new String(content);
+ String result = modifyBody(joinData);
+ List