Retrofit 用Soap協(xié)議訪問WebService 詳解

參考

1、結合Retrofit使用post請求訪問WebService
2、retrofit2調(diào)用webservice-2.基本實現(xiàn)

前言

1匹涮、首先不要把這個想的太復雜,它就是使用【soap】協(xié)議的請求槐壳,數(shù)據(jù)格式都是【xml】然低,基礎還是http的post請求,但是它的規(guī)范顯然更多一些宏粤,總體逃不過【Request和Response】脚翘。
2、以下所有的范例都是使用 【 WeatherWebService 】 這個網(wǎng)站绍哎,它提供了【Soap1.1 和 Soap1.2 】的請求范例来农,有【Request和Response】報文可看,這樣更好理解規(guī)范和格式

一崇堰、WebService 基礎與注意點(第一次用的話稍微看看)

有soap1.1,soap1.2的區(qū)別沃于,請求的header不同,xml的內(nèi)容也略有不同啦~~
跳轉閱讀》》》【 WebService 基礎知識點和用Postman調(diào)試】海诲,復制了部分內(nèi)容過來

Soap1.1:

1繁莹、xmlns后基本都是namespace,比如envelopse標簽有三個namespace特幔,getSupportCity這個方法名有一個namespace
2咨演、區(qū)分soap1.1的是:【xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"】
3、soap1.1的請求header有:【Content-Type: text/xml; charset=utf-8 】和【SOAPAction: "http://WebXml.com.cn/getSupportCity"】

//-------------------------------------Request------------------------------------
POST /WebServices/WeatherWebService.asmx HTTP/1.1
Host: www.webxml.com.cn
Content-Type: text/xml; charset=utf-8   //header中的哦~~
Content-Length: length
SOAPAction: "http://WebXml.com.cn/getSupportCity"  //header中的哦~~

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  //標記為soap1.1協(xié)議
  <soap:Body>
    <getSupportCity xmlns="http://WebXml.com.cn/">  //method和其namespace
      <byProvinceName>string</byProvinceName>     //param
    </getSupportCity>
  </soap:Body>
</soap:Envelope>

//-------------------------------------Response------------------------------------
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getSupportCityResponse xmlns="http://WebXml.com.cn/">  //結果集啦~~
      <getSupportCityResult>
        <string>string</string>
        <string>string</string>
      </getSupportCityResult>
    </getSupportCityResponse>
  </soap:Body>
</soap:Envelope>
Soap1.2:

1蚯斯、略薄风,同上
2、區(qū)分soap1.2的是:【xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"】
3拍嵌、soap1.2的請求header有:【application/soap+xml; charset=utf-8 】和沒有【SOAPAction】

//-------------------------------------Requeset------------------------------------
POST /WebServices/WeatherWebService.asmx HTTP/1.1
Host: www.webxml.com.cn
Content-Type: application/soap+xml; charset=utf-8  //header中的遭赂,與soap1.1不同哦,而且沒有soapaction了横辆,需要注意~~~~
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> //標記為soap1.2協(xié)議
  <soap12:Body>
    <getSupportCity xmlns="http://WebXml.com.cn/">
      <byProvinceName>string</byProvinceName>
    </getSupportCity>
  </soap12:Body>
</soap12:Envelope>

//-------------------------------------Response------------------------------------
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getSupportCityResponse xmlns="http://WebXml.com.cn/">  //結果集~~~
      <getSupportCityResult>
        <string>string</string>
        <string>string</string>
      </getSupportCityResult>
    </getSupportCityResponse>
  </soap12:Body>
</soap12:Envelope>

二撇他、實例

1、公共部分

(1)app 的 builde.gradle添加依賴庫

    compile 'com.squareup.okhttp3:okhttp:3.6.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.0.1'
    compile 'com.squareup.retrofit2:retrofit:2.2.0'
    //retrofit - webservice
    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-scalars:2.2.0'
    compile 'com.squareup.retrofit2:converter-gson:2.2.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'

(2)Retrofit的訪問工具類

/**
 *  Retrofit
 * Created by wujn on 2018/5/25.
 *
 * request : webservice soap
 * response : xml data
 */

public class RetrofitSoapClient {
    //public ZYDApiService service;
    public SoapApiService service;

    private RetrofitSoapClient(){
        //okhttp log : 包含header狈蚤、body數(shù)據(jù)
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {LogUtil.i("RetrofitLog","retrofitBack = "+message);}
        });
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        //okhttp client
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .addInterceptor(loggingInterceptor)
                .build();

        //retrofit client
        Retrofit retrofit = new Retrofit.Builder()
                .client(client)
                .addConverterFactory(ScalarsConverterFactory.create())      //添加 String類型[ Scalars (primitives, boxed, and String)] 轉換器
                .addConverterFactory(SimpleXmlConverterFactory.create())    //添加 xml數(shù)據(jù)類型 bean-<xml
                .addConverterFactory(GsonConverterFactory.create())         //添加 json數(shù)據(jù)類型 bean->json
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl("http://www.webxml.com.cn")        //test baseurl 困肩;http://www.webxml.com.cn/WebServices/
                .build();
        service = retrofit.create(SoapApiService.class);
    }

    private static RetrofitSoapClient INSTANCE  = null;
    //獲取單例
    public static RetrofitSoapClient getInstance() {
        if(INSTANCE == null){
            INSTANCE = new RetrofitSoapClient();
        }
        return INSTANCE;
    }

}

--------------------------------------------------------------------------------------------

2、從簡單的開始脆侮,能訪問上有數(shù)據(jù)返回就不錯了锌畸。

2.1、簡單的soap1.1和1.2的訪問

2.1.1他嚷、接口類

1蹋绽、RequestBody和ResponseBody的基本參數(shù)不用說
2芭毙、根據(jù)網(wǎng)站提供的范例,soap1.1和soap1.2的RequestHeader是不一樣的卸耘,對應的@Body中的ResquetBody也是不一樣的

/**
 * Created by wujn on 2018/5/25.
 * Version : v1.0
 * Function: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx
 * 用來測試的
 *
 *  * 有幾點需要注意:
 * 1退敦、endpoint(baseurl-wsdl) : 不同使用中.wsdl或者?wsdl可以去掉
 * 2、namespace
 * 3蚣抗、soapaction
 * 4侈百、method
 *
 * Soap1.1
 * 格式:xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
 * 請求頭:1、Content-Type:text/xm;charset=UTF-8  2翰铡、SOAPAction= Namespace + Method
 *
 * Soap1.2
 * 格式:xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"
 * 請求頭:1钝域、Content-Type:application/soap+xml;charset=UTF-8  2、無SOAPAction
 *
 */

public interface SoapApiService {
    //--------------------------原始---------------------------------
    //soap1.1
    @Headers({"Content-Type:text/xml; charset=utf-8",
            "SOAPAction:http://WebXml.com.cn/getSupportCity" })
    @POST("/WebServices/WeatherWebService.asmx")
    Observable<ResponseBody> getSupportCity_11(@Body String s);

    //soap1.2
    @Headers({"Content-Type:application/soap+xml;charset=UTF-8" })
    @POST("/WebServices/WeatherWebService.asmx")
    Observable<ResponseBody> getSupportCity_12(@Body String s);
}
2.1.2锭魔、具體請求訪問

這里一定要注意例证,有一個坑,就是在RetrofitSoapClient中的轉換中必須加上
【.addConverterFactory(ScalarsConverterFactory.create())】否則傳的string會混亂迷捧,不符合soap協(xié)議格式织咧,然后一種報錯,說SoapVersion用錯啥的~~((((ToT)?~~這個著實浪費了一點時間

/**
     * 原始soap1.1訪問:把請求的requestbody全部用string弄出來
     * 注意全是xml形式的string漠秋,需要添加 addConverterFactory(ScalarsConverterFactory.create()) 否則有亂七八糟的符號
     * */
    public void testOrgSoap11(View v){
        String soap11 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                "  <soap:Body>\n" +
                "    <getSupportCity xmlns=\"http://WebXml.com.cn/\">\n" +
                "      <byProvinceName>福建</byProvinceName>\n" +
                "    </getSupportCity>\n" +
                "  </soap:Body>\n" +
                "</soap:Envelope>";

        addRxDestroy(RetrofitSoapClient.getInstance().service
                .getSupportCity_11(soap11) //its body
                .compose(RxSchedulers.<ResponseBody>io_main())
                .subscribeWith(new DisposableObserver<ResponseBody>() {

                    @Override
                    public void onNext(ResponseBody responseBody) {
                        try {
                            String result = responseBody.string();
                            LogUtil.d("testOrgSoap11 : webservice response result = \n"+result);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        LogUtil.e("testOrgSoap11 : ex="+e.getMessage());
                    }
                    @Override
                    public void onComplete() {}
                }));
    }


    /**
     * 原始soap1.2訪問:把請求的requestbody全部用string弄出來
     * 注意全是xml形式的string笙蒙,需要添加 addConverterFactory(ScalarsConverterFactory.create()) 否則有亂七八糟的符號
     * */
    public void testOrgSoap12(View v){
        String soap12 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                "<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">\n" +
                "  <soap12:Body>\n" +
                "    <getSupportCity xmlns=\"http://WebXml.com.cn/\">\n" +
                "      <byProvinceName>江蘇</byProvinceName>\n" +
                "    </getSupportCity>\n" +
                "  </soap12:Body>\n" +
                "</soap12:Envelope>";

        addRxDestroy(RetrofitSoapClient.getInstance().service
                .getSupportCity_12(soap12) //its body
                .compose(RxSchedulers.<ResponseBody>io_main())
                .subscribeWith(new DisposableObserver<ResponseBody>() {
                    @Override
                    public void onNext(ResponseBody responseBody) {
                        try {
                            String result = responseBody.string();
                            LogUtil.d("testOrgSoap12 : webservice response result = \n"+result);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        LogUtil.e("testOrgSoap12 : ex="+e.getMessage());
                    }
                    @Override
                    public void onComplete() {}
                }));
    }
2.1.3、拼接工具:針對不同公司其實不一樣的
public class ApiNode {
    // 正常字符-> <xxx>
    public static String toStart(String name) {
        return "<" + name + ">";
    }
    // 正常字符-> </xxx>
    public static String toEnd(String name) {
        return "</" + name + ">";
    }

    //soap 1.1
    public static String getRequestBody11(String method, Map<String, String> map) {
        StringBuffer sbf = new StringBuffer();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            sbf.append(ApiNode.toStart(entry.getKey()));
            sbf.append(entry.getValue());
            sbf.append(ApiNode.toEnd(entry.getKey()));
        }
        String str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
                "  <soap:Body>" +
                "    <" + method + " xmlns=\"http://WebXml.com.cn/\">" + sbf.toString() +
                "    </" + method + ">" +
                "  </soap:Body>" +
                "</soap:Envelope>";
        LogUtil.v(method+"Soap1.1 請求入?yún)?" + str);
        return str;
    }

    //soap 1.2
    public static String getRequestBody12(String method, Map<String, String> map) {
        StringBuffer sbf = new StringBuffer();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            sbf.append(ApiNode.toStart(entry.getKey()));
            sbf.append(entry.getValue());
            sbf.append(ApiNode.toEnd(entry.getKey()));
        }
        String str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">" +
                "  <soap12:Body>" +
                "    <" + method + " xmlns=\"http://WebXml.com.cn/\">" + sbf.toString() +
                "    </" + method + ">" +
                "  </soap12:Body>" +
                "</soap12:Envelope>";
        LogUtil.v(method+"Soap1.2 請求入?yún)?" + str);
        return str;
    }


}

--------------------------------------------------------------------------------------------

2.2庆锦、用bean的方式會不會好一點捅位,繼續(xù)哦

就是把數(shù)據(jù)封裝到bean里面,看的舒服一點搂抒,符合以前用json艇搀,resetful風格的那些請求

2.2.1、接口類:RequestEnvelope11 和ResponseEnvelope11需要看一下
public interface SoapApiService {
    //-----------------------------繼續(xù)封裝-------------------------------------
    //soap1.1
    @Headers({
            "Content-Type:text/xml; charset=utf-8",
            "SOAPAction:http://WebXml.com.cn/getSupportCity"
    })
    @POST("/WebServices/WeatherWebService.asmx")
    Observable<ResponseEnvelope11> getSupportCity_11_model_2(@Body RequestEnvelope11 requestEnvelope11);
}
2.2.2燕耿、所有RequestBody相關的類中符,這里面一層層東西請參考最上面的報文姜胖,當然代碼注釋里也有誉帅,所有的root,element,namespace需要對應上哦~~

(1)、最外層envelopse

/**
 * Created by wujn on 2018/5/27.
 * Version : v1.0
 * Function: whether webservice request envelope
 *
 <?xml version="1.0" encoding="utf-8"?>
 <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
 <getSupportCity xmlns="http://WebXml.com.cn/">
 <byProvinceName>string</byProvinceName>
 </getSupportCity>
 </soap:Body>
 </soap:Envelope>
 */

//Soap 1.1
//request的根目錄標簽
@Root(name = "soap:Envelope" , strict = false)
//Soap 1.1 根標簽的namespace
@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 RequestEnvelope11 {
    //第一級子標簽body
    @Element(name = "soap:Body", required = false)
    private RequestBody11 requestBody11;

    public RequestBody11 getRequestBody11() {
        return requestBody11;
    }
    public void setRequestBody11(RequestBody11 requestBody11) {
        this.requestBody11 = requestBody11;
    }
}

(2)右莱、envelopse內(nèi)的body層

/**
 * Created by wujn on 2018/5/27.
 * Version : v1.0
 * Function: whether webservice request body
 *
 <soap:Body>
 <getSupportCity xmlns="http://WebXml.com.cn/">
 <byProvinceName>string</byProvinceName>
 </getSupportCity>
 </soap:Body>
 */

@Root(name = "soap:Body", strict = false)
public class RequestBody11 {
    @Element(name = "getSupportCity", required = false)
    private RequestSupportCityBean requestSupportCityBean;

    public RequestSupportCityBean getRequestSupportCityBean() {
        return requestSupportCityBean;
    }

    public void setRequestSupportCityBean(RequestSupportCityBean requestSupportCityBean) {
        this.requestSupportCityBean = requestSupportCityBean;
    }
}

(3)蚜锨、body內(nèi)的請求方法getSupportCity,還有方法內(nèi)的參數(shù)byProvinceName

/**
 * Created by wujn on 2018/5/27.
 * Version : v1.0
 * Function: whether webservice request method
 *
 <getSupportCity xmlns="http://WebXml.com.cn/">
 <byProvinceName>string</byProvinceName>
 </getSupportCity>
 */

@Root(name = "getSupportCity", strict = false)
@Namespace(reference = "http://WebXml.com.cn/")
public class RequestSupportCityBean {
    @Element(name = "byProvinceName" , required = false)
    private String byProvinceName;

    public String getByProvinceName() {
        return byProvinceName;
    }

    public void setByProvinceName(String byProvinceName) {
        this.byProvinceName = byProvinceName;
    }
}
2.2.3慢蜓、所有ResponseBody相關的類亚再,這里面一層層東西請參考最上面的報文,當然代碼注釋里也有晨抡,所有的root,element,namespace需要對應上哦~~
注意:坑氛悬,這里的Body層则剃,用的是name="Body"不是name="soap:Body",否則結果中的body=null如捅,不知道為什么棍现,有大神能解釋下么,為什么不按照報文來~~~

(1)镜遣、最外層envelopse :@Element(name = "Body", required = false)

/**
 * Created by wujn on 2018/5/27.
 * Version : v1.0
 * Function: whether webservice response envelope
 *
 <?xml version="1.0" encoding="utf-8"?>
 <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
 <getSupportCityResponse xmlns="http://WebXml.com.cn/">
 <getSupportCityResult>
 <string>string</string>
 <string>string</string>
 </getSupportCityResult>
 </getSupportCityResponse>
 </soap:Body>
 </soap:Envelope>
 */

//Soap 1.1
//request的根目錄標簽
@Root(name = "soap:Envelope" , strict = false)
//Soap 1.1 根標簽的namespace
@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 ResponseEnvelope11 {
    //第一級子標簽body
    //************** this is Body , not soap:Body **************
    @Element(name = "Body", required = false) 
    public ResponseBody11 responseBody11;

    public ResponseBody11 getResponseBody11() {
        return responseBody11;
    }
    public void setResponseBody11(ResponseBody11 responseBody11) {
        this.responseBody11 = responseBody11;
    }

}

(2)己肮、envelopse內(nèi)的body層:@Root(name = "Body", strict = false) //this is Body , not soap:Body

/**
 * Created by wujn on 2018/5/27.
 * Version : v1.0
 * Function: whether webservice response body
 *
 <soap:Body>
 <getSupportCityResponse xmlns="http://WebXml.com.cn/">
 <getSupportCityResult>
 <string>string</string>
 <string>string</string>
 </getSupportCityResult>
 </getSupportCityResponse>
 </soap:Body>
 */

@Root(name = "Body", strict = false) //this is Body , not soap:Body
public class ResponseBody11 {
    @Element(name = "getSupportCityResponse", required = false)
    public ResponseSupportCityBean responseSupportCityBean;

    public ResponseSupportCityBean getResponseSupportCityBean() {
        return responseSupportCityBean;
    }

    public void setResponseSupportCityBean(ResponseSupportCityBean responseSupportCityBean) {
        this.responseSupportCityBean = responseSupportCityBean;
    }
}

(3)、body下具體的response

/**
 * Created by wujn on 2018/5/27.
 * Version : v1.0
 * Function: whether webservice response result
 *
 <getSupportCityResponse xmlns="http://WebXml.com.cn/">
 <getSupportCityResult>
 <string>string</string>
 <string>string</string>
 </getSupportCityResult>
 </getSupportCityResponse>
 */

@Root(name = "getSupportCityResponse" )
@Namespace(reference = "http://WebXml.com.cn/")
public class ResponseSupportCityBean {
//    @Attribute(name = "xmlns", empty = "http://WebXml.com.cn/", required = false)
//    public String nameSpace;

    @Element(name="getSupportCityResult" )
    public ResponseCityBean cityBeen;

    public ResponseCityBean getCityBeen() {
        return cityBeen;
    }

    public void setCityBeen(ResponseCityBean cityBeen) {
        this.cityBeen = cityBeen;
    }
}

(4)悲关、response下的結果集谎僻,還比較簡單,就一個element下面多組數(shù)據(jù)

/**
 * Created by wujn on 2018/5/27.
 * Version : v1.0
 * Function: whether webservice response result detail...
 *
 <getSupportCityResult>
 <string>string</string>
 <string>string</string>
 </getSupportCityResult>
 */

@Root(name = "getSupportCityResult" )
public class ResponseCityBean {
    @ElementList(name = "string" , inline = true)
    public List<String> city;

    public List<String> getCity() {
        return city;
    }

    public void setCity(List<String> city) {
        this.city = city;
    }
}
2.2.4寓辱、具體訪問
/**
     * soap1.1:封裝的bean的requestbody 和 responsebody
     *
     * */
    public void testModelSoap11(View v){
        //webservice的 request 請求參數(shù):一層層的
        RequestSupportCityBean requestSupportCityBean = new RequestSupportCityBean();
        requestSupportCityBean.setByProvinceName("浙江");
        RequestBody11 requestBody11 = new RequestBody11();
        requestBody11.setRequestSupportCityBean(requestSupportCityBean);;
        RequestEnvelope11 requestEnvelope11 = new RequestEnvelope11();
        requestEnvelope11.setRequestBody11(requestBody11);


        addRxDestroy(RetrofitSoapClient.getInstance().service
                .getSupportCity_11_model(requestEnvelope11) //its body
                .compose(RxSchedulers.<ResponseEnvelope11>io_main())
                .subscribeWith(new DisposableObserver<ResponseEnvelope11>() {

                    @Override
                    public void onNext(ResponseEnvelope11 responseEnvelope11) {
                        LogUtil.d("testModelSoap11 : response callback");

                         //封裝的請求bean艘绍,返回的響應也是成功的,有數(shù)據(jù)
                         //model data : ResponseBody callback success
                        if(responseEnvelope11 == null){
                            LogUtil.e("testModelSoap11 : ResponseEnvelope11 Null");
                            return;
                        }

                        ResponseBody11 responseBody11 = responseEnvelope11.getResponseBody11();
                        if(responseBody11 == null){
                            LogUtil.e("testModelSoap11 : ResponseBody11 Null");
                            return;
                        }

                        ResponseSupportCityBean responseSupportCityBean = responseBody11.getResponseSupportCityBean();
                        if(responseSupportCityBean == null){
                            LogUtil.e("testModelSoap11 : ResponseSupportCityBean Null");
                            return;
                        }

                        ResponseCityBean citybean = responseSupportCityBean.getCityBeen();
                        if(citybean == null){
                            LogUtil.e("testModelSoap11 : citybean Null");
                            return;
                        }

                        List<String> citys = citybean.getCity();


                        StringBuilder sb = new StringBuilder();
                        for (String c : citys){
                            sb.append(c+"秫筏、 ");
                        }
                        LogUtil.d("testModelSoap11 : webservice citys = \n"+sb.toString());
                        tv_response_result.setText(mode+"\n"+sb.toString());
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        LogUtil.e("testModelSoap11 : ex="+e.getMessage());
                    }
                    @Override
                    public void onComplete() {}
                }));
    }

以上就是對用retrofit訪問webservice的一點感悟鞍盗,還沒有考慮繼續(xù)封裝。跳昼。

----------------------------更新 2018/5/31-----------------------------------------

3般甲、對固定響應數(shù)據(jù)的格式小小優(yōu)化

3.1、響應數(shù)據(jù):

顯然status,description,tableUpdateTime是固定格式鹅颊,updateData里面是CDATA的數(shù)據(jù)敷存,先不理他...

 <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <instrumentDictionaryResponse xmlns="http://www.zhiyunda.com/zydjcy" xmlns:ns2="http://www.zhiyunda.com/service/instrumentDockingService">
            <status>1</status>
            <description>成功</description>
            <tableUpdateTime>data_dictionary:2018-05-25 11:19:52;checked_unit:2016-09-18 06:32:52;standard_limit:2016-08-15 10:27:48;</tableUpdateTime>
            <updateData><![CDATA[<updatedata><table><name>data_dictionary</name><field>id, codeid, name, pid, remark, inputdate, modifydate, status, type_num</field><values><value>302|302|亞硝酸鹽|1|檢測項目|2016-08-24
 ..............一堆數(shù)據(jù)的省略.........
 10:58:51.0|null|C|null</value></values></table>-200<table><name>standard_limit</name><field>id, inputdate, modifydate, decision_basis, max_limit, min_limit, test_basis, unit, food_type, test_item</field><values></values></table></updatedata>]]>
            </updateData>
        </instrumentDictionaryResponse>
    </S:Body>
 </S:Envelope>
3.2、響應的bean類
3.2.1堪伍、響應的最外層bean:Envelope
//Soap 1.1
//request的根目錄標簽
@Root(name = "S:Envelope" , strict = false)
//Soap 1.1 根標簽的namespace
@NamespaceList({
        @Namespace(reference = "http://schemas.xmlsoap.org/soap/envelope/", prefix = "S")
})
public class ZydResponseDictionaryEnvelope {

    @Path("S:Body") //跳過body
    @Element(name = "instrumentDictionaryResponse", required = false)
    private ZydResponseDictionary zydResponseDictionary;

    public ZydResponseDictionary getZydResponseDictionary() {
        return zydResponseDictionary;
    }

    public void setZydResponseDictionary(ZydResponseDictionary zydResponseDictionary) {
        this.zydResponseDictionary = zydResponseDictionary;
    }
}
3.2.2锚烦、body下的具體返回數(shù)據(jù)的bean,此處還可以繼續(xù)優(yōu)化:@Element(name = "updateData", required = false) private String updateData; 這個可以用泛型T帝雇,暫時不用了就算是獲取CDATA的string值好了涮俄,因為轉換xml的string也可以之后用泛型T來做
@Root(name = "instrumentDictionaryResponse", strict = false)
@NamespaceList({
        @Namespace(reference = "http://www.zhiyunda.com/zydjcy"),
        @Namespace(reference = "http://www.zhiyunda.com/service/instrumentDockingService", prefix = "ns2")
})
public class ZydResponseDictionary {
    //狀態(tài)
    @Element(name = "status", required = false)
    private String status;

    //描述
    @Element(name = "description", required = false)
    private String description;

    //更新時間
    @Element(name = "tableUpdateTime", required = false)
    private String tableUpdateTime;

    //更新數(shù)據(jù)  -->  這個可以用泛型T,暫時不用了就算是獲取CDATA的string值好了
    @Element(name = "updateData", required = false)
    private String updateData;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getTableUpdateTime() {
        return tableUpdateTime;
    }

    public void setTableUpdateTime(String tableUpdateTime) {
        this.tableUpdateTime = tableUpdateTime;
    }

    public String getUpdateData() {
        return updateData;
    }

    public void setUpdateData(String updateData) {
        this.updateData = updateData;
    }

   
}
3.3尸闸、API接口
        @Headers({
            "Content-Type:text/xml; charset=utf-8",
            "SOAPAction:\"\""
    })
    @POST(ZYDApiConfig.POST_WSDL)
    Observable<ZydResponseDictionaryEnvelope> instrumentDictionaryHandle(@Body String s);
3.4彻亲、CallBack:請求的返回值略優(yōu)化下,不管是訪問失敗吮廉,或者訪問成功苞尝,數(shù)據(jù)獲取失敗都并到一起處理了,返回就是--》成功+有效數(shù)據(jù)宦芦,失敗+提示語句
public abstract class ZydResponseDictionaryCallback extends DisposableObserver<ZydResponseDictionaryEnvelope> {

    @Override
    public void onNext(ZydResponseDictionaryEnvelope zydResponseDictionaryEnvelope) {
        if(zydResponseDictionaryEnvelope == null){
            onFailed("接口數(shù)據(jù)為空");
            return;
        }
        ZydResponseDictionary dictionary = zydResponseDictionaryEnvelope.getZydResponseDictionary();
        if (dictionary == null){
            onFailed("接口數(shù)據(jù)為空");
            return;
        }

        if(dictionary.getStatus().equals("1")){
            onSuccess(dictionary.getTableUpdateTime() , dictionary.getUpdateData());
        }else{
            onFailed(dictionary.getDescription());
        }

    }

    @Override
    public void onError(Throwable e) {
        onFailed(ApiException.handleApiExMsg(e)); //就是http code處理
    }
    @Override
    public void onComplete() { }

    public abstract void onSuccess(String tableDate,String updateData);
    public void onFailed(String msg) {

    }
}
3.5宙址、具體請求
String requestBodyStr = ZYDApiNode.getRequestString2InstrumentDictionaryHandle(instance ,
                                                                ZYDSpOper.getTableDate(instance));

        addRxDestroy(RetrofitSoapClient.getInstance().service
                .instrumentDictionaryHandle(requestBodyStr) //its body
                .compose(RxSchedulers.<ZydResponseDictionaryEnvelope>io_main())
                .subscribeWith(new ZydResponseDictionaryCallback() {
                    @Override
                    public void onSuccess(String tableDate, String updateData) {
                      //對CDATA數(shù)據(jù)做處理,這個單獨拉開來講
                      //后續(xù)的業(yè)務需求
                    }

                    @Override
                    public void onFailed(String msg) {
                        DialogUtil.errorDialog(instance,msg);
                    }
                }));
3.6调卑、CDATA的xml數(shù)據(jù)處理抡砂,請看下一篇文章:Android XStream 解析xml數(shù)據(jù)變成bean大咱,支持CDATA

留下疑問,啥年代了為啥還有webservice注益,他有啥好的徽级??

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末聊浅,一起剝皮案震驚了整個濱河市餐抢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌低匙,老刑警劉巖旷痕,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異顽冶,居然都是意外死亡欺抗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門强重,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绞呈,“玉大人,你說我怎么就攤上這事间景〉枭” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵倘要,是天一觀的道長圾亏。 經(jīng)常有香客問我,道長封拧,這世上最難降的妖魔是什么志鹃? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮泽西,結果婚禮上曹铃,老公的妹妹穿的比我還像新娘。我一直安慰自己捧杉,他們只是感情好陕见,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糠溜,像睡著了一般淳玩。 火紅的嫁衣襯著肌膚如雪直撤。 梳的紋絲不亂的頭發(fā)上非竿,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音谋竖,去河邊找鬼红柱。 笑死承匣,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的锤悄。 我是一名探鬼主播韧骗,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼零聚!你這毒婦竟也來了袍暴?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤隶症,失蹤者是張志新(化名)和其女友劉穎政模,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚂会,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡淋样,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了胁住。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趁猴。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖彪见,靈堂內(nèi)的尸體忽然破棺而出儡司,到底是詐尸還是另有隱情,我是刑警寧澤余指,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布枫慷,位于F島的核電站,受9級特大地震影響浪规,放射性物質發(fā)生泄漏或听。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一笋婿、第九天 我趴在偏房一處隱蔽的房頂上張望誉裆。 院中可真熱鬧,春花似錦缸濒、人聲如沸足丢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斩跌。三九已至,卻和暖如春捞慌,著一層夾襖步出監(jiān)牢的瞬間耀鸦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留袖订,地道東北人氮帐。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像洛姑,于是被迫代替她去往敵國和親上沐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 背景 沒啥背景,實在是受夠了ksoap2這個jar包,而公司服務端是基于c#語言的.net開發(fā),不懂他們的技術,而...
    王明超Honor閱讀 5,574評論 30 19
  • WebService介紹 首先我們來談一下為什么需要學習webService這樣的一個技術吧.... 問題一 如果...
    Java3y閱讀 9,561評論 5 139
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理楞艾,服務發(fā)現(xiàn)参咙,斷路器,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • 在開往外地的長途車上 我無意間看到一個女人的臉 眼睛里充滿痛苦硫眯,眼淚 像水一樣不停地流下 奇怪的是 滿車都沒有聽到...
    雪十一月閱讀 240評論 0 5
  • 今天加班昂勒,但還是把一直想做的表情包畫完了~~還是有白邊,要繼續(xù)處理舟铜!
    wendyy閱讀 268評論 0 0