spring-cloud-starter-gateway中GlobalFilter的一些操作

在网关全局过滤器中中进行的一些操作,开发可能会用到,持续更新

直接返回字符串或json格式

获取请求头中token

拿到get或者post请求中的参数

拿到请求返回值

处理网关出现的异常(如其他服务不可用的异常)

动态路由(在url中指定服务名和接口名)

……………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………

代码如下

package com.example.filter;

import com.example.code.Res;
import com.example.code.ResultCode;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.reactivestreams.Publisher;
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.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.GZIPInputStream;

/**
 * @author 刘通
 * @date 2022年05月10日 10:52
 */
@Component
@Slf4j
public class MyGlobaTest implements GlobalFilter, Ordered {
//    /**
//     * 返回自定义json对象
//     * @param exchange
//     * @param chain
//     * @return
//     */
//    @Override
//    @SneakyThrows
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        ObjectMapper objectMapper = new ObjectMapper();
//        String s = objectMapper.writeValueAsString(Res.failed(ResultCode.FAILED,"失败咯"));
//        ServerHttpResponse response = exchange.getResponse();
//        response.setStatusCode(HttpStatus.OK);
//        response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
//        return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(s.getBytes()))));
//    }

//    /**
//     * 获取token
//     * @param exchange
//     * @param chain
//     * @return
//     */
//    @Override
//    @SneakyThrows
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        ServerHttpRequest request = exchange.getRequest();
//        String authorization = request.getHeaders().getFirst("Authorization");
//        if (!ObjectUtils.isEmpty(authorization)){
//            authorization = authorization.replace("Bearer", "").trim();
//        }
//        return chain.filter(exchange);
//    }

//    /**
//     * 获取get或者post请求参数
//     * @param exchange
//     * @param chain
//     * @return
//     */
//    @Override
//    @SneakyThrows
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        ServerHttpRequest request = exchange.getRequest();
//        String method = request.getMethod().name();
//        if (HttpPost.METHOD_NAME.equals(method)) {
//            return DataBufferUtils.join(exchange.getRequest().getBody())
//                    .flatMap(dataBuffer -> {
//                        byte[] bytes = new byte[dataBuffer.readableByteCount()];
//                        dataBuffer.read(bytes);
//                        // 拿到post请求参数
//                        String bodyString = new String(bytes, StandardCharsets.UTF_8);
//                        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 {
//            // 拿到get请求参数
//            MultiValueMap<String, String> queryParams = request.getQueryParams();
//            ObjectMapper obj = new ObjectMapper();
//            String valueAsString = obj.writeValueAsString(queryParams);
//            return chain.filter(exchange);
//        }
//    }

    /**
     * 在网关拿到接口返回数据
     * @param exchange
     * @param chain
     * @return
     */
    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponseDecorator responseBody = getResponseBody(exchange);
        return chain.filter(exchange.mutate().response(responseBody).build());
    }

    /**
     * order须为负的才生效,-1 is response write filter, must be called before that
     * @param exchange
     * @return
     */
    public ServerHttpResponseDecorator getResponseBody(ServerWebExchange exchange){
        ServerHttpResponse originalResponse = exchange.getResponse();
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        return new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {

                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    return super.writeWith(fluxBody.buffer().map(dataBuffer -> {
                        DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                        DataBuffer join = dataBufferFactory.join(dataBuffer);
                        byte[] content = new byte[join.readableByteCount()];
                        join.read(content);
                        //释放掉内存
                        DataBufferUtils.release(join);
                        String s = new String(content, StandardCharsets.UTF_8);

                        List<String> strings = exchange.getResponse().getHeaders().get(HttpHeaders.CONTENT_ENCODING);
                        if (!CollectionUtils.isEmpty(strings) && strings.contains("gzip")) {
                            GZIPInputStream gzipInputStream = null;
                            try {
                                gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(content), content.length);
                                StringWriter writer = new StringWriter();
                                IOUtils.copy(gzipInputStream, writer, "UTF-8");
                                s = writer.toString();

                            } catch (IOException e) {
                                log.error("====Gzip IO error", e);
                            } finally {
                                if (gzipInputStream != null) {
                                    try {
                                        gzipInputStream.close();
                                    } catch (IOException e) {
                                        log.error("===Gzip IO close error", e);
                                    }
                                }
                            }
                        } else {
                            s = new String(content, StandardCharsets.UTF_8);
                        }
                        return bufferFactory.wrap(content);
                    }));
                }
                return super.writeWith(body);
            }
        };
    }
    @Override
    public int getOrder() {
        return -2;
    }
}
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
@RequiredArgsConstructor
// 网关处理异常
public class GatewayExceptionConfiguration implements ErrorWebExceptionHandler {
    @Override
    @SneakyThrows
    public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
        ServerHttpResponse response = serverWebExchange.getResponse();
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(Res.failed(503,throwable.getLocalizedMessage()));
        return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(json.getBytes()))));
    }
}
@Component
@Slf4j
public class DynamicEverythingFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 动态修改路由开始
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> queryParams = request.getQueryParams();
        if (ObjectUtils.isEmpty(queryParams.get("服务名参数"))){
            // TODO: 2022/9/17 返回错误
        }
        if (ObjectUtils.isEmpty(queryParams.get("接口名参数"))){
            // TODO: 2022/9/17 返回错误
        }
        //lb
        String service = queryParams.get("服务名参数").get(0);
        //方法
        String function = queryParams.get("接口名参数").get(0);

        Route route =exchange.getAttribute(GATEWAY_ROUTE_ATTR);
        // 修改路由规则
        Route newRoute = Route.async()
                .asyncPredicate(route.getPredicate())
                .filters(route.getFilters())
                .id(route.getId())
                .order(route.getOrder())
                .uri("lb://"+service)
                .build();
        exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, newRoute);

        String path = "通过网关的基础路径如http://localhost:9000/small/";
        String newPath = path+function;
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(newPath);
        //排除服务名参数和接口名参数
        if (queryParams.size()>2&& HttpMethod.GET.name().equals(request.getMethodValue())){
            for (String next : queryParams.keySet()) {
                if (!"服务名参数".equals(next)&&!"接口名参数".equals(next)){
                    // get请求的话,其他参数加入
                    builder.queryParam(next, queryParams.get(next));
                }
            }
        }
        URI uri = builder.build().toUri();
        // 构建新的请求
        ServerHttpRequest newRequest = request.mutate().uri(uri).build();
        return chain.filter(exchange.mutate().request(newRequest).build());
    }

    @Override
    public int getOrder() {
        return -50;
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值