Retrofit2+Okhttp3+Rxjava2通过SOAP协议请求WebService

来源:互联网 发布:乐乎城市青年社区租房 编辑:程序博客网 时间:2024/05/20 09:25

Retrofit2+Okhttp3+Rxjava2通过SOAP协议请求WebService

刚入职新公司不久,花了九牛二虎把公司源码阅读了一遍,用两个字形容就是:”卧槽”,这写的啥玩意啊,和领导商议之后打算用空余时间重构一下源码,其中主要是网络请求最为频繁之一(感觉是在说废话),发现后台是WebService,以前都是JAVA的,这没弄过啊,经过查阅之后可以用Ksoap2来进行请求,发现Ksoap2挺麻烦的,完全没有之前okhttp+Retrofit那么容易,所以简单的封装了一下基于Retrofit2+Okhttp3+Rxjava2的一个SOAP协议请求库。

主要的就是Header,以及参数(注意参数格式)

第三方依赖//retrofit依赖compile 'com.squareup.retrofit2:retrofit: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'}compile 'com.squareup.retrofit2:converter-gson:2.2.0'compile 'com.squareup.retrofit2:converter-scalars:2.2.0'compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'//OkHttp依赖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'//RxJava依赖compile 'io.reactivex.rxjava2:rxandroid:2.0.1'// Because RxAndroid releases are few and far between, it is recommended you also// explicitly depend on RxJava's latest version for bug fixes and new features.compile 'io.reactivex.rxjava2:rxjava:2.0.9'

请求体RequestEnvelope

import org.simpleframework.xml.Element;import org.simpleframework.xml.Namespace;import org.simpleframework.xml.NamespaceList;import org.simpleframework.xml.Root;@Root(name = "soap: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 RequestEnvelope {    @Element(name = "soap:Body", required = false)    public RequestBody body;    public RequestEnvelope(RequestBody body) {        this.body = body;    }}

请求体RequestBody

import org.simpleframework.xml.Element;import org.simpleframework.xml.Root;@Root(name = "soap:Body", strict = false)public class RequestBody {    @Element(name = "Move_GetDate", required = false)    public RequestModel AssetMaterialInfo;    public RequestBody(RequestModel assetMaterialInfo) {        AssetMaterialInfo = assetMaterialInfo;    }}

请求体RequestModel

import org.simpleframework.xml.Element;import org.simpleframework.xml.Namespace;import org.simpleframework.xml.Root;@Root(name = "Move_GetDate", strict = false)@Namespace(reference = "http://tempuri.org/")public class RequestModel {    @Element(name = "Code", required = false)    public String Code;    @Element(name = "Info", required = false)    public String Info;    @Element(name = "SNum", required = false)    public String SNum;    @Element(name = "yhnm", required = false)    public String yhnm;    @Element(name = "ipdz", required = false)    public String ipdz;    public RequestModel(String Code, String Info,String SNum,String yhnm,String ipdz) {        this.Code = Code;        this.Info = Info;        this.SNum = SNum;        this.yhnm = yhnm;        this.ipdz = ipdz;    }}

接下来就是响应体了ResponseEnvelope

import org.simpleframework.xml.Element;import org.simpleframework.xml.Namespace;import org.simpleframework.xml.NamespaceList;import org.simpleframework.xml.Root;// 指定节点名称,soap:可以省略,即@Root(name = "Envelope")// 当类名与节点名相同时,name属性可以省略,即@Root@Root(name = "soap:Envelope")// 指定命名空间集合,内部可以嵌套多个@Namespace注解@NamespaceList({        /*         *  指定命名空间,reference属性指定命名空间名称,prefix属性指定前缀.         *  例如:         *      命名空间为:xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         *      则用注解表示为@Namespace(reference = "http://www.w3.org/2001/XMLSchema-instance/", prefix = "xsi")         */        @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 ResponseEnvelope {    // 指定子节点的节点名,应与AssetResponseBody的@Root注解对应    @Element(name = "Body", required = false)    public ResponseBody responseBody;}

响应体ResponseBody

import org.simpleframework.xml.Element;import org.simpleframework.xml.Root;@Root(name = "Body", strict = false)public class ResponseBody {    @Element(name = "Move_GetDateResponse", required = false)    public ResponseModel responseModel;}

响应体ResponseModel

import org.simpleframework.xml.Attribute;import org.simpleframework.xml.Element;import org.simpleframework.xml.Root;@Root(name = "Move_GetDateResponse")public class ResponseModel {    @Attribute(name = "xmlns", empty = "http://tempuri.org/", required = false)    public String nameSpace;    @Element(name = "Move_GetDateResult")    public String result;}

然后就是API

public interface ApiStore {    /*     * 指定请求头:     * "Content-Type: text/xml; charset=utf-8"指定文本格式,及编码格式     * SOAPAction的值为     * 分解为http://tempuri.org/ + Move_GetDate,其实就是命名空间+接口名     */    @Headers({            "Content-Type: text/xml; charset=utf-8",            "SOAPAction: http://tempuri.org/Move_GetDate"    })    @POST("DBHelperOra.asmx")    Observable<ResponseEnvelope> getAssetInfo(@Body RequestEnvelope requestEnvelope);}
    public static NetWorkClient getApiService() {        if (apiStore == null) {            apiStore = createService(ApiStore.class);        }        return netWorkClient;    }    /**     * 缺省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(10, TimeUnit.SECONDS);        okHttpClient.writeTimeout(10, TimeUnit.SECONDS);        okHttpClient.addInterceptor(definterceptor);        okHttpClient.addInterceptor(logging);        //失败重连        okHttpClient.retryOnConnectionFailure(true);        return okHttpClient;    }    /**     * 默认拦截器GET     * 默认拦截器缓存只是针对GET请求,并不缓存POST     */    private static Interceptor defcacheInterceptor = new Interceptor() {        @Override        public Response intercept(Chain chain) throws IOException {            Request request = chain.request();            if (!NetWorkUtil.isConnect(mContext)) {//没网强制从缓存读取                request = request.newBuilder()                        .cacheControl(CacheControl.FORCE_CACHE)                        .build();            }            Response response = chain.proceed(request);            Response responseLatest;            if (NetWorkUtil.isConnect(mContext)) {                int maxAge = 0; //有网络时 设置缓存超时时间0个小时                responseLatest = response.newBuilder()                        .header("Cache-Control", "public, max-age=" + maxAge)                        .removeHeader("Pragma")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效                        .build();            } else {                int maxStale = 60 * 60 * 72; // 没网失效72小时                responseLatest = response.newBuilder()                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)                        .removeHeader("Pragma")                        .build();            }            return responseLatest;        }    };    /**     * 缓存     *     * @return     */    private static Cache defcache() {        int cacheSize = 10 * 1024 * 1024;        if (mContext == null) {            throw new NullPointerException("未在Application中初始");        }        return new Cache(PathUtils.getDiskCacheDir(mContext, BASE_CACHE_PATH), cacheSize);    }    private static <T> T createService(Class<T> serviceClass) {        //------------------------设置缓存策略------------------------------------        OkHttpClient.Builder okHttpClient = getdefOkhttp();        //设置Cache目录        okHttpClient.cache(defcache());        //设置缓存        okHttpClient.addInterceptor(defcacheInterceptor);        okHttpClient.addNetworkInterceptor(defcacheInterceptor);        //--------------------------------------------------------------        Retrofit retrofit = new Retrofit.Builder()                .baseUrl(BASE_URL)                //设置OKHttpClient                .client(okHttpClient.build())                .addConverterFactory(ScalarsConverterFactory.create())                //gson转化器//                .addConverterFactory(GsonConverterFactory.create())                .addConverterFactory(SimpleXmlConverterFactory.create(new Persister(new AnnotationStrategy())))                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//                .build();        return retrofit.create(serviceClass);    }    /**     * 具体请求方式     * @param requestEnvelope     * @param callBack     */    public static void execute(RequestEnvelope requestEnvelope, final RequestCallBack callBack) {        apiStore.getAssetInfo(requestEnvelope)                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Observer<ResponseEnvelope>() {                    @Override                    public void onSubscribe(@NonNull Disposable d) {                        Log.d("msg", "onSubscribe");                        callBack.onStart();                    }                    @Override                    public void onNext(@NonNull ResponseEnvelope responseEnvelope) {                        String str = responseEnvelope.responseBody.responseModel.result;                        Log.d("msg///////", str);                        onNext(responseEnvelope);                    }                    @Override                    public void onError(@NonNull Throwable e) {                        Log.d("msg", e.getMessage());                        callBack.onFail(e.getMessage());                    }                    @Override                    public void onComplete() {                        Log.d("msg", "---------------------------------------------");                        callBack.onEnd();                    }                });

请求方式

    // 初始化请求体    RequestModel requestModel = new RequestModel("CodeData",            "InfoData",            "SNumData",            "yhnmData",            "ipdzData");    RequestBody requestBody = new RequestBody(requestModel);    RequestEnvelope requestEnvelope = new RequestEnvelope(requestBody);    NetWorkClient.getApiService().execute(requestEnvelope, new RequestCallBack() {            @Override            public void onStart() {            }            @Override            public void onEnd() {            }            @Override            public void onResponse(ResponseEnvelope response) {            }            @Override            public void onFail(String msg) {            }    });
2 0