Retrofit 数据解析 监控

问题:生产环境上 后端返回数据接口 异常

工作中经常会发生 线上有些页面 突然就不能正常访问了,然后一番检查后发现是因为后端返回的数据接口发生了改变,导致了 数据解析失败进而 页面不能正常访问。(注:这种情况 在后端语言是 PHP的会后 会出现的更加频繁)。

解决方式

其实这个问题的解决 或者说 预防这种问题的发生方式有很多,比如

  • 后端开发人员 在 提交代码时 有专门的的工具能检测出这种异常。这是最优的
  • 测试部门 或者 后端 开发 接口监控脚本,然后定时跑 ,这样能再第一时间发现问题
  • 移动端 在 访问接口发现问题后 主动报警,然后反馈问题。

今天我们就来说说,在移动端 监控数据解析,异常是主动上报的方案。

思路

对数据进行预解析,如果有问题的及时上报,具体到 Retrofit 框架上的话,就是添加一个 ConverterFactory 来专门做这个事情。

难点

1. Retrofit 中虽然 ConverterFactory 可以添加多个,但是最终真正 解析数据并返回最终结果的 只有一个,那么 怎么让 多个 Converter 被调用而 起作用的只有一个呢?

阅读源码发现Retrofit 中提供了 nextResponseBodyConverter 这个Api 来让开发者或者 下一个 Converter 所以我们就可以 在当前 Converter中获取 下一个 Converter来进行真正的 解析工作。这也是我们要注意的一个地方,数据解析的这个 ConverterFactory 必须 在真正 解析数据的 ConverterFactory 之前被添加到 Retrofit

核心代码如下

SerializationCheckerConverterFactory.class

   @Override
    public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {

        //获取下一个  ResponseBodyConverter 因为  BeanCheckerResponseBodyConverter 是不做 真正结果的返回的
        Converter delegate = retrofit.nextResponseBodyConverter(this, type, annotations);
        return new SerializationCheckerResponseBodyConverter<>(delegate, gson, type,annotations,retrofit,listener);
    }

-----------

SerializationCheckerResponseBodyConverter.class

    @Override
    public T convert(ResponseBody value) throws IOException {

        //创建一个新的 ResponseBody 给后面的 Converter 使用
        MediaType contentType = value.contentType();
        String bodyString = value.string();
        ResponseBody newResponseBody = ResponseBody.create(contentType, bodyString);


        StringReader reader = new StringReader(bodyString);
        JsonReader jsonReader = gson.newJsonReader(reader);

        try {
            adapter.read(jsonReader);
            if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
                throw new JsonIOException("JSON document was not fully consumed.");
            }
            return delegate.convert(newResponseBody);
        } catch (Exception e) {

            String errorMessage = StringUtils.isNotEmpty(e.getMessage()) ? e.getMessage() : e.getLocalizedMessage();

            if (listener != null) {
                listener.onSerializationFailed(requestUrl, errorMessage, annotations, retrofit);
            }

            return delegate.convert(newResponseBody);
        } finally {
            value.close();
        }
    }

源码地址

源码存放在GitHub上,有需要自取

你可能感兴趣的:(Retrofit 数据解析 监控)