feign调用返回值通过钉钉返回问题IOUtils.toByteArray(response.body().asInputStream())

         通过feign调用显示打印时候,出现这种情况:当使用 
IOUtils.toByteArray(response.body().asInputStream()) 时候,本地调试正常,但是发到开发环境,一直会返回空;
原因:
https://github.com/OpenFeign/feign/issues/1208

在github的openfeign 的issue里面找到了答案:
https://github.com/OpenFeign/feign/issues/701
"Steam is closed" means you may read stream somewhere. In this case, the root reason is toString() of respsonse. Those function reads the steam and ensure closed the tream. That means you can not display response in debug model in IDEA. So dot no log response before read it.

 

 解决方法就是重新把返回的流拷贝下,然后通过信息打印出来:

 

package com.gwm.marketing.restfulfeign;

import com.alibaba.fastjson.JSONObject;
import com.gwm.marketing.restfulfeign.alerm.OraRpcDingdingConfiguration;
import feign.Logger;
import feign.Request;
import feign.Response;
import org.apache.commons.io.IOUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;

/**
 * @author fanht
 * @descrpiton
 * @date 2022/7/26 14:09:39
 * @versio 1.0
 */
@Configuration
public class OraFeignLogger extends Logger {

    private static final int PASS_STATUS= 200;
    @Resource
    private OraRpcDingdingConfiguration oraRpcDingdingConfiguration;

    @Override
    protected Response logAndRebufferResponse(String configKey,
                                              Level logLevel,
                                              feign.Response response,
                                              long elapsedTime) throws IOException {
        System.out.println("===========远程RPC调用耗时============" + elapsedTime);
        int status = response.status();
        if(PASS_STATUS != status){
            Request request = response.request();
            String requestMsg = request.httpMethod().name() + " " + request.url() + " HTTP/1.1";
            String bodyMsg = request.body() != null ? new String(request.body()): "";
            byte[] bodyData = null;
            String message = "";
            if(response.body() != null){
                String returnRes = IOUtils.toString(response.body().asReader(StandardCharsets.UTF_8));
                message = MessageFormat.format("调用三方接口异常告警:项目:{0},环境:{1},IP:{2},接口请求方式以及请求地址:{3},耗时时间:{4}毫秒,请求入参:{5},三方返回信息:{6}",
                        OraRpcDingdingConfiguration.applicationName, OraRpcDingdingConfiguration.env, OraIpUtil.initIp() , requestMsg, elapsedTime, StringUtils.isEmpty(bodyMsg)?"请求参数为空":bodyMsg,returnRes);
            } else {
                message = MessageFormat.format("调用三方接口异常告警:项目:{0},环境:{1},IP:{2},接口请求方式以及请求地址:{3},耗时时间:{4}毫秒,请求入参:{5}",
                        OraRpcDingdingConfiguration.applicationName, OraRpcDingdingConfiguration.env, OraIpUtil.initIp() , requestMsg, elapsedTime,StringUtils.isEmpty(bodyMsg)?"请求参数为空":bodyMsg);
            }
            sendDingdingAlerm(message,
                    oraRpcDingdingConfiguration.getToken().getUrl());

        } else if (elapsedTime > oraRpcDingdingConfiguration.getRpc().getRpcTimeOut()) {
            Request request = response.request();
            String requestMsg = request.httpMethod().name() + " " + request.url() + " HTTP/1.1";
            String bodyMsg = request.body() != null ? new String(request.body()): "";
            String message = "";
            try {
                //todo 如果是本地debug模式,请注释掉此行。要不然会出现idea的debug模式的流关闭冲突导致无法解析三方返回的数据异常问题(参考:https://github.com/OpenFeign/feign/issues/1208//bodyData = IOUtils.toByteArray(response.body().asInputStream());
                String returnRes = IOUtils.toString(response.body().asReader(StandardCharsets.UTF_8));
                //todo 不去解析bodyData,因为在debug模式下会出现 stream is close的问题 虽然能解决(参考解决方案:https://github.com/OpenFeign/feign/issues/1208),但是debug模式经常使用 不建议。这样会导致的问题是 钉钉告警不能打印显示三方返回的信息
                message = MessageFormat.format("调用三方接口耗时告警:项目:{0},环境:{1},IP:{2},接口请求方式以及请求地址:{3},耗时时间:{4}毫秒,请求入参:{5},三方返回信息:{6}",
                        OraRpcDingdingConfiguration.applicationName, OraRpcDingdingConfiguration.env, OraIpUtil.initIp() , requestMsg , elapsedTime, StringUtils.isEmpty(bodyMsg)?"请求参数为空":bodyMsg,
                        returnRes);
            } catch (Exception e) {
                e.printStackTrace();
            }
            sendDingdingAlerm(message,
                    oraRpcDingdingConfiguration.getToken().getUrl());
        }
        return response;
    }

    @Override
    protected void log(String configKey, String format, Object... args) {
    }

    /**
     * 发送钉钉消息
     */
    public static void sendDingdingAlerm(String message, String dingdingTokenUrl) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("msgtype", "text");
        JSONObject content = new JSONObject();
        content.put("content", message);
        jsonObject.put("text", content);
        OraHttpClient oraHttpClient = new OraHttpClient();
        String response = null;
        try {
            String[] dingdingArr = dingdingTokenUrl.split(",");
            if (dingdingArr != null && dingdingArr.length > 0) {
                for (int i = 0; i < dingdingArr.length; i++) {
                    response = oraHttpClient.post(dingdingArr[i], jsonObject.toJSONString());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}

 

posted @ 2022-10-13 18:23  Doyourself!  阅读(892)  评论(0编辑  收藏  举报