欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring cloud gateway中如何讀取請(qǐng)求參數(shù)

 更新時(shí)間:2021年07月15日 11:23:48   作者:影落離風(fēng)  
這篇文章主要介紹了spring cloud gateway中如何讀取請(qǐng)求參數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

spring cloud gateway讀取請(qǐng)求參數(shù)

1. 我的版本:

  • spring-cloud:Hoxton.RELEASE
  • spring-boot:2.2.2.RELEASE
  • spring-cloud-starter-gateway

2. 請(qǐng)求日志

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
@Component
public class LoggerFilter implements GlobalFilter {
 
	@Override
	public 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()) {
							@Override
							public 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è)試沒有問題,日志正常輸出

gateway網(wǎng)關(guān)轉(zhuǎn)發(fā)請(qǐng)求添加參數(shù)

在繼承AbstractGatewayFilterFactory的過濾器中

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ù)過來,不然會(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ì)出問題了
                   /* 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)求體再次封裝寫回到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)訂閱過一次body。所以要再次封裝請(qǐng)求到request才行,不然會(huì)報(bào)錯(cuò)請(qǐng)求已經(jīng)訂閱過
                    request = new ServerHttpRequestDecorator(request) {
                        @Override
                        public 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.org
                                httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                            }
                            return httpHeaders;
                        }
                        @Override
                        public 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 body
        return 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è)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Spring中Spel表達(dá)式和el表達(dá)式的區(qū)別

    詳解Spring中Spel表達(dá)式和el表達(dá)式的區(qū)別

    在?Java?開發(fā)中,表達(dá)式語(yǔ)言是一種強(qiáng)大的工具,而SpEL?表達(dá)式與EL?表達(dá)式是我們常常遇到兩種表達(dá)式語(yǔ)言,下面我們就來看看它們的具體使用與區(qū)別吧
    2023-07-07
  • 關(guān)于HashMap 并發(fā)時(shí)會(huì)引起死循環(huán)的問題解析

    關(guān)于HashMap 并發(fā)時(shí)會(huì)引起死循環(huán)的問題解析

    JDK1.8之前采用頭插,即在鏈表結(jié)構(gòu)上每次都把數(shù)據(jù)放在鏈表頭部。JDK1.8采用尾插方法,很多朋友在學(xué)習(xí)Java并發(fā)容器和框架時(shí),看到為什么要使用ConcurrentHashMap時(shí)不知道究其原因,今天小編通過本文給大家介紹下HashMap 并發(fā)死循環(huán)問題,一起看看吧
    2021-05-05
  • spring boot+自定義 AOP 實(shí)現(xiàn)全局校驗(yàn)的實(shí)例代碼

    spring boot+自定義 AOP 實(shí)現(xiàn)全局校驗(yàn)的實(shí)例代碼

    最近公司重構(gòu)項(xiàng)目,重構(gòu)為最熱的微服務(wù)框架 spring boot, 重構(gòu)的時(shí)候遇到幾個(gè)可以統(tǒng)一處理的問題。這篇文章主要介紹了spring boot+自定義 AOP 實(shí)現(xiàn)全局校驗(yàn) ,需要的朋友可以參考下
    2019-04-04
  • springboot異步處理@NotBlank或@NotNull注釋校驗(yàn)不生效問題

    springboot異步處理@NotBlank或@NotNull注釋校驗(yàn)不生效問題

    這篇文章主要介紹了springboot異步處理@NotBlank或@NotNull注釋校驗(yàn)不生效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • JAVA實(shí)現(xiàn)監(jiān)測(cè)tomcat是否宕機(jī)及控制重啟的方法

    JAVA實(shí)現(xiàn)監(jiān)測(cè)tomcat是否宕機(jī)及控制重啟的方法

    這篇文章主要介紹了JAVA實(shí)現(xiàn)監(jiān)測(cè)tomcat是否宕機(jī)及控制重啟的方法,可實(shí)現(xiàn)有效的檢測(cè)及控制tomcat服務(wù)器運(yùn)行,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-08-08
  • Java使用注解和反射簡(jiǎn)化編程的方法示例

    Java使用注解和反射簡(jiǎn)化編程的方法示例

    這篇文章主要介紹了Java使用注解和反射簡(jiǎn)化編程的方法,結(jié)合實(shí)例形式分析了java使用注解和反射調(diào)用大量函數(shù)簡(jiǎn)化編程的相關(guān)操作技巧,需要的朋友可以參考下
    2019-10-10
  • Java中wait與sleep的區(qū)別講解(wait有參及無參區(qū)別)

    Java中wait與sleep的區(qū)別講解(wait有參及無參區(qū)別)

    這篇文章主要介紹了Java中wait與sleep的講解(wait有參及無參區(qū)別),通過代碼介紹了wait()?與wait(?long?timeout?)?區(qū)別,wait(0)?與?sleep(0)區(qū)別,需要的朋友可以參考下
    2022-04-04
  • SpringMVC中的異常處理機(jī)制詳解

    SpringMVC中的異常處理機(jī)制詳解

    SpringMVC提供了基于xml和基于注解的異常處理機(jī)制,一般情況下兩者都要進(jìn)行配置,xml異常處理機(jī)制主要用于處理xml方式產(chǎn)生的異常,注解異常處理機(jī)制主要用于處理基于注解方式產(chǎn)生的異常,這篇文章主要介紹了SpringMVC中的異常處理機(jī)制,需要的朋友可以參考下
    2024-05-05
  • Spring多定時(shí)任務(wù)@Scheduled執(zhí)行阻塞問題解決

    Spring多定時(shí)任務(wù)@Scheduled執(zhí)行阻塞問題解決

    這篇文章主要介紹了Spring多定時(shí)任務(wù)@Scheduled執(zhí)行阻塞問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 一文教會(huì)你如何從0到1搭建一個(gè)SpringBoot項(xiàng)目

    一文教會(huì)你如何從0到1搭建一個(gè)SpringBoot項(xiàng)目

    今天剛好學(xué)習(xí)到SpringBoot,就順便記錄一下吧,下面這篇文章主要給大家介紹了關(guān)于如何從0到1搭建一個(gè)SpringBoot項(xiàng)目的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01

最新評(píng)論