android,retrofit,okhttp,日誌攔截器,使用攔截器Interceptor統一列印請求與響應的json
阿新 • • 發佈:2019-01-01
可以打印出傳遞的引數以及返回的結果 : 最下面有完整的 retrofit 案例
------------------retrofit的使用----START--------------------------
首先 : 依賴 :
1. 攔截器 :compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-scalars:2.1.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0'
/** * Retrofit2 Logger攔截器。 */ public final class LoggingInterceptor implements Interceptor { private static final Charset UTF8 = Charset.forName("UTF-8"); public enum Level { NONE, HEADERS, BODY } public interface Logger { void log(String message); Logger DEFAULT = new Logger() { @Override public void log(String message) { //Platform.get().log(4, message, null); } }; } public LoggingInterceptor() { this(Logger.DEFAULT); } public LoggingInterceptor(Logger logger) { this.logger = logger; } private final Logger logger; private volatile Level level = Level.NONE; /** * Change the level at which this interceptor logs. */ public LoggingInterceptor setLevel(Level level) { if (level == null) throw new NullPointerException("level == null. Use Level.NONE instead."); this.level = level; return this; } public Level getLevel() { return level; } @Override public Response intercept(Chain chain) throws IOException { Level level = this.level; Request request = chain.request(); if (level == Level.NONE) { return chain.proceed(request); } boolean logBody = level == Level.BODY; boolean logHeaders = logBody || level == Level.HEADERS; RequestBody requestBody = request.body(); boolean hasRequestBody = requestBody != null; Connection connection = chain.connection(); Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1; String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol(protocol); if (!logHeaders && hasRequestBody) { requestStartMessage += " (" + requestBody.contentLength() + "-byte body)"; } logger.log(requestStartMessage); if (logHeaders) { if (hasRequestBody) { // Request body headers are only present when installed as a network interceptor. Force // them to be included (when available) so there values are known. if (requestBody.contentType() != null) { logger.log("Content-Type: " + requestBody.contentType()); } if (requestBody.contentLength() != -1) { logger.log("Content-Length: " + requestBody.contentLength()); } } Headers headers = request.headers(); for (int i = 0, count = headers.size(); i < count; i++) { String name = headers.name(i); // Skip headers from the request body as they are explicitly logged above. if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) { logger.log(name + ": " + headers.value(i)); } } if (!logBody || !hasRequestBody) { logger.log("--> END " + request.method()); } else if (bodyEncoded(request.headers())) { logger.log("--> END " + request.method() + " (encoded body omitted)"); } else { Buffer buffer = new Buffer(); requestBody.writeTo(buffer); Charset charset = UTF8; MediaType contentType = requestBody.contentType(); if (contentType != null) { charset = contentType.charset(UTF8); } logger.log(""); logger.log(buffer.readString(charset)); logger.log( "--> END " + request.method() + " (" + requestBody.contentLength() + "-byte body)"); } } long startNs = System.nanoTime(); Response response = chain.proceed(request); long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); ResponseBody responseBody = response.body(); long contentLength = responseBody.contentLength(); String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length"; logger.log("<-- " + response.code() + ' ' + response.message() + ' ' + response.request().url() + " (" + tookMs + "ms" + (!logHeaders ? ", " + bodySize + " body" : "") + ')'); if (logHeaders) { Headers headers = response.headers(); for (int i = 0, count = headers.size(); i < count; i++) { logger.log(headers.name(i) + ": " + headers.value(i)); } if (!logBody || !HttpEngine.hasBody(response)) { logger.log("<-- END HTTP"); } else if (bodyEncoded(response.headers())) { logger.log("<-- END HTTP (encoded body omitted)"); } else { BufferedSource source = responseBody.source(); source.request(Long.MAX_VALUE); // Buffer the entire body. Buffer buffer = source.buffer(); Charset charset = UTF8; MediaType contentType = responseBody.contentType(); if (contentType != null) { charset = contentType.charset(UTF8); } if (contentLength != 0) { logger.log(""); logger.log(buffer.clone().readString(charset)); } logger.log("<-- END HTTP (" + buffer.size() + "-byte body)"); } } return response; } private boolean bodyEncoded(Headers headers) { String contentEncoding = headers.get("Content-Encoding"); return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity"); } private static String protocol(Protocol protocol) { return protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1"; } }
2. 重寫:
public class Logger implements LoggingInterceptor.Logger {
@Override
public void log(String message) {
LogUtils.i("http : " + message);
}
}
3. 再次封裝:
LoggingInterceptor logging = new LoggingInterceptor(new Logger()); logging.setLevel(LoggingInterceptor.Level.BODY); OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS) .connectTimeout(5 * 1000, TimeUnit.MILLISECONDS) .readTimeout(5 * 1000, TimeUnit.MILLISECONDS) .retryOnConnectionFailure(true) // 失敗重發 .addInterceptor(logging); Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constant.API_BASE_URL) .addConverterFactory(GsonConverterFactory.create()) // 新增Gson轉換器 .client(builder.build()) .build();
------------以上是對retrofit的使用封裝,在第三個步驟中還要返回自己的代理類 --------END-----------
下面對 okhttp進行封裝
首先新增依賴 :
compile 'com.squareup.okhttp3:okhttp:3.9.0'
解釋 : 這個依賴是 okhttp3,至於和okhttp有什麼不同,請自行百度檢視,在這裡說下我自己的理解 :
okhttp3可以通過builder的形式,完成對okhttp的建立
第一步 : 對攔截器進行重寫 : (我從網上找的,應該可以滿足日常使用)
package intercept;
import android.util.Log;
import java.io.IOException;
import java.util.Locale;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class LoggingInterceptor implements Interceptor {
String TAG = "LoggingInterceptor";
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Log.v(TAG, "request:" + request.toString());
long t1 = System.nanoTime();
okhttp3.Response response = chain.proceed(chain.request());
long t2 = System.nanoTime();
Log.v(TAG, String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers()));
okhttp3.MediaType mediaType = response.body().contentType();
String content = response.body().string();
Log.i(TAG, "response body:" + content);
return response.newBuilder().body(okhttp3.ResponseBody.create(mediaType, content)).build();
} // 下面的span沒什麼用
}
第二步 : 對 okhttp進行簡單的封裝
package intenet;
import intercept.LoggingInterceptor;
import okhttp3.OkHttpClient;
public class OkhttpUtils {
static OkHttpClient okHttpClient;
/**
* 以builder的形式構建 okhttp,如果只是通過new的形式,建立不了攔截器
* @return
*/
public static OkHttpClient getOkhttpInstance() {
if (okHttpClient == null) {
synchronized (OkhttpUtils.class) { // 雙重加鎖機制,後面也要對空判斷,假設兩個執行緒都到這裡,不判斷,下一個執行緒還是會再建立
if (okHttpClient == null) {
okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.build();
}
}
}
return okHttpClient;
}
}
第三步 : 網路請求, url裡面有 easy-mock, 這是一個可以自己造假資料的網站,可以學習一下
final String url = "https://easy-mock.com/mock/59dc1fbe1de3d46fa94c74c6/ceshi/example";
new Thread() {
@Override
public void run() {
super.run();
OkHttpClient okhttpClient = OkhttpUtils.getOkhttpInstance(); // 通過builder構建 okhttp
Request request = new Request.Builder().get().url(url).build();
okhttp3.Call call = okhttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Toast.makeText(getActivity(), "網路請求失敗", Toast.LENGTH_SHORT).show();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String result = response.body().string();
// Log.e("result 網路請求結果是 :::", "onResponse: " + result);
Gson gson = new Gson();
TestBan bean = gson.fromJson(result, TestBan.class);
TestBan.DateBean dataBean = bean.date;
final String dataTime = dataBean.datetime;
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getActivity(), "第二個介面請求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
注意 :
選擇 ----> NO Filters
完結 : 可以在控制檯打印出 json 資料.
下面是我自己用 retrofit 配合 okhttp來列印請求以及返回資料的完整案例,okhttp可以用來 :
http://blog.csdn.net/qq_37043246/article/details/79075479 (自行檢視)
步驟 :
① 依賴
implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1
② 封裝 :
package api;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ApiServiceFactory {
private Api mApi;
private static ApiServiceFactory mFactory;
private ApiServiceFactory() { // 私有主要讓它使用 getInstance 來 創建出 factory
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(5 * 1000, TimeUnit.MILLISECONDS)
.readTimeout(5 * 1000, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(true) // 失敗重發
.addInterceptor(httpLoggingInterceptor);
Retrofit retrofit = new Retrofit.Builder()
//使用自定義的mGsonConverterFactory
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://easy-mock.com/mock/59dc1fbe1de3d46fa94c74c6/ceshi/")
.client(builder.build())
.build();
mApi = retrofit.create(Api.class);
}
public static ApiServiceFactory getInstance() {
if (mFactory == null) {
mFactory = new ApiServiceFactory();
}
return mFactory;
}
public Call<String> queryList(String name) {
return mApi.queryList(name);
}
}
③ 介面 :
package api;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface Api {
@GET("example")
Call<String> queryList(@Query("name") String name);
}
④ 介面 :
package t.cn.myowntest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import api.ApiServiceFactory;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class Main3Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
getData();
}
private void getData() {
Call<String> call = ApiServiceFactory.getInstance().queryList("winner");
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(Main3Activity.this, "失敗了", Toast.LENGTH_SHORT).show();
}
});
}
}
⑤ 列印 :