最近这一年半,实在是大开眼界了,面对各类奇葩的接口,在紧凑的开发周期下,没有时间细想如何去面对,好在最近稍微悠闲了,就把遇到的各类奇葩接口整理了一下,本身手写Spring去模拟这些接口,而后尝试用Retrofit一一破解,终于被我摸出了一些门道。java
首先说明一点,用Json作先后端交互实际上是很好的作法,我我的也很推荐这样来玩。spring
遇到这种场景,咱们首先想到的就是百度,而后咱们会了解如下写法:json
方法1:后端
@Headers("Content-Type: application/json;charset=UTF-8", "Accept: application/json") @POST(ServerAPI.JPUSH_UPLOAD_DEVICE_TOKEN_INFO) fun uploaddevicetoken(@Body body: RequestBody): Single<LaiKangJunVO<Any>> //-------------------------- val gson = Gson() val jsonJpushStr = gson.toJson(jpushload) val requstBody = RequestBody.create(MediaType.parse("application/json"), jsonJpushStr) val disposable = accountService.uploaddevicetoken(requstBody) .subscribeOn(Schedulers.io())
这种方式并无错,可是咱们忽略了一点,咱们添加了ConverterFactory
。咱们都知道,若是添加ConverterFactory,就能够直接这样写:app
方法2:ide
@POST("test4") fun test4(@Body test: Test):Single<Bean> //---------------------- service.test4(Test("XXX", 11)) .subscribeOn(Schedulers.io()) .subscribe({ val i = 0 }, { val i = 0 })
直接把对象当参数传入便可,是否是方便不少?ui
有个弟弟写过一个接口,让我传一个空的Json串,即“{}”,我先用上面的方法1来跑,无论怎么写retrofit都会报错,时间紧没办法,我跑去找弟弟吵了一架,让人家改了。可是后来反思,当哥的应该尽可能兼容弟弟,这个问题该怎么解决呢,之后再遇到这问题该怎么处理,直到我用上面的方法2传递了一个空的对象,终于解决了:url
data class TestBean() @POST("test4") fun test(@Body bean: TestBean):Single<Bean> //---------------------- service.test(TestBean()) .subscribeOn(Schedulers.io()) .subscribe({ val i = 0 }, { val i = 0 })
事情的原由是,在作「注销」接口时,后端弟弟在spring拦截器里面去拦截参数,不知足的话他不能返回responseBody,只能返回一个responseHeder,可是因为咱们用了ConverterFactory,retrofit会自动把responseBody反序列化成对象,但此时的responseBody是个空串,因此在解析的时候就会报解析错误end of .....
。code
应对这种场景,咱们能够直接使用retrofit内部的okhttp来实现:对象
private fun ok() { val req = Request.Builder() .url(url + "test") .build() val moshi = Moshi.Builder().build() val call = client.newCall(req) call.enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { val head = response.headers() val head1 = response.header("Date") val test = TestJsonAdapter(moshi).fromJson(response.body()?.source()) val i = 0 } override fun onFailure(call: Call, e: IOException) { val i = 0 } }) }
可是这样以来就形成了咱们的代码的不统一。在我百般尝试和各类百度后,终于找到一篇帖子,因而有了如下的解决方案:
@POST("test4") fun test4(@Body test: Test):Single<retrofit2.Response<Boolean>> //--------------------------------- private fun retrofit4():Disposable { return service.test4(Test("XXX", 11)) .subscribeOn(Schedulers.io()) .subscribe({ val i = 0 val token = it.headers()["token"] }, { val i = 0 }) }
咱们都知道retrofit能够全局在请求头中加参数:
val client = OkHttpClient.Builder() client.addInterceptor { val oriReq = it.request() val req = oriReq.newBuilder() .header("token", token.toString()) .method(oriReq.method(), oriReq.body()) .build() it.proceed(req) } retrofit = Retrofit.Builder() .baseUrl(url) .client(client.build()) .addConverterFactory(MoshiConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build() service = retrofit.create(Service::class.java)