Retrofit2+Okhttp3+Rxjava2 Request Web Service through SOAP Protocol

Keywords: xml Retrofit OkHttp Attribute

Retrofit2+Okhttp3+Rxjava2 Request Web Service through SOAP Protocol

Shortly after joining the new company, I spent nine nights and two tigers reading the company's source code, describing it in two words as "bedroom". What's this writing about? After consulting with the leaders, I intend to reconstruct the source code in my spare time. It's mainly one of the most frequent network requests (feeling is talking nonsense). I found that the backstage is Web Service, which used to be JAVA, which I haven't done before. After consulting, Ksoap2 can be used for requests. It is found that Ksoap2 is troublesome. It is not as easy as okhttp+Retrofit before. So it simply encapsulates a SOAP protocol request Library Based on Retrofit2+Okhttp3+Rxjava2.

Third-party dependency
//retrofit dependency
compile 'com.squareup.retrofit2:retrofit:2.2.0'
//XML parsing
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 dependence
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 dependence
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'

Request Envelope

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;
    }
}

Request Body

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;
    }
}

Request Body Request Model

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;
    }
}

Next comes the response body, Response Envelope.

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.NamespaceList;
import org.simpleframework.xml.Root;

// Specify the node name, soap: can be omitted, that is @Root (name = Envelope)
// When the class name is the same as the node name, the name attribute can be omitted, i.e. @Root
@Root(name = "soap:Envelope")
// Specify a namespace collection that can nest multiple @Namespace annotations internally
@NamespaceList({
        /*
         *  Specify the namespace, the reference attribute specifies the namespace name, and the prefix attribute specifies the prefix.
         *  For example:
         *      The namespace is: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         *      The annotation is @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 {
    // Specifying the node name of the child node should correspond to the @Root annotation of AssetResponseBody
    @Element(name = "Body", required = false)
    public ResponseBody responseBody;
}

Response Body

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;
}

Response Body Response Model

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;
}

Then there's the API.

public interface ApiStore {
    /*
     * Specify the request header:
     * "Content-Type: text/xml; charset=utf-8"Specify text format, and encoding format
     * SOAPAction The value is
     * Decomposition into http://tempuri.org/+Move_GetDate, which is actually namespace+interface name
     */
    @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;
    }




    /**
     * Default OKHttp configuration
     * @return
     */
    private static OkHttpClient.Builder getdefOkhttp() {
        //Log correlation
        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);

        //Failure reconnect
        okHttpClient.retryOnConnectionFailure(true);
        return okHttpClient;
    }

    /**
     * Default interceptor GET
     * The default interceptor cache is only for GET requests and does not cache POST
     */
    private static Interceptor defcacheInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (!NetWorkUtil.isConnect(mContext)) {//Mandatory read from cache without network
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
            }
            Response response = chain.proceed(request);
            Response responseLatest;
            if (NetWorkUtil.isConnect(mContext)) {
                int maxAge = 0; //Setting up a cache timeout time of 0 hours when there is a network
                responseLatest = response.newBuilder()
                        .header("Cache-Control", "public, max-age=" + maxAge)
                        .removeHeader("Pragma")// Clear header information, because if the server does not support it, it will return some interference information. Clear header information will not take effect below.
                        .build();
            } else {
                int maxStale = 60 * 60 * 72; // Failure of power grid for 72 hours
                responseLatest = response.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .removeHeader("Pragma")
                        .build();
            }
            return responseLatest;
        }
    };
    /**
     * cache
     *
     * @return
     */
    private static Cache defcache() {
        int cacheSize = 10 * 1024 * 1024;
        if (mContext == null) {
            throw new NullPointerException("Not in Application Middle initial");
        }
        return new Cache(PathUtils.getDiskCacheDir(mContext, BASE_CACHE_PATH), cacheSize);
    }




    private static <T> T createService(Class<T> serviceClass) {
        //--------------------------------------------------------------------------------------------------------------------------------------------------------------------
        OkHttpClient.Builder okHttpClient = getdefOkhttp();
        //Setting Cache Directory
        okHttpClient.cache(defcache());
        //Set cache
        okHttpClient.addInterceptor(defcacheInterceptor);
        okHttpClient.addNetworkInterceptor(defcacheInterceptor);
        //--------------------------------------------------------------
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                //Setting up OKHttpClient
                .client(okHttpClient.build())
                .addConverterFactory(ScalarsConverterFactory.create())
                //gson converter
//                .addConverterFactory(GsonConverterFactory.create())
                .addConverterFactory(SimpleXmlConverterFactory.create(new Persister(new AnnotationStrategy())))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//
                .build();

        return retrofit.create(serviceClass);
    }

    /**
     * Specific mode of request
     * @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();
                    }
                });

Request mode

    // Initialization request body
    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) {

            }
    });

Posted by phpHappy on Mon, 11 Feb 2019 22:12:21 -0800