spring cloud 获取到达网关请求的 请求路径 参数 和 响应

发布时间:2023年12月28日

首先要在网关项目中,新增一个全局过滤器,因为获取请求参数的时,如果不加处理,获取一次后,后面的过滤器就拿不到请求参数了,我理解别人大概试着意思.

package com.enterprise.filter;

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.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;
/**
 * @author: Blossom
 * CacheBodyGlobalFilterk的作用是为了解决
 * ServerHttpRequest中body的数据为NULL的情况
 */
@Component
public class CacheBodyGlobalFilter implements Ordered, GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        if (exchange.getRequest().getHeaders().getContentType() == null) {
            return chain.filter(exchange);
        } else {
            //获取databuffer
            return DataBufferUtils.join(exchange.getRequest().getBody())
                    .flatMap(dataBuffer -> { //设定返回值并处理
                        DataBufferUtils.retain(dataBuffer); //设定存储空间
                        Flux<DataBuffer> cachedFlux = Flux//读取Flux中所有数据并且保存
                                .defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
                        ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator( //得到ServerHttpRequest
                                exchange.getRequest()) {
                            @Override //重载getBody方法 让其从我设定的缓存获取
                            public Flux<DataBuffer> getBody() {
                                return cachedFlux;
                            }
                        };
                        //放行 并且设定exchange为我重载后的
                        return chain.filter(exchange.mutate().request(mutatedRequest).build());
                    });
        }
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

在建一个过滤器,保存访问日志信息,通过Feign 调用其他模块的保存接口

package com.enterprise.filter;

import com.alibaba.fastjson.JSON;
import com.enterprise.feignclient.IFeignSystemService;
import com.enterprise.utils.IpUtil;
import com.nimbusds.jose.JWSObject;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.CharsetUtil;
import net.minidev.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
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.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.net.URI;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 保存访问日志
 */
@Component
public class AccessLogFilter implements GlobalFilter, Ordered {

    @Autowired
    private IFeignSystemService systemService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 请求对象
        ServerHttpRequest request = exchange.getRequest();
        // 响应对象
        ServerHttpResponse response = exchange.getResponse();

        String ip = IpUtil.getIP(request);

        // 获取token
        String authorization = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        String token = StringUtils.substringAfter(authorization, "Bearer ");

        Map value = null;

        if(StringUtils.isNotBlank(token)){
            JWSObject jwsObject = null;
            try {
                jwsObject = JWSObject.parse(token);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            JSONObject jsonObject = jwsObject.getPayload().toJSONObject();
            String u = (String)redisTemplate.opsForValue().get("loginUser:"+jsonObject.get("jti").toString());
            value = (Map) JSON.parse(u);
            System.out.println(value);
        }

        RequestPath path = request.getPath();

        if(StringUtils.startsWith(path.toString(),"/system/accessLog/list")){
            //查看访问日志不记录日志
            return chain.filter(exchange);
        }

        String parameter="";

        if (HttpMethod.POST.equals(exchange.getRequest().getMethod()) && null != exchange.getRequest().getHeaders().getContentType()
                && exchange.getRequest().getHeaders().getContentType().includes(MediaType.APPLICATION_JSON)
                && !exchange.getRequest().getHeaders().getContentType().includes(MediaType.MULTIPART_FORM_DATA)) {

            String requestbody = resolveBodyFromRequest(exchange.getRequest());
            parameter = requestbody;
            //return chain.filter(exchange.mutate().request(generateNewRequest(exchange.getRequest(), requestbody)).build());
        }else if(HttpMethod.GET.equals(exchange.getRequest().getMethod())){
            MultiValueMap<String, String> queryParams = request.getQueryParams();
            parameter = queryParams.toString();
        }

        Map<String,String> log=new HashMap<>();
        log.put("userId",value!=null?(String)value.get("id"):"");
        log.put("userUsername",value!=null?(String)value.get("username"):"");
        log.put("ip",ip);
        log.put("path",path.toString());
        log.put("method",exchange.getRequest().getMethod().toString());
        log.put("reqParameter",parameter);

        //saveLog(log);

        //return chain.filter(exchange);
        return chain.filter(exchange.mutate().response(recordResponseLog(exchange,log)).build());
    }

    /*private void saveLog(Map<String, String> log) {

    }*/

    private void saveLog(Map map){
        System.out.println(map);
        systemService.saveLog(map);
    }

    /**
     * 这里必须小于-1
     * @return
     */
    @Override
    public int getOrder() {
        return -2;
    }

    /**
     * 获取响应数据
     * @param exchange
     * @return
     */
    private ServerHttpResponseDecorator recordResponseLog(ServerWebExchange exchange,Map map) {
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = exchange.getRequest().getHeaders();
        MediaType mediaType = headers.getContentType();
        DataBufferFactory bufferFactory = response.bufferFactory();

        ServerHttpResponseDecorator decoratorResponse = new ServerHttpResponseDecorator(response) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    // 没有token的不会记录日志,所以不记录响应
                    /*if (StrUtil.isBlank(headers.getFirst("Authorization"))) {
                        return super.writeWith(body);
                    }*/
                    // 过滤上传附件请求
                    if ((mediaType != null && mediaType.equals(MediaType.MULTIPART_FORM_DATA))
                            || (mediaType != null && mediaType.equals(MediaType.APPLICATION_FORM_URLENCODED))) {
                        return super.writeWith(body);
                    }

                    String path = (String)map.get("path");
                    if(StringUtils.startsWith(path,"/system/api/file")){
                        //下载文件
                        saveLog(map);
                        return super.writeWith(body);
                    }

                    Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {// 解决返回体分段传输获取完整响应数据问题
                        StringBuilder bodyString = new StringBuilder();
                        dataBuffers.forEach(dataBuffer -> {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer);
                            bodyString.append(new String(content, CharsetUtil.UTF_8));
                        });

                        // 拿到返回数据,可以进行做一些修改
                        String result = bodyString.toString();
                        byte[] uppedContent = new String(result.getBytes(), CharsetUtil.UTF_8).getBytes();
                        // 保存响应日志
                        map.put("response",result);
                        saveLog(map);
                        response.getHeaders().setContentLength(uppedContent.length);
                        return bufferFactory.wrap(uppedContent);
                    }));
                }
                return super.writeWith(body);
            }
        };
        return decoratorResponse;
    }

    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();
    }
    private ServerHttpRequest generateNewRequest(ServerHttpRequest request, String requestBody) {
        URI ex = UriComponentsBuilder.fromUri(request.getURI()).build(true).toUri();
        ServerHttpRequest newRequest = request.mutate().uri(ex).build();
        DataBuffer dataBuffer = stringBuffer(requestBody);
        Flux<DataBuffer> flux = Flux.just(dataBuffer);
        newRequest = new ServerHttpRequestDecorator(newRequest) {
            @Override
            public Flux<DataBuffer> getBody() {
                return flux;
            }
        };
        return newRequest;
    }

    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/qq_31683775/article/details/135275278
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。