zoukankan      html  css  js  c++  java
  • Retrofit、Okhttp使用小记(cookie,accesstoken,POST

    博主在项目中用RxJava也差不多几个月了,但是结合Retrofit使用经验还不是太多。恰好新项目的后台是http+json的,就打算尝试一把。
    刚开始由于Retrofit还不太熟,但是后台接口急着测试,所以只好先用okhttp把接口测试成功先。
    最最简单的测试方法就是http在线测试啦,相信很多小伙伴都知道啦,不过还是给不知道的小伙伴科普一下吧,http://www.atool.org/httptest.php/

    okhttp比较简单,测试登录很快就测试成功了,但是在测试其他获取数据的接口时,遇到了一点小麻烦,因为后台做了cookie验证,需要保存登录时的cookie和登录接口返回的accesstoken才能成功获取到数据。
    至于保存cookie这个比较简单,都是借鉴一下前人的经验哈,把第一次请求的cookie信息保存到内存中,之后每次请求都使用相同的cookie请求就可以了。
    注意在junit测试的时候如果是异步,还没等到获取网络数据,测试就结束了,此时我们要在最后加上一句代码,让程序等待获取数据,不直接结束。
    System.in.read();
    先贴一下使用ok实现登录的代码:

    public Call UserLogin(String username, String pwd) {
            MemoryCookieStore cookieStore = new MemoryCookieStore();
            cookieJar = new CookieJarImpl(cookieStore);
            OkHttpClient client = new OkHttpClient.Builder()
                    .cookieJar(cookieJar)
                    .build();
    
            FormBody formBody = new FormBody.Builder()
                    .add("KEY", MD5.hexdigest("一个固定的key"))
                    .add("Action","接口名称")
                    .add("UserName", MyEncode.encode(username))
                    .add("PassWord", MyEncode.encode(pwd))
                    .build();
    
            Request request = new Request.Builder()
                    .url("baseURL:如:http://www.baidu.com/json/Userservice.ashx")
                    .post(formBody)
                    .build();
            Call call = client.newCall(request);
            return call;
        }

    其他的就不多说了,就是post的基本使用。
    重点是这两句代码:

    MemoryCookieStore cookieStore = new MemoryCookieStore();
    cookieJar = new CookieJarImpl(cookieStore);

    创建一个Cookie仓库,接着创建一个cookieJar、在okhttpClient中吧cookieJar设置进去即可。
    以上代码用到三个java类,
    CookieStore.javaMemoryCookieStore.javaCookieJarImpl.java 都是直接复制过来用的,是鸿洋封装的okhttpUtils里面的代码~

    之后每次访问后台接口都使用相同的cookieJar。

    使用okhttp测试接口比较简单,很快就测试好了。但是每次测试都要写一大堆东西,非常麻烦。
    再加上本来就是想要熟练一下Retrofit的使用的,之前只用在WebService上,很多使用都不一样,要注意的也不一样。
    接下来我们开始改造:
    如果接触过一点Retrofit的应该都知道要先写一个IApi接口吧。接口我们都知道,面向接口编程,达到解耦程序的目的。
    我们先新建一个IUserApi ,并添加一个登陆方法。

    public interface IUserApi {
        @POST("UserService.ashx")
        Observable<RequestResult<String>> login(
        @Query("Action") String action,
        @Query("KEY") String key,
        @Query("UserName") String username,
        @Query("PassWord") String password);
    }

    看上去应该没啥问题,基本上都是参考网上写的。
    接下来是使用。

    Retrofit retrofit = new Retrofit.Builder()
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())             
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(new MyOkHttpClient())
                    .baseUrl(Dic.BASEURL)
                    .build();
    IUserApi api = retrofit.create(IUserApi.class);
    api.login("login","key","fancy","123456")
       .subscribe(new ServerSubscriber<String>(iview) {
                        @Override
                        public void onMyNext(String accesstoken) {
                        System.out.println(accesstoken);
                    });

    在junit中测试时,不用加,加了会报错,正式使用的时候可以加上。

    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())

    接下来就是跑junit测试,哎,咋就是登陆失败呢。
    看上去明明和okhttp一样啊,用的okhttpClient就是之前的,怎么会有问题呢? 改了半天也没改出什么名堂来~最后决定使出我的终极绝招,HttpLoggingInterceptor http请求拦截,看看请求过程中有什么不一样。
    以下是okhttp方式的日志:

    信息:
    POST http://www.baidu.com/json/UserService.ashx http/1.1
    信息:
    KEY=1234353464565&Action=login&UserName=MKs6XgGG7ZJdKMqHI8sYSA%3D%3D%0A&PassWord=cAL%2BvRqMtRI%3D%0A

    一下是Retrofit方式的日志:

    信息:
     --> POST http://www.baidu.com/json/UserService.ashx?Action=userLogin&KEY=1234353464565&UserName=MKs6XgGG7ZJdKMqHI8sYSA%3D%3D%0A&PassWord=cAL%2BvRqMtRI%3D%0A http/1.1

    应该一眼就能看出区别了,前者是post到baseurl,参数是表单形式传递的。 而后者是直接连参数一起post过去了。

    那我们应该如何修改呢。最开始我也只是随便尝试,修改@Query,试试别的参数,查看了一下@Field(按住ctrl单击跳到对应类),对应的解释是Named pair for a form-encoded request.,感觉应该是这个。
    然后把请求接口中的@Query全都替换成了@Field。
    又跑了一遍,结果提示必须添加编码,这时候也不知道该如何添加编码,最后就直接百度了。其实只要再接口上添加一个@FormUrlEncoded 注解就可以了。
    最终的接口如下:

        @FormUrlEncoded
        @POST("UserService.ashx")
        Observable<RequestResult<String>> UserLogin(
                @Field("Action") String action,
                @Field("KEY") String key,
                @Field("UserName") String username,
                @Field("PassWord") String password);

    再跑一遍就能够登录成功了。
    关于获取数据,测试前需要先登录,然后使用相同的cookie和登录的accesstoken才能够成功获取到数据。

    这个就要rxjava来配合了,当然你也可以用okhttp迷之缩进哈,至于代码的可读性和通用性,那就不好说了,谁用谁知道是不?
    Retrofit本来就提供了rxjava支持的,所以我们用rxjava来实现线程调度~ !!! 拒绝迷之缩进 !!!
    因为Retrofit的创建基本是通用的,就直接封到一个RetrofitUtil.create()方法里面了。

    Retrofit retrofit = RetrofitUtil.create("");
            IUserApi api = retrofit.create(IUserApi.class);
            TestApi.getAccesstoken()
                    .flatMap(new Func1<RequestResult<String>, Observable<? extends String>>() {
                        @Override
                        public Observable<? extends String> call(RequestResult<String> stringRequestResult) {
                            return api.getInfo("GetInfo", Dic.key, stringRequestResult.getAccesstoken());
                        }
                    })
                    .subscribe(new ServerSubscriber<String>() {
                        @Override
                        public void onNext(String s) {
                            System.out.println(s);
                        }
                    });

    一个flatMap就解决问题啦,是不是非常简单,用lambda格式化一下,会更加简洁。

    TestApi.getAccesstoken()
                    .flatMap(stringRequestResult -> api.getInfo("GetInfo", Dic.key, stringRequestResult.getAccesstoken()))
                    .subscribe(new ServerSubscriber<String>() {
                        @Override
                        public void onNext(String s) {
                            System.out.println(s);
                        }
                    });

    经过以上步骤基本上把okhttp改造成了Retrofit+Rx了。虽然暂时还看不出多大的优势,似乎只有在最后测试时获取token再获取数据那里稍微简单一点,但是,在正式使用的时候token不是第一次请求就保存下来了么,这种形式应该用不上吧。
    没错,在以上场景只是测试方便,在正式使用的时候并用不上。
    但是接下来的需求,RxJava应该能够让你心服口服。

    有点累,下篇博客再更吧。

  • 相关阅读:
    CentOs下Mongodb的下载与安装
    Mysql的sql_mode
    【Android】无限滚动的HorizontalScrollView
    Android 交错 GridView
    Android文档资源大放送 感兴趣的话可以网盘下载(个人收集)
    2014年最新720多套Android源码2.0GB免费一次性打包下载
    安卓开发之刮刮乐实例教程
    Android捕获崩溃异常
    Android -- Messager与Service
    Git的简单使用
  • 原文地址:https://www.cnblogs.com/onetwo/p/7278106.html
Copyright © 2011-2022 走看看