gateWay网关实现统一拦截response

背景:在微服务项目中支持国际化,各个服务端出现了太多冗余代码,所以在网关处进行统一拦截进行国际化。

1.首先,gateWay网关处实现GlobalFilter,ordered接口,进行拦截

package com.ruoyi.gateway.filter;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.gateway.service.LocaleMessageSourceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.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.context.annotation.Configuration;
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.http.server.reactive.ServerHttpResponse;
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.nio.charset.Charset;

import static com.mrobot.common.core.constant.HttpStatus.NO_SUCH_MESSAGE;


@Slf4j
@Component
@Configuration
public class ResponseGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private LocaleMessageSourceService localeMessageSourceService;

    private static String CODE = "code";
    private static String MSG = "msg";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse originalResponse = exchange.getResponse();
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        ServerHttpResponseDecorator decoratedResponse = 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.map(dataBuffer -> {
                        byte[] content = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(content);
                        //释放掉内存
                        DataBufferUtils.release(dataBuffer);
                        String lastStr = new String(content, Charset.forName("UTF-8"));

                        JSONObject jsonObject = JSONUtil.parseObj(lastStr, false);
                        log.info("原始Response:{}", jsonObject);
                        //在此处处理返回结果
                        switch (jsonObject.getInt(CODE)) {
                            case NO_SUCH_MESSAGE:
                                lastStr = JSONUtil.toJsonStr(getGlobalResponse(jsonObject));
                                log.info("国际化处理后Response:{}", lastStr);
                                return bufferFactory.wrap(lastStr.getBytes());
                        }
                        //不处理异常则用json转换前的数据返回
                        return bufferFactory.wrap(content);
                    }));
                }
                return super.writeWith(body);
            }
        };
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }

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

    private GlobalResponse getGlobalResponse(JSONObject jsonObject) {
        GlobalResponse globalResponse = new GlobalResponse();
        String msg = jsonObject.getStr(MSG);
        String[] split = msg.split("'");
        String s = split[1];
        globalResponse.setMsg(StringUtils.isEmpty(localeMessageSourceService.getMessage(s)) ? msg : localeMessageSourceService.getMessage(s));
        globalResponse.setCode(jsonObject.getInt(CODE));
        return globalResponse;
    }
}

像上面代码所示,使用switch进行处理,方便其他人进行扩展,而不满足的response我们尽量不去动它,让它怎么来怎么回去

而进行对比的code,就需要在服务端进行自定义全局异常,对你需要拦截的异常进行重新定义返回code,该code必须独一无二,方便网关处进行拦截。

2.需要自定义一个返回对象

package com.ruoyi.gateway.filter;

import lombok.Data;

import java.io.Serializable;

@Data
public class GlobalResponse implements Serializable {

    private static final long serialVersionUID = 3236949286095520863L;
    private int code;

    private String msg;

}

国际化支持报错返回只需要code和msg,具体返回体可按照所需来定义

如此,就可以实现网关处拦截请求进行你想要的操作了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值