注:Spring Cloud Gateway建立在Spring Framework 5,Project Reactor和Spring Boot 2之上,使用非阻塞API。gateway是用過webflux實作.關于搭建和配置我就不多說了。
以下我弄的一個例子,代碼:
@Component
public class AuthSignFilter implements GlobalFilter, Ordered {
static Logger logger = LoggerFactory.getLogger(AuthSignFilter.class);
/**
* 全域過濾器
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("==================");
String url = exchange.getRequest().getPath().pathWithinApplication().value();
logger.info("請求URL:"+url);
logger.info("method:"+exchange.getRequest().getMethod());
//獲取header
String appKey = exchange.getRequest().getHeaders().getFirst("token");
logger.info("appKey:"+appKey);
//請求的body
Flux<DataBuffer> flux = exchange.getRequest().getBody();
//這里如何決議出請求的報文呢?
return chain.filter(exchange.mutate().request(exchange.getRequest()).build());
}
@Override
public int getOrder() {
return -200;
}
}
關于flux<databuffer>的理解,DataBuffer是一個抽象結束ByteBuffer。問題是,如何在不必將整個流存盤在記憶體中(OutOfMemoryError)或寫入本地磁盤的情況下即時決議它? Netty ?
Flux<DataBuffer>我想在發送到輸出通道之前,截取請求里面的引數進行處理, 卡這里好久了,網上提供的材料都沒有特別有用。
希望看到的大拿,知道的或者有研究過的,給點建議或方法。或者我的思路是不是正確的,還是哪里出錯了,感激不盡
uj5u.com熱心網友回復:
這里有gateway的一些資料,有興趣的同學可以去看看http://www.iocoder.cn/categories/Spring-Cloud-Gateway/
uj5u.com熱心網友回復:
@Componentpublic class PostFilter extends AbstractNameValueGatewayFilterFactory {
private static final String X_APP_ID_HEADER = "X-app-id";
public static final String X_FORWARDED_FOR = "X-Forwarded-For";
@Override
public GatewayFilter apply(Consumer<NameValueConfig> consumer) {
return null;
}
@Override
public GatewayFilter apply(NameValueConfig nameValueConfig) {
return (exchange, chain) -> {
URI uri = exchange.getRequest().getURI();
URI ex = UriComponentsBuilder.fromUri(uri).build(true).toUri();
ServerHttpRequest request = exchange.getRequest().mutate().uri(ex).build();
if("POST".equalsIgnoreCase(request.getMethodValue())){//判斷是否為POST請求
Flux<DataBuffer> body = request.getBody();
AtomicReference<String> bodyRef = new AtomicReference<>();//快取讀取的request body資訊
body.subscribe(dataBuffer -> {
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(dataBuffer.asByteBuffer());
DataBufferUtils.release(dataBuffer);
bodyRef.set(charBuffer.toString());
});//讀取request body到快取
String bodyStr = bodyRef.get();//獲取request body
System.out.println(bodyStr);//這里是我們需要做的操作
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());
};
}
protected 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 String name() {
return null;
}
@Override
public ServerHttpRequest.Builder mutate(ServerHttpRequest request) {
return null;
}
@Override
public ShortcutType shortcutType() {
return null;
}
@Override
public String shortcutFieldPrefix() {
return null;
}
}
參考 https://www.cnblogs.com/cafebabe-yun/p/9328554.html
uj5u.com熱心網友回復:
下面的代碼能讓你將buffer轉為String,https://blog.csdn.net/tianyaleixiaowu/article/details/83348100我會寫多篇來詳細講post的處理
Flux<DataBuffer> body = exchange.getRequest().getBody();
body.subscribe(buffer -> {
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
DataBufferUtils.release(buffer);
try {
String bodyString = new String(bytes, "utf-8");
System.out.println(bodyString);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
});
uj5u.com熱心網友回復:
這個問題可以參考這個,先配置一個readBody的預言器,然后從快取中獲取,http://blog.51cto.com/thinklili/2329184uj5u.com熱心網友回復:
import com.github.wxiaoqi.security.gate.utils.StringUtil;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 日志全域過濾器
*
* @author duwei
* @version V1.0
* @date 2019/12/12 11:23 AM
*/
@Configuration
public class LogGlobalFilter implements GlobalFilter, Ordered {
private static Logger logger = LoggerFactory.getLogger(LogGlobalFilter.class);
@Override
public int getOrder() {
return -5;
}
/**
* Process the Web request and (optionally) delegate to the next
* {@code WebFilter} through the given {@link GatewayFilterChain}.
*
* @param exchange the current server exchange
* @param chain provides a way to delegate to the next filter
* @return {@code Mono<Void>} to indicate when request processing is complete
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String method = request.getMethodValue();
String contentType = request.getHeaders().getFirst("Content-Type");
if ("POST".equals(method.toUpperCase())) {
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
try {
String bodyString = new String(bytes, "utf-8");
logtrace(exchange, bodyString);
exchange.getAttributes().put("POST_BODY", bodyString);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
DataBufferUtils.release(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
DataBuffer buffer = exchange.getResponse().bufferFactory()
.wrap(bytes);
return Mono.just(buffer);
});
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
return chain.filter(exchange.mutate().request(mutatedRequest)
.build());
});
} else if ("GET".equals(method.toUpperCase())) {
Map m = request.getQueryParams();
logtrace(exchange, StringUtil.mapToString(m, ",", "="));
}
return chain.filter(exchange);
}
/**
* 日志資訊
*
* @param exchange
* @param param 請求引數
*/
private void logtrace(ServerWebExchange exchange, String param) {
ServerHttpRequest serverHttpRequest = exchange.getRequest();
String path = serverHttpRequest.getURI().getPath();
String method = serverHttpRequest.getMethodValue();
String headers = serverHttpRequest.getHeaders().entrySet()
.stream()
.map(entry -> " " + entry.getKey() + ": [" + String.join(";", entry.getValue()) + "]")
.collect(Collectors.joining("\n"));
logger.info("\n" + "---------------- ---------------- ---------------->>\n" +
"HttpMethod : {}\n" +
"Uri : {}\n" +
"Param : {}\n" +
"Headers : \n" +
"{}\n" +
"\"<<---------------- ---------------- ----------------"
, method, path, param, headers);
}
}
uj5u.com熱心網友回復:
您好,如何解決讀取body的, 我家readbody后 get請求就不能用了轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/93207.html
標籤:Java相關
上一篇:SpringMVC,配置了表單驗證的國際化資源(不使用JSR303的message屬性),不使用< form:errors / >標簽,如何獲取錯誤資訊?
下一篇:IText7 實作圖片拷貝問題
