一般来说,服务器回400错误是由于客户端发的请求格式有问题.
400 Bad Request 是由于明显的客户端错误(例如,格式错误的请求语法,太大的大小,无效的请求消息或欺骗性路由请求),服务器不能或不会处理该请求。
但是,遇到了一家比较奇葩的公司,请求逻辑正常该回200的情况下回了400.业务逻辑的错误跟客户端请求逻辑错误混在一起.....
{"code":752, "success":false, "data":{},"msg":"用户无法找到", ...}
服务器能正常返回数据,说明出问题的地方是业务逻辑,但是服务器回400,客户端就只能走onError(Throwable e)回调,拿不到这个msg,用户就不知道是什么问题,就会跑来反馈说这是什么垃圾app,用都用不了...
忍住脏话,考虑兼容
既然okhttp的log拦截器HttpLoggingInterceptor能拿到这串数据,说明至少有两种方法可以获取到.一是重写该拦截器;二是用反射...
懒得重写一个,所以用第二种方法
看一下代码的日志打印,可以发现上面的log是在HttpLoggingInterceptor.intercept(Chain chain)方法中实现的,根据日志分析一下可以知道就是buffer这串字符串取出来的数据.
if (responseBody.contentLength() != 0) {
logger.log("");
logger.log(buffer.clone().readString(charset));
}
logger.log("<-- END HTTP (" + buffer.size() + "-byte body)");
看一下代码前后的生成过程,发现该数据在方法里是局部变量里.
Java 反射不支持访问局部变量。因为局部变量是存储在方法栈上的,它们在方法结束后就消失了,无法被反射访问。
这个局部变量拿不到,反射调用intercept(Chain chain)方法的话需要传参,不太行
所以之恩呢把这个HttpLoggingInterceptor类拿出来,放到项目里. 在类里加上全局变量send,并把值赋上
public static String send = ""; //定义全局变量if (responseBody.contentLength() != 0) {
logger.log("");
logger.log(buffer.clone().readString(charset));
send = buffer.clone().readString(charset); //赋值
}
然后在网络回调的onError中反射该值就可以拿到了
@Override
public void onError(Throwable e) {
String msg = "失败状态";
try{
//拿到HttpLoggingInterceptor类的实例
Object object = HttpLoggingInterceptor.class.newInstance();
Field send = object.getClass().getField("send"); //反射获取属性
JSONObject json = JSONObject.parseObject((String) send.get(object));
System.out.println("json: " + json); msg = json.getString("msg");
System.out.println(msg);
}catch(Exception q){
System.out.println(getStackTraceString(q)); }
}