重写请求体处理类:
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import com.byd.dilink.api.endecrypt.dto.ClubIdentifierDto;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;
@Slf4j
@Component
public class TestRewriteRequestBody implements RewriteFunction<String, String> {
@Override
public Publisher<String> apply(ServerWebExchange serverWebExchange, String body) {
if (!StringUtils.isEmpty(body)) {
// 自定义的myModify方法对body处理,自定义返回的java类MyBody
MyBody mybody = myModify(body);
log.info("入参body={}", JSON.toJSONString(mybody));
//放用户标识到请求头部
serverWebExchange.getAttributes().put("identifier", clubIdentifierDto.getIdentifier());
return Mono.just(JSON.toJSONString(mybody));
}
return Mono.empty();
}
}
重写响应体处理类:
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Slf4j
@Component
public class TestRewriteResponseBody implements RewriteFunction<String, String> {
@Override
public Publisher<String> apply(ServerWebExchange serverWebExchange, String resBody) {
String identifer = (String) serverWebExchange.getAttributes().get("identifier");
if (StringUtils.isNotBlank(resBody) && identifer != null) {
// 自定义的myResponeModify方法对body处理,自定义返回的java类MyBody
resBody = myResponeModify(body, identifer);
}
serverWebExchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
return Mono.just(resBody);
}
}
请求头部修改:
import com.byd.dilink.api.common.utils.RandomStringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import java.util.function.Consumer;
@Component
@Slf4j
public class TestRequestHeaderGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
Consumer<HttpHeaders> httpHeaders = httpHeader -> {
String nonce = RandomStringUtils.randomStr(16);
String curTime = String.valueOf(System.currentTimeMillis() / 1000);
httpHeader.setContentType(MediaType.APPLICATION_JSON);
httpHeader.set("Nonce", nonce);
httpHeader.set("Curtime", curTime);
};
ServerHttpRequest request = exchange.getRequest().mutate().headers(httpHeaders).build();
return chain.filter(exchange.mutate().request(request).build());
};
}
}
日志收集处理:
import java.net.URI;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class RequestBodyLogGatewayFilterFactory
extends AbstractGatewayFilterFactory<RequestBodyLogGatewayFilterFactory.Config> {
public RequestBodyLogGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
Route gatewayUrl = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
URI uri = gatewayUrl.getUri();
String instance = uri.getAuthority();
ServerHttpRequest request = exchange.getRequest();
String URIPath = request.getURI().toString();
String method = request.getMethodValue();
return chain.filter(exchange);
};
}
public static class Config {}
}
route配置文件:
[{
"filters": [{
"name": "RequestBodyLog"
},
{
"name": "ModifyRequestBody",
"args": {
"inClass": "#{T(String)}",
"outClass": "#{T(String)}",
"rewriteFunction": "#{@testRewriteRequestBody}"
}
},
{
"name": "TestRequestHeader"
},
{
"name": "RewritePath",
"args": {
"_genkey_0": "/test/(?<segment>.*)",
"_genkey_1": "/ceshi/$\\{segment}"
}
},
{
"name": "ModifyResponseBody",
"args": {
"inClass": "#{T(String)}",
"outClass": "#{T(String)}",
"rewriteFunction": "#{@testRewriteResponseBody}"
}
}
],
"id": "test",
"order": 0,
"predicates": [{
"args": {
"_genkey_0": "/test/**"
},
"name": "Path"
}, {
"args": {
"param": "s",
"regexp": "myForInterfaceApp.myforwardInformationFlow"
},
"name": "Query"
}, {
"args": {
"inClass": "#{T(String)}",
"predicate": "#{@logPredicate}"
},
"name": "ReadBodyPredicateFactory"
}],
"uri": "http://127.0.0.1/"
},
{
"filters": [],
"id": "index",
"order": 0,
"predicates": [
{
"args": {
"pattern": "/",
"pattern1": "/favicon.ico"
},
"name": "Path"
}
],
"uri": "lb://app"
}
]
动态监听nacos配置路由
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import reactor.core.publisher.Mono;
/**
* 另外一种方式,监听nacos配置变化更新路由
*/
@Component
public class NacosDynamicRouteService implements ApplicationEventPublisherAware {
private String dataId = "route";
private String group = "DEFAULT_GROUP";
@Value("${spring.cloud.nacos.config.server-addr}")
private String serverAddr;
@Value("${spring.profiles.active}")
private String profiles;
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private NacosConfigProperties nacosConfigProperties;
private ApplicationEventPublisher applicationEventPublisher;
private static final List<String> ROUTE_LIST = new ArrayList<>();
@PostConstruct
public void dynamicRouteByNacosListener() throws NacosException {
ConfigService configService = NacosFactory.createConfigService(serverAddr);
String routeFileName = dataId + "-" + profiles;
configService.getConfig(routeFileName, group, 5000);
configService.addListener(routeFileName, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
clearRoute();
List<RouteDefinition> gatewayRouteDefinitions =
JSONObject.parseArray(configInfo, RouteDefinition.class);
for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
addRoute(routeDefinition);
}
publish();
}
@Override
public Executor getExecutor() {
return null;
}
});
initRoute(configService, routeFileName);
}
private void initRoute(ConfigService configService, String routeFileName) throws NacosException {
String content = configService.getConfig(routeFileName, group, 5000);
clearRoute();
List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(content, RouteDefinition.class);
for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
addRoute(routeDefinition);
}
}
private void clearRoute() {
for (String id : ROUTE_LIST) {
this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
}
ROUTE_LIST.clear();
}
private void addRoute(RouteDefinition definition) {
try {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
ROUTE_LIST.add(definition.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
private void publish() {
this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}