工作中跟客户端沟通时产生了点问题, 记录一下.

起因

后端有一个接口是这样的

@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}}

更多相关文章

  1. Android(安卓)Wifi P2P 入门
  2. Android实现服务器登录
  3. Android(安卓)Activity生命週期简介
  4. android 获取服务器文件流 hander
  5. Android客户端连接tomcat时出错:connect failed: ECONNREFUSED (C
  6. Android(安卓)Mqtt
  7. Android—构建安全的Android客户端请求,避免非法请求
  8. Android(安卓)Binder的使用和设计[android native serivce]
  9. android 面试题一

随机推荐

  1. Android(安卓)编程下 Touch 事件的分发和
  2. 更改android锁屏方向
  3. Android(安卓)HTTP协议请求网络(一)之认
  4. Android中WebView页面交互
  5. Android:Intent Filter 和 action 简介
  6. No resource found that matches the giv
  7. Android设备管理器漏洞
  8. android studio 2.1 preview4 之 gradle
  9. Android中文 API (31) —— TimePicker
  10. android控件隐藏与显示