通过Http协议获取网络资源,OkHttpClient的使用

所需要的jar包: okhttp-3.0.0-RC1.jar 与 okio-1.6.0.jar (okhttp内部依赖okio)

OkHttpClient分同步请求与异步请求,这就是最大的不同了

Get方式的同步请求:

 /**
     * 通过get的方式请求数据,这里为同步请求,需要在子线程中运行
     */
    private void getGetData() {
        try {
            //1.声名okhttp客户端
            OkHttpClient okHttpClient = new OkHttpClient();
            //2.设置请求方式,设置请求参数
            Request request = new Request.Builder().get().url("网址").build();
            //3.获得请求结果
            Response response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {//判断请求是否成功
                //获得相应的实体
                ResponseBody body = response.body();
                String string = body.string();//获得String
                byte[] bytes = body.bytes();//获得byte[]
                InputStream inputStream = body.byteStream();//获得流
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Get方式的异步请求:

/**
     * 通过get方式请求数据,这里为异步请求,不需要另开子线程,内部是在子线程中运行的
     */
    private void getAsyncOkHttp() {
        //1.声名okhttp客户端
        OkHttpClient okHttpClient = new OkHttpClient();
        //2.设置请求方式,设置请求参数
        Request request = new Request.Builder().get().url("网址").build();
        //注意区别,同步是这样的:okHttpClient.newCall(request).execute();
        okHttpClient.newCall(request).enqueue(new Callback() {//异步
            @Override //请求数据失败的回调
            public void onFailure(Request request, IOException e) {

            }

            @Override //请求数据成功的回调,子线程中运行的  可以判断下状态码 response.code()
            public void onResponse(Response response) throws IOException {
                String string = response.body().string();//获得String
                byte[] bytes = response.body().bytes();//获得byte[]
                InputStream inputStream = response.body().byteStream();//获得流
            }
        });
    }

POST 

public static final OkHttpClient client = new OkHttpClient();

//post json
public static Response postByH5(String url, Map<String, String> header, String json) throws IOException { if (header == null) { header = new HashMap(); } RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder() .url(url) .headers(Headers.of(header)) .post(body) .build(); Response response = client.newCall(request).execute(); return response; } //表单同步 public static Response postFromByH5(String url, Map<String, String> header, String json) throws IOException { if (header == null) { header = new HashMap(); } HashMap<String, String> hashMap = new Gson().<HashMap<String, String>>fromJson(json, HashMap.class); FormBody.Builder builder = new FormBody.Builder(); if (hashMap != null) { Iterator<Map.Entry<String, String>> entries = hashMap.entrySet().iterator(); while (entries.hasNext()) { Map.Entry<String, String> entry = entries.next(); builder.add(entry.getKey(), entry.getValue()); } } FormBody formBody = builder.build(); Request request = new Request.Builder() .url(url) .headers(Headers.of(header)) .post(formBody) .build(); Response response = client.newCall(request).execute(); return response; }

一些状态码的说明:

 

网络请求工具:张鸿洋的okhttpUtils

添加拦截器:

import android.text.TextUtils;

import com.google.gson.Gson;
import com.shch.nursingworkers.App;
import com.shch.nursingworkers.bean.BaseBena;
import com.shch.nursingworkers.utils.ConstantUtil;
import com.shch.nursingworkers.utils.LogUtil;
import com.shch.nursingworkers.utils.encrypt.AESUtil;
import com.shch.nursingworkers.utils.encrypt.EncryptUtil;
import com.shch.nursingworkers.utils.encrypt.RSAUtil;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;

import java.io.IOException;
import java.util.Locale;

import okhttp3.Call;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;

import static com.shch.nursingworkers.utils.data.UrlUtils.login;

/**
 * okhttp的拦截器
 */
public class LogInterceptor implements Interceptor {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        //打印请求的网址
        //LogUtil.e("request:" + request.toString());
        LogUtil.e("request:" + URLDecoder.decode(request.toString(), "utf-8"));//避免乱码

        long t1 = System.nanoTime();
        okhttp3.Response response = chain.proceed(chain.request());
        long t2 = System.nanoTime();

        //打印请求头 网址 与 消耗的时间
        LogUtil.e(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();

        //是文本类型的数据,才去打印请求结果
        if(mediaType != null && isText(mediaType)) {
            String content = response.body().string();
            try{
                //防止下载apk或者其他文件时,解析出错     拿到请求的json数据后,这里你想干嘛就干嘛吧
                //BaseBena baseBena = new Gson().fromJson(content, BaseBena.class);
                //打印请求的内容
                LogUtil.e("response body:" + content);
              
                //复制一个请求转给外面的请求回调
                return response.newBuilder()
                        .body(okhttp3.ResponseBody.create(mediaType, content))
                        .build();
            }catch (Exception e){

            }
        }
        return response;
    }

    /**
     * 判断请求的内容是否是文本,防止请求的url是apk或者其他文件时,出现错误(比如:我在下载一个19兆的apk文件时,最后下下来变成了35兆)
     * @param mediaType
     * @return
     */
    private boolean isText(MediaType mediaType){
        if (mediaType.type() != null && mediaType.type().equals("text")){
            return true;
        }
        if (mediaType.subtype() != null){
            if (mediaType.subtype().equals("json") ||
                    mediaType.subtype().equals("xml") ||
                    mediaType.subtype().equals("html") ||
                    mediaType.subtype().equals("webviewhtml"))
                return true;
        }
        return false;
    }
}    

 

Cookie、Session、Token那点事儿

 

拦截器的添加与Session持久化

//Session持久化  在Application的onCreate()方法中初始化
        CookieJarImpl cookieJar = new CookieJarImpl(new PersistentCookieStore(getApplicationContext()));
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .cookieJar(cookieJar)
                .connectTimeout(15000L, TimeUnit.MILLISECONDS)
                .readTimeout(15000L, TimeUnit.MILLISECONDS)
                .addInterceptor(new LogInterceptor())//添加拦截器
                .build();
        OkHttpUtils.initClient(okHttpClient);

效果如下:

建议先看另一篇 okhttp的拦截器执行流程详解

 

过期后自动登录,获取新的SessionId

import com.google.gson.Gson;
import com.shch.nursingworkers.App;
import com.shch.nursingworkers.bean.BaseBena;
import com.shch.nursingworkers.utils.ConstantUtil;
import com.shch.nursingworkers.utils.LogUtil;
import com.shch.nursingworkers.utils.encrypt.AESUtil;
import com.shch.nursingworkers.utils.encrypt.EncryptUtil;
import com.shch.nursingworkers.utils.encrypt.RSAUtil;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;
import com.zhy.http.okhttp.request.RequestCall;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.Locale;

import okhttp3.Call;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.Response;

import static com.shch.nursingworkers.utils.data.UrlUtils.login;

/**
 * okhttp的拦截器
 */
public class LogInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();//请求的相关信息
        //打印请求的网址
        //LogUtil.e("request:" + request.toString());
        LogUtil.e("request:" + URLDecoder.decode(request.toString(), "utf-8"));

        long t1 = System.nanoTime();
        okhttp3.Response response = chain.proceed(chain.request());//继续请求,拿到请求数据
        long t2 = System.nanoTime();

        //打印请求头 网址 与 消耗的时间
        LogUtil.e(String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s",
                response.request().url(), (t2 - t1) / 1e6d, response.headers()));

        Response.Builder builder = response.newBuilder();
        Response clone = builder.build();//先克隆一个响应,来打印日志

        okhttp3.MediaType mediaType = clone.body().contentType();

        //是文本内向的数据,才去打印请求结果
        if(mediaType != null && isText(mediaType)) {
            String content = clone.body().string();
            try{
                //防止下载apk时,解析出错
                BaseBena baseBena = new Gson().fromJson(content, BaseBena.class);
                //打印请求的内容
                LogUtil.e("response body:" + content);
                if(baseBena!=null && "unlogin".equals(baseBena.getMessage())){
                    /*//未登录就登录*/
                    response.body().close();//先关闭该接口的资源(不会回调)
                    Request loginRequest = getLoginRequest();//获取登陆的Request
                    Response loginResponse = chain.proceed(loginRequest);//执行登陆,获取新的SessionId
                    if (loginResponse.isSuccessful()) {//登陆成功(200 ~ 300)
                        loginResponse.body().close();//释放登陆成功的资源
                        return chain.proceed(request);//重新执行最开始的接口
                    }

                }
                //复制一个请求转给外面的请求回调
                return response.newBuilder()
                        .body(okhttp3.ResponseBody.create(mediaType, content))
                        .build();
            }catch (Exception e){

            }
        }else{
            if(mediaType == null){
                LogUtil.e("拦截器,mediaType=" + mediaType);//可能是后台返回的空白页,没有返回数据类型,如没有这个头:Content-Type: application/json;charset=utf-8 
                response.close();
            }
        }
        return response;
    }

    /**
     * 判断请求的内容是否是文本,防止请求的url是apk或者其他文件时,出现错误
     * @param mediaType
     * @return
     */
    private boolean isText(MediaType mediaType){
        if (mediaType.type() != null && mediaType.type().equals("text")){
            return true;
        }
        if (mediaType.subtype() != null){
            if (mediaType.subtype().equals("json") ||
                    mediaType.subtype().equals("xml") ||
                    mediaType.subtype().equals("html") ||
                    mediaType.subtype().equals("webviewhtml"))
                return true;
        }
        return false;
    }


    /**
     * 防止Session过时
     */
    public Request getLoginRequest() throws IOException {
        String username = App.getSharedPreferences().getString(ConstantUtil.SP_LOGIN_NUMBER,"");
        String password = App.getSharedPreferences().getString(ConstantUtil.SP_LOGIN_PASSWORD,"");

        //加密的处理,RSA加密AES钥匙,再加密内容
        //生成AES秘钥
        byte[] aeskey = AESUtil.generateKey2byte();
        //RSA加密AES的秘钥
        byte[] aeskeyToRsa = RSAUtil.encryptByPublicKey(aeskey, RSAUtil.PUBLICKEY);
        final RequestCall build = OkHttpUtils
                .get()
                .url(login)
                .addParams("key", EncryptUtil.parseByte2HexStr(aeskeyToRsa))//将加了密的AES秘钥给服务器
                //用户名与密码的加密
                .addParams("username", AESUtil.encrypt2String(username, aeskey))
                .addParams("password", AESUtil.encrypt2String(password, aeskey))
                .addParams("loginType", "E")
                .build();

        return build.buildCall(null).request();
    }

}

 

posted @ 2016-09-28 19:13  ts-android  阅读(1595)  评论(0编辑  收藏  举报