Retorfit2.0+Rxjava1+Okhttp3实现soap协议的Webservice

最近业余接了一个项目,服务器端使用的是SOAP协议来传输数据,虽然之前也使用过ksoap包来实现SOAP协议传输,但懂不能一直停留在之前的技术上吧… 所以,这次我想换个方法来实现SOAP协议传输。

既然要换SOAP协议的实现方法,那么就先研究一下这个SOAP协议具体是个什么东东
下面是一段SOAP请求:

POST /WebServices/WeatherWebService.asmx HTTP/1.1

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.3603)
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://WebXml.com.cn/getSupportCity"
Host: www.webxml.com.cn
Content-Length: 348
Expect: 100-continue
Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><getSupportCity xmlns="http://WebXml.com.cn/"><byProvinceName>广东</byProvinceName></getSupportCity></soap:Body></soap:Envelope>

上面的内容显示,其实SOAP协议实现的就是一个HTTP的POST请求,不过使用了SOAPAction来标识请求的内容是SOAP协议的,接收端需要根据SOAP协议来解析内容;最后的XML格式的内容就是SOAP具体的请求内容了。

明白了这层关系,那么我们就可以考虑使用retrofit和okhttp来实现SOAP协议了。
本文使用到的库:

 // Rxjava
    compile 'io.reactivex:rxandroid:1.2.1'
    compile 'io.reactivex:rxjava:1.1.6'
    // okhttp3
    compile 'com.squareup.okhttp3:okhttp:3.7.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.7.0'
    compile 'com.squareup.okhttp3:okhttp-urlconnection:3.7.0'
    // Retorfit2
    compile 'com.squareup.retrofit2:retrofit:2.2.0'
    //将网络请求转化成java bean对象 也可以自定义
    compile 'com.squareup.retrofit2:converter-gson:2.2.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.2.0'
    //XML解析
    compile('com.squareup.retrofit2:converter-simplexml:2.2.0') {
        exclude group: 'xpp3', module: 'xpp3'
        exclude group: 'stax', module: 'stax-api'
        exclude group: 'stax', module: 'stax'
    }
    //retrofit和rxandroid连接
    compile 'com.squareup.retrofit2:adapter-rxjava:2.2.0'

注:由于SOAP使用的是XML的数据格式,因此需要使用xml解析器,但需要去掉retrofit中默认的xml格式解析的模块。

首先,需要对okhttp3进行一些设置,包括缓存以及超时机制等,直接上代码:

 //------------------------设置缓存策略------------------------------------
 OkHttpClient.Builder okHttpClient = getdefOkhttp();
 //设置Cache目录
 okHttpClient.cache(defcache());
 //设置缓存
 okHttpClient.addInterceptor(defcacheInterceptor);
 okHttpClient.addNetworkInterceptor(defcacheInterceptor);
 //--------------------------------------------------------------
 mOkHttpClient = okHttpClient.build();
 /**
 * 缓存
 *
 * @return
 */
 private static Cache defcache() {
    int cacheSize = 10 * 1024 * 1024;
    return new Cache(new File(FileUtil.getRootPath() + File.separator + "cache"), cacheSize);
 }
/**
* 缺省OKHttp配置
*
* @return
*/
private static OkHttpClient.Builder getdefOkhttp() {
   //Log相关
   HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
   logging.setLevel(HttpLoggingInterceptor.Level.BODY);

   OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
   okHttpClient.connectTimeout(10, TimeUnit.SECONDS);
   okHttpClient.readTimeout(8, TimeUnit.SECONDS);
   okHttpClient.writeTimeout(8, TimeUnit.SECONDS);
   okHttpClient.addInterceptor(logging);
   //失败重连
   okHttpClient.retryOnConnectionFailure(true);
   return okHttpClient;
}

然后,配置retrofit2,注意使用的是SimpleXmlConverterFactory:

Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
                .baseUrl(url)
                //设置OKHttpClient
                .client(mOkHttpClient)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(SimpleXmlConverterFactory.create(new Persister(new AnnotationStrategy())))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create());
        return retrofitBuilder.build().create(serviceClass);

OK,以上完成了HTTP请求的通信配置,接下来就是组装SOAP请求内容以及解析SOAP返回值的部分。

首先,我们需要使用一个工具:SOAPUI,来确定服务器端的SOAP协议版本,协议的命名空间。方法名称以及参数等信息,举个栗子:

请求内容:

这里写图片描述

应答内容:(请忽略应答错误内容….)
这里写图片描述

整明白请求以及应答的头部以及具体内容之后,接下来就是哟个retrofit的simplexml解析器来组装请求和解析应答:(注解的方式)

请求内容:

// 请求头部最外层接口
public abstract class ISOAPReqEnv {
    @Element(name = "soapenv:Body")
    ISOAPReqBody mBody = null;
}

// 请求头部body接口
public abstract class ISOAPReqBody {

}

// 请求头部env层以及body层的实现,因为所有请求的这两层格式都一样
@Root(name = "soapenv:Envelope")
@NamespaceList({
        @Namespace(reference = "http://tempuri.org/", prefix = "tem"),
        @Namespace(reference = "http://schemas.xmlsoap.org/soap/envelope/", prefix = "soapenv")
})
public class SOAPReqEnv extends ISOAPReqEnv {
    public SOAPReqEnv(ISOAPReqBody body) {
        this.mBody = body;
    }
}
......

// 登录请求body
@Root(name = "soapenv:Body", strict = false)
public class SOAPLoginReqBody extends ISOAPReqBody {
    @Element(name = "tem:AppLogin")
    private SOAPLoginReqParams mLoginParams;

    public SOAPLoginReqBody(SOAPLoginReqParams loginParams) {
        this.mLoginParams = loginParams;
    }
}
// 登录请求参数
@Root(name = "tem:AppLogin", strict = false)
public class SOAPLoginReqParams {
    @Element(name = "tem:key")
    private String mKey;
    @Element(name = "tem:userid")
    private String mUserId;
    @Element(name = "tem:pwd")
    private String mPwd;
    @Element(name = "tem:hospitalName")
    private String hospital;

    public SOAPLoginReqParams(String key, String userId, String pwd) {
        this.mKey = key;
        this.mUserId = userId;
        this.mPwd = pwd;
    }
}

说明一下参数,如果参数中存在数组,可使用数组注解:

@ElementArray(name = "tem:filespath", entry = "tem:string")
    private String[] mFilePaths;

应答内容:

// 应答头部最外层
@Root(name = "Envelope")
@NamespaceList({
        @Namespace(reference = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi"),
        @Namespace(reference = "http://www.w3.org/2001/XMLSchema", prefix = "xsd"),
        @Namespace(reference = "http://schemas.xmlsoap.org/soap/envelope/", prefix = "soap")
})
public class SOAPLoginResEnv {
    @Element(name = "Body")
    SOAPLoginResBody mBody = null;

    public SOAPLoginResBody getBody() {
        return mBody;
    }
}

// 应答头部body
@Root(name = "Body", strict = false)
public class SOAPLoginResBody {
    @Element(name = "userLoginResponse")
    private SOAPLoginResParams mLoginParams;

    public SOAPLoginResParams getLoginParams() {
        return mLoginParams;
    }
}

// 应答内容
@Root(name = "userLoginResponse", strict = false)
@Namespace(reference = "http://tempuri.org/")
public class SOAPLoginResParams{
    @Element(name = "userLoginResult")
    private String mResult;

    public String getResult() {
        return mResult;
    }

    public void setResult(String result) {
        mResult = result;
    }
}

由于我们这边服务端的应答内容都是自行组装的xml格式的字符串,所以我们的应答内容中就只有一个String类型的response。

如果你的应答内容也是一个类似请求参数类型的,那么可以继续使用请求参数类型的注解方式来解析。

最后,由于我们使用了rxjava1的方式来进行一步的网络请求和解析,我们需要这样发送请求和接收应答:

// 发送请求接口
public interface IServiceStore {
    /*
     * 指定请求头:
     * "Content-Type: text/xml; charset=utf-8"指定文本格式,及编码格式
     * SOAPAction的值为
     * 分解为http://tempuri.org/ + userLogin,其实就是命名空间+接口名
     */
    @Headers({
            "Content-Type: text/xml; charset=utf-8",
            "SOAPAction: http://tempuri.org/userLogin"
    })
    @POST("webToPad.asmx")
    Observable<SOAPLoginResEnv> userLogin(@Body ISOAPReqEnv requestEnvelope);
}

    public static void login(ISOAPReqEnv soapReqEnv, final ResultCallback callback) {
        createStore();

......
// 发送请求接收应答的实现        
public static void login(ISOAPReqEnv soapReqEnv, final ResultCallback callback) {
        createStore();
        mRxServiceStore.userLogin(soapReqEnv).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<SOAPLoginResEnv>() {
            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(@NonNull Throwable e) {
                e.printStackTrace();
                callback.fail((Exception) e);
            }

            @Override
            public void onNext(@NonNull SOAPLoginResEnv isoapResEnv) {
                String result = isoapResEnv.getBody().getLoginParams().getResult();
                if (isSuccess(result)) {
                    callback.success(result);
                } else {
                    onError(new Exception(StringUtil.getMiddle(result, "<msg>", "</msg>")));
                }
            }
        });
    }
......

 private static IServiceStore mRxServiceStore;

    private static void createStore() {
        mRxServiceStore = createService(IServiceStore.class);
    }

这样就完成了SOAP协议的实现。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: RetrofitRxJava和LiveData是Android开发中常用的三个库,用于提升网络请求和数据响应的效率和易用性。 首先来说说Retrofit,它是Square公司开发的一个网络请求库,可以简化HTTP请求的过程。具体来说,Retrofit通过注解方式定义API接口,支持多种数据格式的解析,如JSON、XML等,提供了丰富的请求方法和参数,可以使用线程池进行并发请求Retrofit可以根据接口的定义,自动将HTTP请求转化为对应的Java方法调用,并将服务器返回的数据转化为Java对象。通过Retrofit,我们可以轻松地进行网络请求,提高了开发效率。 然后是RxJavaRxJava基于观察者模式和函数式编程思想,是一个强大的异步编程库。它提供了丰富的操作符和线程调度器,可以轻松地处理复杂的异步任务。通过RxJava,我们可以通过链式调用的方式组合多个异步操作,将它们串行或并行执行,还可以添加错误处理和重试机制。RxJava可以与Retrofit配合使用,通过它的观察者模式,可以实现将网络请求结果流式化,使得异步任务的处理更加简洁和灵活。 最后是LiveData,LiveData是Google在Android Architecture Components中引入的一个观察者模式类。LiveData具有生命周期感知能力,可以根据Activity或Fragment的生命周期自动管理数据的更新和释放,避免了内存泄漏和空指针异常。LiveData还支持后台线程发送数据,可以与RxJava搭配使用来实现异步数据更新。LiveData使得数据的处理更加安全可控,为开发者提供了一种便捷的方式来更新UI和响应数据变化。 综上所述,Retrofit提供了简洁的网络请求接口,RxJava提供了强大的异步编程能力,LiveData提供了响应式的数据更新机制。它们三者的结合使得网络请求和数据响应的处理更加简单高效,提高了开发效率和代码质量。 ### 回答2: RetrofitRxJava和LiveData是三种在Android开发中经常使用的库,用于进行网络请求和响应处理、异步操作和数据监听。 Retrofit是一种用于处理网络请求的库,它能够将网络请求与后台API进行连接,通过定义接口和请求方法,方便地进行网络请求和处理响应结果。Retrofit通过注解的方式定义网络请求方式、URL等信息,结合Gson等库进行数据解析,使得网络请求变得简单高效。 RxJava是一种响应式编程库,它能够方便地实现异步操作和事件流处理。通过使用Observables(被观察者)和Subscribers(观察者),我们可以将异步任务和数据流以扁平化的方式进行处理。RxJava提供了丰富的操作符,能够方便地实现异步请求、线程切换、数据过滤、转换等功能,使得代码逻辑更加简洁和可读。 LiveData是一种用于在Android应用中实现数据监听的库。LiveData可以感知生命周期并自动更新界面数据,能够保证数据的一致性和UI的正确性。LiveData可以与ViewModel结合使用,通过观察数据的变化来更新UI。与传统的观察者模式相比,LiveData具有更丰富的功能,例如避免内存泄漏、解决配置变化等问题。 综上所述,Retrofit是用于处理网络请求的库,通过简单高效的方式连接后台API;RxJava是用于实现异步操作和事件流处理的库,提供丰富的操作符;LiveData是用于在Android应用中实现数据监听的库,能够自动更新界面数据。这三个库的结合使用可以更加方便地进行网络请求、数据处理和UI更新。 ### 回答3: RetrofitRxJava和LiveData都是在Android开发中常用的工具或库。它们各自有着不同的功能和用途。 Retrofit是一个用于网络请求的库,它能够更方便地进行网络通信。通过Retrofit,我们可以定义网络请求的接口,定义请求的方法和参数,并且可以方便地处理返回的数据。Retrofit底层使用了OkHttp库,可以实现网络请求的异步调用和线程切换,提高了网络请求的效率和稳定性。 RxJava是一个基于观察者模式的库,它提供了一套丰富的函数式编程接口,能够处理异步事件流。通过RxJava,我们可以轻松地创建、转换和操作Observable(被观察者),并且可以使用丰富的操作符来处理数据的过滤、变换和组合。RxJava还支持线程切换和错误处理,能够更好地处理异步任务。 LiveData是Android架构组件库中的一个组件,它用于在数据发生变化时通知观察者。LiveData可以感知Activity或Fragment的生命周期,并且会将数据更新通知给观察者。与传统的观察者模式相比,LiveData具有生命周期感知能力,可以避免内存泄漏和空指针异常。LiveData还支持数据的多个观察者,可以实现多个界面或组件之间的数据共享。 综上所述,Retrofit用于网络请求RxJava用于处理异步事件流,LiveData用于在数据变化时通知观察者。它们在Android开发中各有不同的应用场景,能够提高开发效率和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值