OkHttp 如何使用Interceptor(拦截器)修改(GET/POST)请求

582 阅读2分钟

大家好,给大家伙分享之前,先说两句不相干的话,从事Android开发亦有5年了,以前经常遇到问题,都会在网上查询资料,在众多前辈的指导下,解决了我很多开发遇到的问题,正是有这些前辈的分享,让我们少走了很多弯路,我在想我也遇到了很多开发问题,我为什么不可以分享,所以从今天开始,我要分享一些我遇到的一些问题和经验,包括我之前遇到的一些印象深刻的问题,我都会慢慢去找出来分享,希望大家能够支持,谢谢~

进入主题,可能大家都会遇到这样的一个问题,后台服务接口鉴权,和一些公共的参数上传,如:设备号,设备类型,appkey,appVersion,sign等等...一般来说,这些公共的参数都会放在Head上面。

拦截器的功能就不在多说了,详情看cloud.tencent.com/developer/a…

添加HEAD

这个比较简单

class MyHeadInterceptor : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val builder = chain.request().newBuilder()
        builder.addHeader("token", "token123456").build()
        builder.addHeader("device", "Android").build()
        builder.addHeader("isLogin", "false").build()
        return chain.proceed(builder.build())
    }

}

GET

  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
      var request: Request = chain.request()
      val url = request.url
      val newUrl = url.newBuilder().apply {
            addEncodedQueryParameter("add1", "我是新加的")
            addEncodedQueryParameter("add2", "我也是")
        }.build()
        request = request.newBuilder().url(newUrl).build()
        return chain.proceed(request)
   
    }

POST

// FormBody和url不太一样,若需添加公共参数,需要新建一个构造器
FormBody.Builder bodyBuilder = new FormBody.Builder(); // 把已有的post参数添加到新的构造器 
if (request.body() instanceof FormBody) { 
    FormBody formBody = (FormBody) request.body(); 
    for (int i = 0; i < formBody.size(); i++) { 
    bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i)); 
    } 
} 
// 这里可以添加一些公共post参数 
bodyBuilder.addEncoded("key_xxx", "value_xxx"); 
FormBody newBody = bodyBuilder.build(); 
// 打印所有post参数 
for (int i = 0; i < newBody.size(); i++) { 
    Log.d("TEST", newBody.name(i) + " " + newBody.value(i)); 
} 
// 将最终的表单body填充到request中 
requestBuilder.post(newBody);

现在get和post现在都比较清楚,如果是json呢,传的json 怎么修改呢??? 现在就遇到一个情况,一般来说sign,appkey这些都应该放在head里面,如果硬要求放在body里面怎么办呢? 比如说:

    {
        "orderId": "ADDSEE1AA55"
    }

我这样的一个json需要变成这样的:

{
    "appid":"t9Hf0frozfHdYO41",
    "data": {
        "orderId": "ADDSEE1AA55"
    }
    "sign":"安全签名",
}

别慌,我们还是一样的思路,用拦截器把拿到json,然后在对json重新包装就解决啦,那怎么拿到json呢,我们来看看:

private fun bodyToString(request: Request): String {
    return try {
        val copy = request.newBuilder().build()
        val buffer = Buffer()
        copy.body!!.writeTo(buffer)
        buffer.readUtf8()
    } catch (e: IOException) {
        ""
    }
}

这样就可以拿到json数据啦 那我们来试试看吧

val oldJsonObject = JSONObject(bodyToString(request))
val newJSONObject = JSONObject().apply {
    put("data",oldJsonObject)
    put("sign","123456")
    put("appid","123456")
}
val newBody: RequestBody = newJSONObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
request = request.newBuilder().post(newBody).build()
return chain.proceed(request)

贴一下完整的代码:

class TestInterceptor : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        var request: Request = chain.request()
        when(request.method){
            "GET" -> {
                val url = request.url
                val newUrl = url.newBuilder().apply {
                    addEncodedQueryParameter("add1", "我是新加的")
                    addEncodedQueryParameter("add2", "我也是")
                }.build()
                request = request.newBuilder().url(newUrl).build()
                return chain.proceed(request)
            }
            "POST" -> {
                val oldJsonObject = JSONObject(bodyToString(request))
                val newJSONObject = JSONObject().apply {
                    put("data",oldJsonObject)
                    put("sign","123456")
                    put("appid","123456")
                }
                val newBody: RequestBody = newJSONObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
                request = request.newBuilder().post(newBody).build()
                return chain.proceed(request)
            }
            else -> {
                return chain.proceed(request)
            }
        }
    }

    private fun bodyToString(request: Request): String {
        return try {
            val copy = request.newBuilder().build()
            val buffer = Buffer()
            copy.body!!.writeTo(buffer)
            buffer.readUtf8()
        } catch (e: IOException) {
            ""
        }
    }

}

好了,今天的分享就到此结束啦。 有什么不对的地方,欢迎大家指导和交流。谢谢~