网关中经常需要通过获取ServerHttpResponse响应的信息后进行业务逻辑处理以及一些辅助的处理,例如:完整的请求,响应日志打印;登录成功后创建会话业务等等。
下面通过代码来说明拦截ServerHttpResponse的body并重写body
BodyHandlerFunction 响应body拦截处理接口
public interface BodyHandlerFunction extends
BiFunction<ServerHttpResponse, Publisher<? extends DataBuffer>, Mono<Void>> {
}
- 此接口用于在writeWith中拦截body转化处理body
BodyHandlerServerHttpResponseDecorator
/**
* ServerHttpResponse包装类,通过BodyHandlerFunction处理响应body
*
* @author
* @version
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class BodyHandlerServerHttpResponseDecorator
extends ServerHttpResponseDecorator {
/**
* body 处理拦截器
*/
private BodyHandlerFunction bodyHandler = initDefaultBodyHandler();
/**
* 构造函数
*
* @param bodyHandler
* @param delegate
*/
public BodyHandlerServerHttpResponseDecorator(
BodyHandlerFunction bodyHandler, ServerHttpResponse delegate) {
super(delegate);
if (bodyHandler != null) {
this.bodyHandler = bodyHandler;
}
}
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
//body 拦截处理器处理响应
return bodyHandler.apply(getDelegate(), body);
}
@Override
public Mono<Void> writeAndFlushWith(
Publisher<? extends Publisher<? extends DataBuffer>> body) {
return writeWith(Flux.from(body).flatMapSequential(p -> p));
}
/**
* 默认body拦截处理器
*
* @return
*/
private BodyHandlerFunction initDefaultBodyHandler() {
return (resp, body) -> resp.writeWith(body);
}
}
- 1.此类实现ServerHttpResponseDecorator
- 2.此类包含BodyHandlerFunction用于body的处理转化
测试代码
public class Test1GlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange,
GatewayFilterChain chain) {
System.out.println("Test1GlobalFilter进入此方法");
//构建响应拦截处理器
BodyHandlerFunction bodyHandler = (resp, body) -> Flux.from(body)
.map(dataBuffer -> {
//响应信息转换为字符串
String reqBody = null;
try {
//dataBuffer 转换为String
reqBody = IOUtils
.toString(dataBuffer.asInputStream(), "UTF-8")
.replaceAll(">\\s{1,}<", "><");
System.out.println(reqBody);
} catch (IOException e) {
e.printStackTrace();
}
return reqBody;
}).flatMap(orgBody -> {
//根据原有的响应信息构建新响应信息并写入到resp中
//此处可以根据业务进行组装新的响应信息,
// 例如:登录后创建会话
//- 拿到登录请求的响应信息,判断登录是否成功
//- 登录成功调用创建会话接口,根据创建会话接口返回组装登录的真实响应
System.out.println("orgBody=" + orgBody);
String rbody = orgBody + "new1234";
HttpHeaders headers = resp.getHeaders();
headers.setContentLength(rbody.length());
return resp.writeWith(Flux.just(rbody)
.map(bx -> resp.bufferFactory()
.wrap(bx.getBytes())));
}).then();
//构建响应包装类
BodyHandlerServerHttpResponseDecorator responseDecorator = new BodyHandlerServerHttpResponseDecorator(
bodyHandler, exchange.getResponse());
return chain
.filter(exchange.mutate().response(responseDecorator).build());
}
@Override
public int getOrder() {
//WRITE_RESPONSE_FILTER 之前执行
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 1;
}
}
- 测试代码创建了一个全局的过滤器
- 在过滤其中构建了具有业务功能BodyHandlerFunction
- 构建带有业务功能BodyHandlerFunction的Response包装类
- 将Response包装类写入到exchange中
测试类BodyHandlerFunction功能主要是将resqbody 转化成字符串后并在原始的body上追加新字符串new1234。最后将新的body写入到response中;测试类只是为了验证整个代码逻辑是否正常。