Okhttp的拦截器和封装
一、目录
二、 OkHttp拦截器概述
OKHttp中,Interceptors拦截器是一种强大的机制,可以监视,重写和重试Call实例
1.OkHttp的拦截器的作用
1.拦截器可以一次性对所有请求的返回值修改
2.拦截器可以一次性对请求的参数和返回的结果进行编码,比如统一设置为UTF-8
3.拦截器可以对所有的请求做统一的日志处理,不需要在每个请求开始或者结束的位置都添加一个日志操作。
4.其他需要对请求和返回进行统一处理的需求…
2.OkHttp拦截器的分类
OkHttp中的拦截器分2个:APP层面的拦截器(Application Interception)网络请求层面的拦截器(Network Interception)。
3.两种区别
Application:
1.不需要担心是否影响OKHttp的请求策略和请求速度
2.即使从缓存中取数据,也会执行Application拦截器
3.允许重试,即Chain.proceed()可以执行多次
4.可以监听观察这个请求的最原始的为改变的意图(请求头,请求体等)无法操作OKHttp为我们自动添加额外的请求头
5.无法操作中间的响应结果,比如当URL重定向发生以及请求重试,只能操作客户端主动第一次请求以及最终的响应结果
Network Interceptors
1.可以修改OKHttp框架自动添加的一些属性,与允许操作中间响应,比如当请求操作发生重定向或者重试等
2.可以观察最终完整的请求参数(也就是最终服务器接收到的请求数据和数据)
三、两种拦截器的实例
1.实例化appInterceptor拦截器
Interceptor appInterceptor = new Interceptor(){
public Response intercept(Chain chain) throws IOException{
Request request = chain.request();
HttpUrl url = request.url();
String s = url.url().toString();
Log.d(TAG,"app intercept:begin");
Response response = chain.proceed(request);
Log.d(TAG,:"app intercept:end");
return response;
}
};
2.实例化networkInterceptor拦截器
Interceptor networkInterceptor = new Interceptor(){
public Response intercept(Chain chain) throws IOException{
Request request = chain.request();
Log.d(TAG,"network interceptor:begin");
Response response = chain.proceed(request);
Log.d(TAG,"network interceptor:end");
return response;
}
};
3.将两个拦截器配置在Client中,并发送请求
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
okHttpClient = new OKHttpClient
.Builder()
.addInterceptor(appInterceptor)
.addNetworkInterceptor(networkInterceptor)
.build();
Button button = (Button)findViewById(R.id.bt);
button.setOnClickListener(new View.OnclickListener(){
public void onClick(View v){
Request request = new Request.Builder()
.url("http://www.baidu.cn")
.build();
okHttpClient.newCall(request).enqueue(new Callback(){
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG,"--" + response.networkResponse());
}
});
}
});
4.运行结果
四、拦截器的实际应用
1.统一添加Header
应用场景:后台要求在请求API时,在每个接口的请求头添加上对于的Token这时候就可以使用拦截器对他们进行统一的配置
Interceptor TokenHeaderInterceptor = new Interceptor(){
public Response intercept(Chain chain) throws IOException{
String token = Appservice.getToken();
Request originalRequest = chain.request();
Request updataRequest = originalRequest.newBuilder()
.header("token",token)
.build();
return chain.proceed(updateRequest);
}
};
在OKHttpClient中配置
okHttp = new OKHttpClient
.Builder()
.addInterector(TokenHeaderInterceptor)
.addNetworkInterceptor(networkInterceptor)
.build();
Button button =(Button)findViewById(R.id.bt);
button.setOnClientListener(new View.onClientListener(){
public void onClick(View v){
Request request = new Request.Builder
.url("http://www.baidu.cn")
.build();
okHttpClient.newCall(request).enqueue(new Callback(){
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "--" + response.networkResponse());
}
});
}
});
2.改变请求体
应用场景:在上面的login接口基础上,后台要求我们传过去的请求参数是按照一定规则经过加密的。
规则:
请求参数名统一为content;
content值:JSON格式的字符串经过AES加密后的内容;
实例化拦截器
Interceptor RequestEncryptInterceptor = new Interceptor() {
private static final String FORM_NAME = "content";
private static final String CHARSET="UTF-8";
public Response intercept(chain chain) throws IOException{
Request request = chain.request();
Requestbody body=request.body();
if(body instanceof FormBody){
FormBody formBody = (FormBody)body;
Map<String,String> formMap=new HashMap<>();
for(int i=0;i<formBody.size();i++){
formMap.put(formBody,name(i),formBody.value(i));
}
Gson gson=new Gson();
String jsonParams=gson.toJson(formMap);
String encrytParams = AESCrytUtils.encrypt(jsonParams.getBytes(CHARSET),AppConstant.getAESKey());
body=new FormBody.Builder().add(FORM_NAME,encryptParams).build();
}
if(body!=null)
{
request = request,newBuilder()
.post(body)
.build();
}
return chain.proceed(request);
}
};
五、OkHttp的封装
1.封装
public class NetRequest {
private static NetRequest netRequest;
private static OkHttpClient okHttpClient; // OKHttp网络请求
private Handler mHandler;
private NetRequest() {
// 初始化okhttp 创建一个OKHttpClient对象,一个app里最好实例化一个此对象
okHttpClient = new OkHttpClient();
okHttpClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS);
mHandler = new Handler(Looper.getMainLooper());
}
/**
* 单例模式 获取NetRequest实例
*
* @return netRequest
*/
private static NetRequest getInstance() {
if (netRequest == null) {
netRequest = new NetRequest();
}
return netRequest;
}
//-------------对外提供的方法Start--------------------------------
/**
* 建立网络框架,获取网络数据,异步get请求(Form)
*
* @param url url
* @param params key value
* @param callBack data
*/
public static void getFormRequest(String url, Map<String, String> params, DataCallBack callBack) {
getInstance().inner_getFormAsync(url, params, callBack);
}
/**
* 建立网络框架,获取网络数据,异步post请求(Form)
*
* @param url url
* @param params key value
* @param callBack data
*/
public static void postFormRequest(String url, Map<String, String> params, DataCallBack callBack) {
getInstance().inner_postFormAsync(url, params, callBack);
}
/**
* 建立网络框架,获取网络数据,异步post请求(json)
*
* @param url url
* @param params key value
* @param callBack data
*/
public static void postJsonRequest(String url, Map<String, String> params, DataCallBack callBack) {
getInstance().inner_postJsonAsync(url, params, callBack);
}
//-------------对外提供的方法End--------------------------------
/**
* 异步get请求(Form),内部实现方法
*
* @param url url
* @param params key value
*/
private void inner_getFormAsync(String url, Map<String, String> params, final DataCallBack callBack) {
if (params == null) {
params = new HashMap<>();
}
// 请求url(baseUrl+参数)
final String doUrl = urlJoint(url, params);
// 新建一个请求
final Request request = new Request.Builder().url(doUrl).build();
//执行请求获得响应结果
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
deliverDataFailure(request, e, callBack);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { // 请求成功
//执行请求成功的操作
String result = response.body().string();
deliverDataSuccess(result, callBack);
} else {
throw new IOException(response + "");
}
}
});
}
/**
* 异步post请求(Form),内部实现方法
*
* @param url url
* @param params params
* @param callBack callBack
*/
private void inner_postFormAsync(String url, Map<String, String> params, final DataCallBack callBack) {
RequestBody requestBody;
if (params == null) {
params = new HashMap<>();
}
FormBody.Builder builder = new FormBody.Builder();
/**
* 在这对添加的参数进行遍历
*/
for (Map.Entry<String, String> map : params.entrySet()) {
String key = map.getKey();
String value;
/**
* 判断值是否是空的
*/
if (map.getValue() == null) {
value = "";
} else {
value = map.getValue();
}
/**
* 把key和value添加到formbody中
*/
builder.add(key, value);
}
requestBody = builder.build();
//结果返回
final Request request = new Request.Builder().url(url).post(requestBody).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
deliverDataFailure(request, e, callBack);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { // 请求成功
//执行请求成功的操作
String result = response.body().string();
deliverDataSuccess(result, callBack);
} else {
throw new IOException(response + "");
}
}
});
}
/**
* post请求传json
*
* @param url url
* @param callBack 成功或失败回调
* @param params params
*/
private void inner_postJsonAsync(String url, Map<String, String> params, final DataCallBack callBack) {
// 将map转换成json,需要引入Gson包
String mapToJson = new Gson().toJson(params);
final Request request = buildJsonPostRequest(url, mapToJson);
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
deliverDataFailure(request, e, callBack);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { // 请求成功
//执行请求成功的操作
String result = response.body().string();
deliverDataSuccess(result, callBack);
} else {
throw new IOException(response + "");
}
}
});
}
/**
* Json_POST请求参数
*
* @param url url
* @param json json
* @return requestBody
*/
private Request buildJsonPostRequest(String url, String json) {
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
return new Request.Builder().url(url).post(requestBody).build();
}
/**
* 分发失败的时候调用
*
* @param request request
* @param e e
* @param callBack callBack
*/
private void deliverDataFailure(final Request request, final IOException e, final DataCallBack callBack) {
/**
* 在这里使用异步处理
*/
mHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.requestFailure(request, e);
}
}
});
}
/**
* 分发成功的时候调用
*
* @param result result
* @param callBack callBack
*/
private void deliverDataSuccess(final String result, final DataCallBack callBack) {
/**
* 在这里使用异步线程处理
*/
mHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
try {
callBack.requestSuccess(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
/**
* 数据回调接口
*/
public interface DataCallBack {
void requestSuccess(String result) throws Exception;
void requestFailure(Request request, IOException e);
}
/**
* 拼接url和请求参数
*
* @param url url
* @param params key value
* @return String url
*/
private static String urlJoint(String url, Map<String, String> params) {
StringBuilder endUrl = new StringBuilder(url);
boolean isFirst = true;
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
if (isFirst && !url.contains("?")) {
isFirst = false;
endUrl.append("?");
} else {
endUrl.append("&");
}
endUrl.append(entry.getKey());
endUrl.append("=");
endUrl.append(entry.getValue());
}
return endUrl.toString();
}
}
2.使用
String url = "网络请求地址“;
HashMap<String,String> params = new HashMap<>();
params.put("key","value");
// ...
NetRequest.getFormRequest(url, params, new NetRequest.DataCallBack() {
@Override
public void requestSuccess(String result) throws Exception {
// 请求成功的回调
}
@Override
public void requestFailure(Request request, IOException e) {
// 请求失败的回调
}
});