聊聊 Android 的网络请求框架 Retrofit 2 + okhttp 3
工作中跟客户端沟通时产生了点问题, 记录一下.
起因
后端有一个接口是这样的
@RequestMapping("android")public BaseResult android(@RequestBody RequestData requestData) { }
RequestData.java
package com.junbaor.network.model;public class RequestData { private Integer id; private String name; // 省略 get set}
如果使用 http://localhost:8080/android?id=1&name=张三
是调不通的
只能处理 Content-Type 为 application/json 的请求, 需要把参数放在 post 请求体内
{ "id":1, "name":"张三"}
问题
客户端使用第一种方式调不通, 告知需把参数转成 json 对象放到请求体内,
反馈说之前都是按照第一种方式调用的接口, 做不到第二种。
解决
后端没有找到优雅的解决方式, 被迫修改接口实现, 之所以继续保留 requestData 是为了兼容其它调用方.
@RequestMapping(value = "android")public BaseResult android(@RequestBody(required = false) RequestData requestData, @RequestParam(required = false) Integer id, @RequestParam(required = false) String name) { // 处理逻辑时先判断 requestParam 是否有值, 没有的话再从 requestData 取}
研究 Android
long long ago 写过一点 Android , 不太相信想自己试试。
打听后得知客户端的网络框架是 Retrofit 配合 OkHttp。
开始研究 Android, 安装环境就不说了。
引包
先引入客户端使用的网络框架, 使用的都是最新版, 由于数据是 json 格式再引入 gson 库(虽然不知道他们用的是什么解析库). converter-gson 是 retrofit2 的工具包, 用来把 json 封装成对象.
compile 'com.squareup.retrofit2:retrofit:2.3.0'compile 'com.squareup.okhttp3:okhttp:3.9.1'compile 'com.google.code.gson:gson:2.8.2'compile 'com.squareup.retrofit2:converter-gson:2.3.0'
编码
// OkHttp 请求日志拦截器HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { System.out.println(message); }});logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);// OkHttp 客户端OkHttpClient okHttpClient = new OkHttpClient().newBuilder() .connectTimeout(2, TimeUnit.MILLISECONDS) .addNetworkInterceptor(logInterceptor) .build(); // 把后台返回的时间戳转成 java.util.DateGson gson = new GsonBuilder().registerTypeAdapter(Date.class, new GsonDateTypeAdapter()).create();Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://127.0.0.1:8080") .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create(gson)) .build(); //请求参数RequestData requestData = new RequestData();requestData.setId(1);requestData.setName("张三");TestService testService = retrofit.create(TestService.class);Call testServiceReslut = testService.getTestResult(requestData);testServiceReslut.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { System.out.println("响应成功, 数据:" + response.body()); } @Override public void onFailure(Call call, Throwable t) { System.out.println("响应失败, 原因:" + t.getMessage()); }});
源码
参见:https://github.com/junbaor/an...
Android 端重点关注:com.junbaor.network.NetworkTest
Server 端重点关注:com.junbaor.network.NetworkApplication
花絮
Gson 时间戳转 Date
GsonDateTypeAdapter.java
package com.junbaor.network.extend;import com.google.gson.TypeAdapter;import com.google.gson.stream.JsonReader;import com.google.gson.stream.JsonWriter;import java.io.IOException;import java.util.Date;/** * Created by junbaor on 2017/12/13. * * 将后台返回的时间戳转成 java.util.Date * 参见: https://stackoverflow.com/questions/41348055/gson-dateformat-to-parse-output-unix-timestamps */public class GsonDateTypeAdapter extends TypeAdapter { @Override public void write(JsonWriter out, Date value) throws IOException { if (value == null) { out.nullValue(); } else { out.value(value.getTime() / 1000); } } @Override public Date read(JsonReader in) throws IOException { if (in != null) { return new Date(in.nextLong() / 1000); } else { return null; } }}
okhttp 日志打印
在网上找到了这个 https://github.com/square/okh...
由于没有 logger 实现, 打印的比较凌乱, 索性把代码拷到项目中以便修改, 用控制台输出实现了 logger 接口
// OkHttp 日志拦截器HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { System.out.println(message); }});logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
日志效果:
--> POST http://127.0.0.1:8080/android http/1.1Content-Type: application/json; charset=UTF-8Content-Length: 24Host: 127.0.0.1:8080Connection: Keep-AliveAccept-Encoding: gzipUser-Agent: okhttp/3.9.1{"id":1,"name":"张三"}--> END POST (24-byte body)<-- 200 http://127.0.0.1:8080/android (15ms)Content-Type: application/json;charset=UTF-8Transfer-Encoding: chunkedDate: Wed, 13 Dec 2017 16:05:49 GMT{"code":200,"message":"成功","data":{"id":1,"name":"张三","birthday":1513181149729}}<-- END HTTP (88-byte body)响应成功, 数据:BaseResult{code=200, message='成功', data=ResponseData{id=1, name='张三', birthday=Sun Jan 18 20:19:41 CST 1970}}
更多相关文章
- Android客户端连接tomcat时出错:connect failed: ECONNREFUSED (C
- Android—构建安全的Android客户端请求,避免非法请求
- android客户端访问网络工具类
- android ScreenshotClient 接口截屏幕
- Android库. 1 UDP客户端
- Android 无线接口层RIL(Radio Layer Interface)——RILD
- 应用phprpc协议实现Android客户端的一些总结
- Android系统服务接口
- Android之崩溃日志管理(原创)