spring cloud gateway中如何讀取請(qǐng)求參數(shù)
import lombok.extern.slf4j.Slf4j;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.core.io.buffer.DataBuffer;import org.springframework.core.io.buffer.DataBufferUtils;import org.springframework.http.HttpMethod;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.nio.charset.StandardCharsets;import java.util.Map;import java.util.stream.Collectors; /** * @author MinWeikai * @date 2019-12-20 18:09:39 */@Slf4j@Componentpublic class LoggerFilter implements GlobalFilter { @Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();String method = request.getMethodValue(); if (HttpMethod.POST.matches(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);logtrace(exchange, bodyString);exchange.getAttributes().put('POST_BODY', bodyString);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()) {@Overridepublic Flux<DataBuffer> getBody() {return cachedFlux;}};return chain.filter(exchange.mutate().request(mutatedRequest).build());});} else if (HttpMethod.GET.matches(method)) {Map m = request.getQueryParams();logtrace(exchange, m.toString());}return chain.filter(exchange);} /** * 日志信息 * * @param exchange * @param param 請(qǐng)求參數(shù) */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'));log.info('n' + '---------------- ---------------- ---------------->>n' +'HttpMethod : {}n' +'Uri: {}n' +'Param : {}n' +'Headers : n' +'{}n' +''<<---------------- ---------------- ----------------', method, path, param, headers);} }3. 測(cè)試輸出,我這邊測(cè)試沒(méi)有問(wèn)題,日志正常輸出
在繼承AbstractGatewayFilterFactory的過(guò)濾器中
GET請(qǐng)求添加參數(shù)// 參考api文檔中GatewapFilter中“添加請(qǐng)求參數(shù)攔截器”:AddRequestParameterGatewayFilterFactory.java //記錄日志 //logger.info('全局參數(shù)處理: {} url:{} 參數(shù):{}',method.toString(),serverHttpRequest.getURI().getRawPath(),newRequestQueryParams.toString()); // 獲取原參數(shù) URI uri = serverHttpRequest.getURI(); StringBuilder query = new StringBuilder(); String originalQuery = uri.getRawQuery(); if (org.springframework.util.StringUtils.hasText(originalQuery)) {query.append(originalQuery);if (originalQuery.charAt(originalQuery.length() - 1) != ’&’) { query.append(’&’);} } // 添加查詢參數(shù) query.append(ServiceConstants.COMMON_PARAMETER_ENTERPRISEID+'='+authenticationVO.getEnterpriseId() +'&'+ServiceConstants.COMMON_PARAMETER_USERID+'='+authenticationVO.getUserId()); // 替換查詢參數(shù) URI newUri = UriComponentsBuilder.fromUri(uri) .replaceQuery(query.toString()) .build(true) .toUri(); ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build(); return chain.filter(exchange.mutate().request(request).build());POST請(qǐng)求添加參數(shù)
//從請(qǐng)求里獲取Post請(qǐng)求體 String bodyStr = resolveBodyFromRequest(serverHttpRequest); String userId = '123';// 這種處理方式,必須保證post請(qǐng)求時(shí),原始post表單必須有數(shù)據(jù)過(guò)來(lái),不然會(huì)報(bào)錯(cuò) if (StringUtils.isEmpty(bodyStr)) {logger.error('請(qǐng)求異常:{} POST請(qǐng)求必須傳遞參數(shù)', serverHttpRequest.getURI().getRawPath());ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.BAD_REQUEST);return response.setComplete(); } //application/x-www-form-urlencoded和application/json才添加參數(shù) //其他上傳文件之類的,不做參數(shù)處理,因?yàn)槲募魈砑訁?shù),文件原格式就會(huì)出問(wèn)題了 /* if (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equalsIgnoreCase(contentType)) {// 普通鍵值對(duì),增加參數(shù)bodyStr = String.format(bodyStr+'&%s=%s&%s=%s',ServiceConstants.COMMON_PARAMETER_ENTERPRISEID,authenticationVO.getEnterpriseId(),ServiceConstants.COMMON_PARAMETER_USERID,authenticationVO.getUserId()); }*/ // 新增body參數(shù) if (MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType)) {JSONObject jsonObject = new JSONObject(bodyStr);jsonObject.put('userId', userId);bodyStr = jsonObject.toString(); } //記錄日志 logger.info('全局參數(shù)處理: {} url:{} 參數(shù):{}', method.toString(), serverHttpRequest.getURI().getRawPath(), bodyStr); //下面的將請(qǐng)求體再次封裝寫(xiě)回到request里,傳到下一級(jí),否則,由于請(qǐng)求體已被消費(fèi),后續(xù)的服務(wù)將取不到值 URI uri = serverHttpRequest.getURI(); URI newUri = UriComponentsBuilder.fromUri(uri).build(true).toUri(); ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build(); DataBuffer bodyDataBuffer = stringBuffer(bodyStr); Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer); // 定義新的消息頭 HttpHeaders headers = new HttpHeaders(); headers.putAll(exchange.getRequest().getHeaders()); // 添加消息頭// headers.set(ServiceConstants.SHIRO_SESSION_PRINCIPALS,GsonUtils.toJson(authenticationVO)); // 由于修改了傳遞參數(shù),需要重新設(shè)置CONTENT_LENGTH,長(zhǎng)度是字節(jié)長(zhǎng)度,不是字符串長(zhǎng)度 int length = bodyStr.getBytes().length; headers.remove(HttpHeaders.CONTENT_LENGTH); headers.setContentLength(length); // 設(shè)置CONTENT_TYPE if (StringUtils.isEmpty(contentType)) {headers.set(HttpHeaders.CONTENT_TYPE, contentType); } // 由于post的body只能訂閱一次,由于上面代碼中已經(jīng)訂閱過(guò)一次body。所以要再次封裝請(qǐng)求到request才行,不然會(huì)報(bào)錯(cuò)請(qǐng)求已經(jīng)訂閱過(guò) request = new ServerHttpRequestDecorator(request) {@Overridepublic HttpHeaders getHeaders() { long contentLength = headers.getContentLength(); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.putAll(super.getHeaders()); if (contentLength > 0) {httpHeaders.setContentLength(contentLength); } else {// TODO: this causes a ’HTTP/1.1 411 Length Required’ on httpbin.orghttpHeaders.set(HttpHeaders.TRANSFER_ENCODING, 'chunked'); } return httpHeaders;}@Overridepublic Flux<DataBuffer> getBody() { return bodyFlux;} }; //封裝request,傳給下一級(jí) request.mutate().header(HttpHeaders.CONTENT_LENGTH, Integer.toString(bodyStr.length())); return chain.filter(exchange.mutate().request(request).build()); /** * 從Flux<DataBuffer>中獲取字符串的方法 * @return 請(qǐng)求體 */ private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {//獲取請(qǐng)求體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 bodyreturn bodyRef.get(); }
/*** 字符串轉(zhuǎn)DataBuffer* @param value* @return*/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;}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. python web框架的總結(jié)2. Python如何進(jìn)行時(shí)間處理3. 詳解Python模塊化編程與裝飾器4. python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)5. html小技巧之td,div標(biāo)簽里內(nèi)容不換行6. 以PHP代碼為實(shí)例詳解RabbitMQ消息隊(duì)列中間件的6種模式7. python logging 重復(fù)寫(xiě)日志問(wèn)題解決辦法詳解8. Python中l(wèi)ogger日志模塊詳解9. python裝飾器三種裝飾模式的簡(jiǎn)單分析10. Python實(shí)現(xiàn)迪杰斯特拉算法過(guò)程解析
