系统在生产环境出现问题时,排查问题最好的方式就是查看日志了,日志的记录尽量详细,这样你才能快速定位问题。
如果需要在Zuul中进行详细的日志记录,这两种日志必不可少。
o API请求信息
o API响应信息
前面有介绍过如何获取请求信息,文章请查看《Spring Cloud Zuul过滤器获取请求参数问题》。
今天正好又有一位朋友问我如何获取响应的数据,抽时间给大家写篇文章简单分享下。
熟悉Zuul的朋友都知道,Zuul中有4种类型过滤器,每种都有特定的使用场景,要想记录响应数据,那么必须是在请求路由到了具体的服务之后,返回了才有数据,这种需求就适合用post过滤器来实现了。
这边给大家介绍两种方式获取响应数据:
第一种

try {
     Object zuulResponse = RequestContext.getCurrentContext().get("zuulResponse");
     if (zuulResponse != null) {
         RibbonHttpResponse resp = (RibbonHttpResponse) zuulResponse;
         String body = IOUtils.toString(resp.getBody());
         System.err.println(body);
         resp.close();
         RequestContext.getCurrentContext().setResponseBody(body);
     }
} catch (IOException e) {
    e.printStackTrace();
}

第二种

InputStream stream = RequestContext.getCurrentContext().getResponseDataStream();
try {
    String body = IOUtils.toString(stream);
    System.err.println(body);
    RequestContext.getCurrentContext().setResponseBody(body);
} catch (IOException e) {
    e.printStackTrace();
}

为什么上面两种方式可以取到响应内容?
在RibbonRoutingFilter或者SimpleHostRoutingFilter中可以看到下面一段代码:

public Object run() {
    RequestContext context = RequestContext.getCurrentContext();
    this.helper.addIgnoredHeaders();
    try {
        RibbonCommandContext commandContext = buildCommandContext(context);
        ClientHttpResponse response = forward(commandContext);
        setResponse(response);
        return response;
    }
    catch (ZuulException ex) {
        throw new ZuulRuntimeException(ex);
    }
    catch (Exception ex) {
        throw new ZuulRuntimeException(ex);
    }
}

forward()方法对服务调用,拿到响应结果,通过setResponse()方法进行响应的设置。
protected void setResponse(ClientHttpResponse resp)
throws ClientException, IOException {
RequestContext.getCurrentContext().set("zuulResponse", resp);
this.helper.setResponse(resp.getStatusCode().value(),
resp.getBody() == null ? null : resp.getBody(), resp.getHeaders());
}
上面第一行代码就可以解释我们的第一种获取的方法,这边直接把响应内容加到了RequestContext中。
第二种方式的解释就在helper.setResponse的逻辑里面了,如下:

public void setResponse(int status, InputStream entity,
            MultiValueMap headers) throws IOException {
    RequestContext context = RequestContext.getCurrentContext();
    context.setResponseStatusCode(status);
    if (entity != null) {
        context.setResponseDataStream(entity);
    }

    // .....
}

第二天又问了另外一个问题,怎么获取response的contentType?
需求是可以区分是正常的数据响应还是文件下载:
这位朋友获取的代码是:

HttpServletResponse response = ctx.getResponse();
response.getContentType()

他说上面的方式获取不到?
我给大家介绍两种获取方式,如下:
第一种
List> headerList = RequestContext.getCurrentContext().getOriginResponseHeaders();
for (Pair pair : headerList) {
if (pair.first().equals("Content-Type")) {
System.err.println(pair.second());
}
}
第二种

Object zuulResponse = RequestContext.getCurrentContext().get("zuulResponse");
if (zuulResponse != null) {
     RibbonHttpResponse resp = (RibbonHttpResponse) zuulResponse;
     System.err.println(resp.getHeaders().getContentType().toString());
}

推荐下我的新书《Spring Cloud微服务-全栈技术与案例解析》
新书购买:单本75折包邮
Spring Cloud Zuul记录接口响应数据_第1张图片
猿天地
Spring Cloud Zuul记录接口响应数据_第2张图片
阅读原文,学习课程。

尹吉欢
我不差钱啊
喜欢作者