背景:在微服务项目中支持国际化,各个服务端出现了太多冗余代码,所以在网关处进行统一拦截进行国际化。
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,具体返回体可按照所需来定义
如此,就可以实现网关处拦截请求进行你想要的操作了