Spring Cloud Gateway 路由自定义修改 Responsebody

 1.无脑的实现了一种自己写一个过滤器,修改返回体  此方法需注意fluxBody.buffer().map(dataBuffers -> {})中的buffer方法调用,不然有些返回体会分段传输的。

package com.wukala.gatewayserver.filter;

import cn.wukala.common.commonbase.result.WrapMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
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.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.util.List;

/**
 * 结果封装成固定200格式
 *
 * @author: zym
 */


@Component
public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    ObjectMapper objectMapper;

    private static Joiner joiner = Joiner.on("");


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


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {

                    Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                        List<String> list = Lists.newArrayList();

                        dataBuffers.forEach(dataBuffer -> {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer);

                            try {
                                list.add(new String(content, "utf-8"));
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                        String s = joiner.join(list);
                        try {
                            if (!WrapMapper.isWrap(s)) {
                                s = objectMapper.writeValueAsString(WrapMapper.ok(objectMapper.readValue(s, Object.class)));
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        System.out.println(s);
                        return bufferFactory().wrap(s.getBytes());
                    }));


                }
                return super.writeWith(body);
            }
        };

        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }
}

2.官方文档提供的 modifyResponseBody过滤器。比较简洁  (推荐)此方法需要注意过滤器顺序问题 当然取决于你的匹配,modifyResponseBody(...)以及其重载方法我没找到可以自定义的order顺序的方法。

package com.wukala.gatewayserver.config;

import cn.wukala.common.commonbase.result.WrapMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

import java.io.IOException;

/**
 * @Author: zym
 * @Description:
 * @Date: Created in 2018-12-26
 * @Modified By:
 */
@Configuration
public class RotesConfiguration {

    @Bean
    public RouteLocator routes(RouteLocatorBuilder routeLocatorBuilder, ObjectMapper objectMapper) {
        return routeLocatorBuilder.routes()
                .route("rewrite_response_upper", r -> r.path("/oauth-server/oauth/token")
                        .filters(f -> f.rewritePath("/oauth-server", "")
                                .modifyResponseBody(String.class, String.class,
                                        (exchange, s) -> {
                                            try {
                                                return Mono.just(objectMapper.writeValueAsString(WrapMapper.ok(objectMapper.readValue(s, Object.class))));
                                            } catch (IOException e) {
                                                e.printStackTrace();
                                            }
                                            return Mono.just(s);
                                        })).uri("lb://oauth-server"))

                .build();
    }
}

用之前还是过一遍官方文档,少走很多弯路。。。

效果如下

展开阅读全文

没有更多推荐了,返回首页