Spring Cloud Gateway全局GlobalFilter获取请求参数
创建自定义的GlobalFilter
可以实现日志处理、认证鉴权等,用户发起Get、Post请求,经过网关gateway,gateway的GlobalFilter
进行拦截,获取参数,处理并包装,转到下一级,这里就涉及获取请求参数的问题。
Get请求
@Component
public class AuthSignFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (token == null || token.isEmpty()) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
Post请求
Post请求的传参获取相对比较麻烦一些,gateway采用了webflux的方式来封装的请求体。
我们知道Post常用的两种传参content-type
是application/x-www-form-urlencoded
和application/json
,无论是application/x-www-form-urlencoded
和application/json
都可以通过如下方式
import io.netty.buffer.ByteBufAllocator;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
@Component
public class AuthSignFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest serverHttpRequest = exchange.getRequest();
String method = serverHttpRequest.getMethodValue();
if ("POST".equals(method)) {
//从请求里获取Post请求体
String bodyStr = resolveBodyFromRequest(serverHttpRequest);
//TODO 得到Post请求的请求参数后,做你想做的事
//下面的将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值
URI uri = serverHttpRequest.getURI();
ServerHttpRequest request = serverHttpRequest.mutate().uri(uri).build();
DataBuffer bodyDataBuffer = stringBuffer(bodyStr);
Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);
request = new ServerHttpRequestDecorator(request) {
@Override
public Flux<DataBuffer> getBody() {
return bodyFlux;
}
};
//封装request,传给下一级
return chain.filter(exchange.mutate().request(request).build());
} else if ("GET".equals(method)) {
Map requestQueryParams = serverHttpRequest.getQueryParams();
//TODO 得到Get请求的请求参数后,做你想做的事
return chain.filter(exchange);
}
return chain.filter(exchange);
}
/**
* 从Flux<DataBuffer>中获取字符串的方法
* @return 请求体
*/
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
//获取请求体
Flux<DataBuffer> body = serverHttpRequest.getBody();
AtomicReference<String> bodyRef = new AtomicReference<>();
body.subscribe(buffer -> {
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
DataBufferUtils.release(buffer);
bodyRef.set(charBuffer.toString());
});
//获取request body
return bodyRef.get();
}
private DataBuffer stringBuffer(String value) {
byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
buffer.write(bytes);
return buffer;
}
@Override
public int getOrder() {
return 0;
}
}
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/26/spring-cloud-gateway-global-globalfilter-get-request-parameters/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论