好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

spring cloud gateway中如何读取请求参数

spring cloud gateway读取请求参数

1. 我的版本:

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

2. 请求日志

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

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    请求参数

      */

     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. 测试输出,我这边测试没有问题,日志正常输出

gateway网关转发请求添加参数

在继承AbstractGatewayFilterFactory的过滤器中

GET请求添加参数

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

// 参考api文档中GatewapFilter中[添加请求参数拦截器]:AddRequestParameterGatewayFilterFactory.java

 

             //记录日志

             //logger.info("全局参数处理: {} url:{} 参数:{}",method.toString(),serverHttpRequest.getURI().getRawPath(),newRequestQueryParams.toString());

             // 获取原参数

             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( '&' );

                 }

             }

             // 添加查询参数

             query.append(ServiceConstants.COMMON_PARAMETER_ENTERPRISEID+ "=" +authenticationVO.getEnterpriseId()

                     + "&" +ServiceConstants.COMMON_PARAMETER_USERID+ "=" +authenticationVO.getUserId());

 

             // 替换查询参数

             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请求添加参数

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

//从请求里获取Post请求体

                     String bodyStr = resolveBodyFromRequest(serverHttpRequest);

                     String userId = "123" ;

// 这种处理方式,必须保证post请求时,原始post表单必须有数据过来,不然会报错

                     if (StringUtils.isEmpty(bodyStr)) {

                         logger.error( "请求异常:{} POST请求必须传递参数" , serverHttpRequest.getURI().getRawPath());

                         ServerHttpResponse response = exchange.getResponse();

                         response.setStatusCode(HttpStatus.BAD_REQUEST);

                         return response.setComplete();

                     }

                     //application/x-www-form-urlencoded和application/json才添加参数

                     //其他上传文件之类的,不做参数处理,因为文件流添加参数,文件原格式就会出问题了

                    /* if (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equalsIgnoreCase(contentType)) {

                         // 普通键值对,增加参数

                         bodyStr = String.format(bodyStr+"&%s=%s&%s=%s",ServiceConstants.COMMON_PARAMETER_ENTERPRISEID,authenticationVO.getEnterpriseId()

                                 ,ServiceConstants.COMMON_PARAMETER_USERID,authenticationVO.getUserId());

                     }*/

                     // 新增body参数

                     if (MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType)) {

                         JSONObject jsonObject = new JSONObject(bodyStr);

                         jsonObject.put("userId", userId);

                         bodyStr = jsonObject.toString();

                     }

                     //记录日志

                     logger.info("全局参数处理: {} url:{} 参数:{}", method.toString(), serverHttpRequest.getURI().getRawPath(), bodyStr);

                     //下面的将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值

                     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));

                     // 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度

                     int length = bodyStr.getBytes().length;

                     headers.remove(HttpHeaders.CONTENT_LENGTH);

                     headers.setContentLength(length);

                     // 设置CONTENT_TYPE

                     if (StringUtils.isEmpty(contentType)) {

                         headers.set(HttpHeaders.CONTENT_TYPE, contentType);

                     }

                     // 由于post的body只能订阅一次,由于上面代码中已经订阅过一次body。所以要再次封装请求到request才行,不然会报错请求已经订阅过

                     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,传给下一级

                     request.mutate().header(HttpHeaders.CONTENT_LENGTH, Integer.toString(bodyStr.length()));

                     return chain.filter(exchange.mutate().request(request).build());

    /**

      * 从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();

     }

?

1

2

3

4

5

6

7

8

9

10

11

12

/**

* 字符串转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;

}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/weixin_41187876/article/details/103637035

查看更多关于spring cloud gateway中如何读取请求参数的详细内容...

  阅读:20次