工做中跟客戶端溝通時產生了點問題, 記錄一下.java
後端有一個接口是這樣的android
@RequestMapping("android") public BaseResult android(@RequestBody RequestData requestData) { }
RequestData.javagit
package com.junbaor.network.model; public class RequestData { private Integer id; private String name; // 省略 get set }
若是使用 http://localhost:8080/android?id=1&name=張三
是調不通的github
只能處理 Content-Type 爲 application/json 的請求, 須要把參數放在 post 請求體內json
{ "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 取 }
long long ago 寫過一點 Android , 不太相信想本身試試。
打聽後得知客戶端的網絡框架是 Retrofit 配合 OkHttp。
開始研究 Android, 安裝環境就不說了。app
先引入客戶端使用的網絡框架, 使用的都是最新版, 因爲數據是 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.Date Gson 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<ResponseData>() { @Override public void onResponse(Call<ResponseData> call, Response<ResponseData> response) { System.out.println("響應成功, 數據:" + response.body()); } @Override public void onFailure(Call<ResponseData> call, Throwable t) { System.out.println("響應失敗, 緣由:" + t.getMessage()); } });
參見:https://github.com/junbaor/an...
Android 端重點關注:com.junbaor.network.NetworkTest
Server 端重點關注:com.junbaor.network.NetworkApplicationide
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<Date> { @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; } } }
在網上找到了這個 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.1 Content-Type: application/json; charset=UTF-8 Content-Length: 24 Host: 127.0.0.1:8080 Connection: Keep-Alive Accept-Encoding: gzip User-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-8 Transfer-Encoding: chunked Date: 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}}