RxJava学习笔记2:基于RxJava+okHttp的Rest Cas登录实现

来源:互联网 发布:经传软件官网 编辑:程序博客网 时间:2024/05/04 20:40

1.本来打算用已经对RxJava提供支持的Retrofit2实现,但Retrofit2的文档基本没有,没有找到可以获取Cookie、对status code处理的方法,所以还是用okHttp进行了实现
2.上周开始学习RxJava,是想解决多个网络请求嵌套访问的问题,CAS算是比较典型的多个同步请求后才能获取实际需要的内容。
3.代码中用到了”如何用okHttp进行Cookie的自动管理”,App这边对应Cas Server,服务A,服务B,这样至少要处理3个域名下的Cookie,自动管理是不能少的。代码来自http://stackoverflow.com/questions/25461792/persistent-cookie-store-using-okhttp-2-on-android
4.这次App实现决定采用了MVP模式,一个人做的好处就是可以很快的实现的自己的想法,当时觉得太麻烦了,那么多接口,重用可能性很小……这次登录请求由原来的基于Volley的普通请求改成现在的代码,幸亏用了MVP:)

依赖:

    compile 'com.squareup.okhttp:okhttp:2.6.0'    compile 'com.squareup.okhttp:okhttp-urlconnection:2.6.0'    compile 'io.reactivex:rxjava:1.1.0'    compile 'io.reactivex:rxandroid:1.1.0'    compile 'com.google.code.gson:gson:2.5'    compile 'com.jakewharton.timber:timber:4.1.0'

CAS的Rest接口:
http://jasig.github.io/cas/4.1.x/protocol/REST-Protocol.html

  1. 以用户名和密码访问CAS Server获取 TGT
  2. 用1返回的TGT和约定好的服务端Service地址访问CAS Server,获取ST
  3. 用ST请求Service地址,获取Cookie

1.封装获取TGT请求返回Observable

    public static Observable<String> getTGT(final String account, final String password) {        return Observable.create(new Observable.OnSubscribe<String>() {            @Override            public void call(final Subscriber<? super String> subscriber) {                try {                    String tgtPath = casServer + "/v1/tickets";                    FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();                    formEncodingBuilder.add("username", account);                    formEncodingBuilder.add("password", password);                    RequestBody formBody = formEncodingBuilder.build();                    Request request = new Request.Builder()                            .url(tgtPath)                            .post(formBody)                            .build();                    Response response = mOkHttpClient.newCall(request).execute();                    int code = response.code();                    if (201 == code) {                        String location = response.header("Location");                        String tgt = location.substring(location.lastIndexOf("/") + 1);                        subscriber.onNext(tgt);                    } else {                        System.out.println(code);                        System.out.println(response.body().string());                        subscriber.onError(new Exception("error"));                    }                } catch (Exception e) {                    subscriber.onError(e);                }            }        });    }

2.获取ST

    public static Observable<String> getST(final String tgt, final String service) {        return Observable.create(new Observable.OnSubscribe<String>() {            @Override            public void call(final Subscriber<? super String> subscriber) {                try {                    String stPath = casServer + "/v1/tickets/" + tgt; // POST /cas/v1/tickets/{TGT id} HTTP/1.0                    FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();                    formEncodingBuilder.add("service", service);                    RequestBody formBody = formEncodingBuilder.build();                    Request request = new Request.Builder()                            .url(stPath)                            .post(formBody)                            .build();                    Response response = mOkHttpClient.newCall(request).execute();                    if (!response.isSuccessful()) {                        throw new IOException("Unexpected code " + response);                    }                    String st = response.body().string();                    subscriber.onNext(st);                    subscriber.onCompleted();                } catch (IOException e) {                    subscriber.onError(e);                }            }        });    }

3.换取Cookie

    public static Observable< List<String>> getCookie(final String st, final String service){        return Observable.create(new Observable.OnSubscribe< List<String>>() {            @Override            public void call(Subscriber<? super  List<String>> subscriber) {                try {                    String cookiePath = service + "?" + "ticket=" + st;                    Request request = new Request.Builder()                            .url(cookiePath)                            .build();                    Response response = mOkHttpClient.newCall(request).execute();                    if (!response.isSuccessful()) {                        throw new IOException("Unexpected code " + response);                    }                    List<String> list = response.headers("Set-Cookie");                    subscriber.onNext(list);                    subscriber.onCompleted();                }catch (Exception e){                    e.printStackTrace();                    subscriber.onError(e);                }            }        });    }

整合

    public void login(final String account, final String password, final String service) {        getTGT(account, password)                .flatMap(new Func1<String, Observable<String>>() {                    @Override                    public Observable<String> call(String tgt) {                        return getST(tgt, service);                    }                })                .flatMap(new Func1<String, Observable<List<String>>>() {                    @Override                    public Observable<List<String>> call(String st) {                        return getCookie(st, service);                    }                })                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Observer<List<String>>() {                    @Override                    public void onCompleted() {                       Timber.e("onCompleted");                    }                    @Override                    public void onError(Throwable e) {                        Toast.makeText(LoginActivity.this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();                        Timber.e("onError");                        e.printStackTrace();                    }                    @Override                    public void onNext(List<String> s) {                        Toast.makeText(LoginActivity.this, s.toArray().toString(), Toast.LENGTH_SHORT).show();                        Timber.e("onNext");                    }                });    }
3 1