zoukankan      html  css  js  c++  java
  • Spring Cloud Zuul记录接口响应数据

    系统在生产环境出现问题时,排查问题最好的方式就是查看日志了,日志的记录尽量详细,这样你才能快速定位问题。

    如果需要在Zuul中进行详细的日志记录,这两种日志必不可少。

    • API请求信息
    • 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<String, String> 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<Pair<String, String>>  headerList = RequestContext.getCurrentContext().getOriginResponseHeaders();
    for (Pair<String, String> 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折包邮

    WechatIMG48.jpeg

    欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course)

    微信扫码加入猿天地知识星球

    猿天地

  • 相关阅读:
    第一章 重构
    Android View的事件分发
    java.lang.NoSuchMethodError: android.view.View.setBackground
    handler消息机制
    魅族手机Listview下拉出现hold字样的奇葩问题解决方案
    数据结构--树,二叉树
    数据结构之栈和队列
    设计模式--六大原则
    ListView上下线添加
    Python 入门(七)函数
  • 原文地址:https://www.cnblogs.com/yinjihuan/p/10514527.html
Copyright © 2011-2022 走看看