zoukankan      html  css  js  c++  java
  • java getway springcloud 记录请求数据

    java getway springcloud 记录请求数据,兼容post请求无参数和response返回无参数

    方式1

    import com.icar.web.icarutils.util.ClientUtil;
    import com.icar.web.icarutils.util.IdWorkerUtil;
    import lombok.AllArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    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.http.HttpHeaders;
    import org.springframework.http.MediaType;
    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.io.UnsupportedEncodingException;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    @Component
    @Slf4j
    public class HttpRequestGlobalFilter implements GlobalFilter, Ordered {
    
        @Value("${xxxx.collectrequestlogs:false}")
        private Boolean collectrequestlog;
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            ServerHttpRequest request = exchange.getRequest();
            String accessId=new IdWorkerUtil().nextId()+"";
           try{
               String method = request.getMethodValue();
               String contentType = request.getHeaders().getFirst("Content-Type");
    
    
               if ("POST".equals(method)&&(contentType!=null&&contentType.equals(MediaType.APPLICATION_JSON_VALUE))){  //&& contentType.startsWith("multipart/form-data")
                    if(collectrequestlog){
                        return  SavePostRequestDataBody(exchange, chain,request,method,contentType,accessId);
                    }
                    else {
                        SaveLogData(exchange,"",accessId);
                    }
               }
               else if ("GET".equals(method)) {
                   Map requestQueryParams = request.getQueryParams();
                   String param=requestQueryParams.toString();
                   SaveLogData(exchange,param,accessId);
               }else{
                   SaveLogData(exchange,"",accessId);
               }
               ServerHttpRequest.Builder requestBuilder = request.mutate();
               //requestBuilder.build().getHeaders().set("userId",userId);
               requestBuilder.headers(k -> k.set("accessId", accessId));
               ServerHttpRequest builder = requestBuilder.build();
               return chain.filter(exchange.mutate().request(builder.mutate().build()).build());
           }
           catch (Exception e){
               log.error("",e);
           }
            ServerHttpRequest.Builder requestBuilder = request.mutate();
            //requestBuilder.build().getHeaders().set("userId",userId);
            requestBuilder.headers(k -> k.set("accessId", accessId));
            ServerHttpRequest builder = requestBuilder.build();
            return chain.filter(exchange.mutate().request(builder.mutate().build()).build());
        }
    
        /**
         * 获取post请求数据
         * @param exchange
         * @param method
         * @param contentType
         * @param accessId
         * @return
         */
        private Mono<Void> SavePostRequestDataBody(ServerWebExchange exchange, GatewayFilterChain chain, ServerHttpRequest request, String method, String contentType, String accessId) {
            //判断请求是否有参数
            HttpHeaders headers = request.getHeaders();
            long contentLength = headers.getContentLength();
            //当请求体里面没有任何数据的话不用后面的获取数据步骤
            if (contentLength < 1) {
                SaveLogData(exchange,"",accessId);
                ServerHttpRequest.Builder requestBuilder = request.mutate();
                //requestBuilder.build().getHeaders().set("userId",userId);
                requestBuilder.headers(k -> k.set("accessId", accessId));
                ServerHttpRequest builder = requestBuilder.build();
                return chain.filter(exchange.mutate().request(builder.mutate().build()).build());
            }
            Flux<DataBuffer> flux =exchange.getRequest().getBody();
            Mono<Void>  mono=   DataBufferUtils.join(flux)
                    .flatMap(dataBuffer -> {
    
                        try
                        {
                            byte[] bytes = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(bytes);
    
                            try {
                                if(contentType==null||!contentType.startsWith("application/json")){   //multipart/form-data
                                    SaveLogData(exchange,"",accessId);
                                }else{
                                    String bodyString = new String(bytes, "utf-8");
                                    SaveLogData(exchange,bodyString,accessId);
                                }
    
                                //log.info(bodyString);
                                //exchange.getAttributes().put("POST_BODY",bodyString);
                            } catch (UnsupportedEncodingException e) {
                                log.error("",e);
                            }
                            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;
                                }
                            };
                            ServerHttpRequest.Builder requestBuilder = mutatedRequest.mutate();
                            requestBuilder.headers(k -> k.set("accessId", accessId));
                            ServerHttpRequest builder = requestBuilder.build();
    
                            return chain.filter(exchange.mutate().request(mutatedRequest)
                                    .build());
                        }
                        catch (Exception e){
                            SaveLogData(exchange,"",accessId);
                            log.error("",e);
                        }finally {
    
                        }
                        return  null;
                    });
            return  mono;
        }
    
        private void SaveLogData(ServerWebExchange exchange,String param,String accessId) {
            try{
                ServerHttpRequest request= exchange.getRequest();
                String ip = ClientUtil.getIPAddress(request);
                String method = request.getMethodValue();
                String url = request.getURI().toString();
                String headers = request.getHeaders().entrySet()
                        .stream()
                        .map(entry -> "            " + entry.getKey() + ": [" + String.join(";", entry.getValue()) + "]")
                        .collect(Collectors.joining("
    "));
                log.info("
    " + "-------------------------------------------------------------------------------->>
    " +
                                "locationtype: request
    " +
                                "Url: {}
    " +
                                "HttpMethod: {}
    " +
                                "IP: {}
    " +
                                "accessId: {}
    " +
                                "Param: {}
    " +
                                "Headers: 
    " +
                                "{}
    " +
                                ""<<--------------------------------------------------------------------------------"
                        , method, url, ip,accessId,param, headers);
    
            }
            catch (Exception e){
                log.error("",e);
            }
        }
    
        @Override
        public int getOrder() {
            return -200;
        }
    }

    方式二

    import lombok.Data;
    import org.springframework.http.HttpHeaders;
    import org.springframework.util.LinkedMultiValueMap;
    import org.springframework.util.MultiValueMap;
    
    /**
     * 网关上下文
     */
    @Data
    public class GatewayContext {
    
        public static final String CACHE_GATEWAY_CONTEXT = "cacheGatewayContext";
    
        /**
         * cache headers
         */
        private HttpHeaders headers;
    
        /**
         * baseHeader
         */
        private HttpHeaders  baseHeader;
    
        /**
         * cache json body
         */
        private String cacheBody;
        /**
         * cache formdata
         */
        private MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
    
        /**
         * ipAddress
         */
        private String  ipAddress;
    
        /**
         * path
         */
        private String path;
    
    }
    import com.icar.web.gateway.entity.GatewayContext;
    import io.netty.buffer.ByteBufAllocator;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.core.io.ByteArrayResource;
    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.HttpHeaders;
    import org.springframework.http.MediaType;
    import org.springframework.http.codec.HttpMessageReader;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.stereotype.Component;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.reactive.function.server.HandlerStrategies;
    import org.springframework.web.reactive.function.server.ServerRequest;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    import java.util.List;
    import java.util.Map;
    
    
    /**
     * 请求内容存储 处理请求内容 内容放在gatewayContext中
     *//*
     * @author kam
     *
     *         <p>
     *         请求内容存储 处理请求内容 内容放在gatewayContext中
     *         </p>
     */
    
    @Component
    @Slf4j
    public class RequestCoverFilter implements GlobalFilter, Ordered {
    
    /**
         * default HttpMessageReader
         */
    
        private static final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();
    
        /* * ReadFormData
         *
         * @param exchange
         * @param chain
         * @return
         */
    
        private Mono<Void> readFormData(ServerWebExchange exchange, GatewayFilterChain chain,
            GatewayContext gatewayContext) {
            final ServerHttpRequest request = exchange.getRequest();
            HttpHeaders headers = request.getHeaders();
    
            return exchange.getFormData().doOnNext(multiValueMap -> {
                gatewayContext.setFormData(multiValueMap);
                log.debug("[GatewayContext]Read FormData:{}", multiValueMap);
            }).then(Mono.defer(() -> {
                Charset charset = headers.getContentType().getCharset();
                charset = charset == null ? StandardCharsets.UTF_8 : charset;
                String charsetName = charset.name();
                MultiValueMap<String, String> formData = gatewayContext.getFormData();
    
    /**
                 * formData is empty just return
                 */
    
                if (null == formData || formData.isEmpty()) {
                    return chain.filter(exchange);
                }
                StringBuilder formDataBodyBuilder = new StringBuilder();
                String entryKey;
                List<String> entryValue;
                try {
    /**
                     * repackage form data
                     */
    
                    for (Map.Entry<String, List<String>> entry : formData.entrySet()) {
                        entryKey = entry.getKey();
                        entryValue = entry.getValue();
                        if (entryValue.size() > 1) {
                            for (String value : entryValue) {
                                formDataBodyBuilder.append(entryKey).append("=")
                                    .append(URLEncoder.encode(value, charsetName)).append("&");
                            }
                        } else {
                            formDataBodyBuilder.append(entryKey).append("=")
                                .append(URLEncoder.encode(entryValue.get(0), charsetName)).append("&");
                        }
                    }
                } catch (UnsupportedEncodingException e) {
                    // ignore URLEncode Exception
                }
    
    /**
                 * substring with the last char '&'
                 */
    
                String formDataBodyString = "";
                if (formDataBodyBuilder.length() > 0) {
                    formDataBodyString = formDataBodyBuilder.substring(0, formDataBodyBuilder.length() - 1);
                }
    /**
                 * get data bytes
                 */
    
                byte[] bodyBytes = formDataBodyString.getBytes(charset);
                int contentLength = bodyBytes.length;
                ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(request) {
    
    /**
                     * change content-length
                     *
                     * @return
                     */
    
                    @Override
                    public HttpHeaders getHeaders() {
                        HttpHeaders httpHeaders = new HttpHeaders();
                        httpHeaders.putAll(super.getHeaders());
                        if (contentLength > 0) {
                            httpHeaders.setContentLength(contentLength);
                        } else {
                            httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                        }
                        return httpHeaders;
                    }
    /**
                     * read bytes to Flux<Databuffer>
                     *
                     * @return
                     */
    
                    @Override
                    public Flux<DataBuffer> getBody() {
                        return DataBufferUtils.read(new ByteArrayResource(bodyBytes),
                            new NettyDataBufferFactory(ByteBufAllocator.DEFAULT), contentLength);
                    }
                };
                ServerWebExchange mutateExchange = exchange.mutate().request(decorator).build();
                log.info("[GatewayContext]Rewrite Form Data :{}", formDataBodyString);
    
                return chain.filter(mutateExchange);
            }));
        }
    
    
    /**
         * ReadJsonBody
         *
         * @param exchange
         * @param chain
         * @return
         */
    
        private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain, GatewayContext gatewayContext) {
    
    /**
             * join the body
             */
    
            return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
    
    /*
                 * read the body Flux<DataBuffer>, and release the buffer
                 * //TODO when SpringCloudGateway Version Release To G.SR2,this can be update with the new version's feature
                 * see PR https://github.com/spring-cloud/spring-cloud-gateway/pull/1095
                 */
    
                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(bytes);
                DataBufferUtils.release(dataBuffer);
                Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
                    DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
                    DataBufferUtils.retain(buffer);
                    return Mono.just(buffer);
                });
    /**
                 * repackage ServerHttpRequest
                 */
    
                ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
                    @Override
                    public Flux<DataBuffer> getBody() {
                        return cachedFlux;
                    }
                };
    /**
                 * mutate exchage with new ServerHttpRequest
                 */
    
                ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
    
    /**
                 * read body string with default messageReaders
                 */
    
                return ServerRequest.create(mutatedExchange, messageReaders).bodyToMono(String.class)
                    .doOnNext(objectValue -> {
                        gatewayContext.setCacheBody(objectValue);
                        log.debug("[GatewayContext]Read JsonBody:{}", objectValue);
                    }).then(chain.filter(mutatedExchange));
            });
        }
    
        @Override
        public int getOrder() {
            return HIGHEST_PRECEDENCE;
        }
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    /**
             * save request path and serviceId into gateway context
             */
    
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();
    
            GatewayContext gatewayContext = new GatewayContext();
            String path = request.getPath().pathWithinApplication().value();
            gatewayContext.setPath(path);
            gatewayContext.getFormData().addAll(request.getQueryParams());
            gatewayContext.setIpAddress(String.valueOf(request.getRemoteAddress()));
            HttpHeaders headers = request.getHeaders();
            gatewayContext.setHeaders(headers);
            log.debug("HttpMethod:{},Url:{}", request.getMethod(), request.getURI().getRawPath());
    
            /// 注意,因为webflux的响应式编程 不能再采取原先的编码方式 即应该先将gatewayContext放入exchange中,否则其他地方可能取不到
    
    /**
             * save gateway context into exchange
             */
    
            exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext);
    
            // 处理参数
            MediaType contentType = headers.getContentType();
            long contentLength = headers.getContentLength();
            if (contentLength > 0) {
                if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) {
                    return readBody(exchange, chain, gatewayContext);
                }
                if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {
                    return readFormData(exchange, chain, gatewayContext);
                }
            }
            // TODO 多版本划区域控制后期实现
    
            log.debug("[GatewayContext]ContentType:{},Gateway context is set with {}", contentType, gatewayContext);
            return chain.filter(exchange);
        }
    
    }
    spring-cloud的版本
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.1.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
    <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Hoxton.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>com.alibaba.cloud</groupId>
                    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                    <version>2.2.1.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>

    参考原来

    pringCloud-Gateway获取body参数,解决只能获取一次问题,终极解决方案

  • 相关阅读:
    SGU 495 Kids and Prizes
    HDU 3853 LOOPS
    HDU 4089 Activation
    HDU 4405 Aeroplane chess
    ZOJ 3329 One Person Game
    POJ 2096 Collecting Bugs
    POJ1573(Robot Motion)
    poj2632(Crashing Robots)
    poj1068(Parencodings)
    poj2506(Tiling)
  • 原文地址:https://www.cnblogs.com/zhian/p/15143596.html
Copyright © 2011-2022 走看看