Retrofit 用Soap协议访问WebService 详解

简介: 参考1、结合Retrofit使用post请求访问WebService2、retrofit2调用webservice-2.基本实现前言1、首先不要把这个想的太复杂,它就是使用【soap】协议的请求,数据格式都是【xml】,基础还是http的post请求,但是它的规范显然更多一些,总体逃不过【Request和Response】。

参考

1、结合Retrofit使用post请求访问WebService
2、retrofit2调用webservice-2.基本实现

前言

1、首先不要把这个想的太复杂,它就是使用【soap】协议的请求,数据格式都是【xml】,基础还是http的post请求,但是它的规范显然更多一些,总体逃不过【Request和Response】。
2、以下所有的范例都是使用 【 WeatherWebService 】 这个网站,它提供了【Soap1.1 和 Soap1.2 】的请求范例,有【Request和Response】报文可看,这样更好理解规范和格式

一、WebService 基础与注意点(第一次用的话稍微看看)

有soap1.1,soap1.2的区别,请求的header不同,xml的内容也略有不同啦~~
跳转阅读》》》【 WebService 基础知识点和用Postman调试】,复制了部分内容过来

Soap1.1:

1、xmlns后基本都是namespace,比如envelopse标签有三个namespace,getSupportCity这个方法名有一个namespace
2、区分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协议
  <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、区分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协议
  <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数据
        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数据类型 bean-<xml
                .addConverterFactory(GsonConverterFactory.create())         //添加 json数据类型 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、从简单的开始,能访问上有数据返回就不错了。

2.1、简单的soap1.1和1.2的访问

2.1.1、接口类

1、RequestBody和ResponseBody的基本参数不用说
2、根据网站提供的范例,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协议格式,然后一种报错,说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 请求入参:" + 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 请求入参:" + str);
        return str;
    }


}

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

2.2、用bean的方式会不会好一点,继续哦

就是把数据封装到bean里面,看的舒服一点,符合以前用json,resetful风格的那些请求

2.2.1、接口类:RequestEnvelope11 和ResponseEnvelope11需要看一下
public interface SoapApiService {
    //-----------------------------继续封装-------------------------------------
    //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内的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内的请求方法getSupportCity,还有方法内的参数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内的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下面多组数据

/**
 * 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 请求参数:一层层的
        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,返回的响应也是成功的,有数据
                         //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的一点感悟,还没有考虑继续封装。。

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

3、对固定响应数据的格式小小优化

3.1、响应数据:

显然status,description,tableUpdateTime是固定格式,updateData里面是CDATA的数据,先不理他...

 <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
 ..............一堆数据的省略.........
 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下的具体返回数据的bean,此处还可以继续优化:@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 {
    //状态
    @Element(name = "status", required = false)
    private String status;

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

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

    //更新数据  -->  这个可以用泛型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:请求的返回值略优化下,不管是访问失败,或者访问成功,数据获取失败都并到一起处理了,返回就是--》成功+有效数据,失败+提示语句
public abstract class ZydResponseDictionaryCallback extends DisposableObserver<ZydResponseDictionaryEnvelope> {

    @Override
    public void onNext(ZydResponseDictionaryEnvelope zydResponseDictionaryEnvelope) {
        if(zydResponseDictionaryEnvelope == null){
            onFailed("接口数据为空");
            return;
        }
        ZydResponseDictionary dictionary = zydResponseDictionaryEnvelope.getZydResponseDictionary();
        if (dictionary == null){
            onFailed("接口数据为空");
            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数据做处理,这个单独拉开来讲
                      //后续的业务需求
                    }

                    @Override
                    public void onFailed(String msg) {
                        DialogUtil.errorDialog(instance,msg);
                    }
                }));
3.6、CDATA的xml数据处理,请看下一篇文章:Android XStream 解析xml数据变成bean,支持CDATA

留下疑问,啥年代了为啥还有webservice,他有啥好的??

目录
相关文章
|
5月前
|
API 数据库 网络架构
REST WebService与SOAP WebService的比较
REST WebService与SOAP WebService的比较
|
网络安全 网络架构
https请求SOAP webService接口
https请求SOAP webService接口
115 0
|
JSON 移动开发 网络协议
Web | 什么是 RPC 消息协议 ?
Web | 什么是 RPC 消息协议 ?
177 0
|
存储 缓存 JSON
【JavaEE】HTTP应用层协议
是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而 [9] 消息内容则具有一个类似MIME的格式。
100 1
|
XML 缓存 JSON
REST vs SOAP:两种 Web 服务协议的分析
REST(Representational State Transfer)和 SOAP(Simple Object Access Protocol)都是 Web 服务架构的两种主要风格。两者都提供了一种通信方式,可以让不同的应用程序通过网络互相交换数据。但是,它们之间有一些重要的区别。
|
XML JSON 编解码
http使用restful代理soap
作为建立在http协议之上的数据协议,soap定义了数据报文的格式与规范与应用程序的调用方式(RPC模式),隐藏了网络传输的细节,这里采用restful的风格来请求webservice服务
363 0
http使用restful代理soap
|
Web App开发 JavaScript 前端开发
|
Java 网络架构
WebService就是这么简单(三)
首先我们来谈一下为什么需要学习webService这样的一个技术吧….
194 0
WebService就是这么简单(三)
|
XML 网络架构 数据格式
webservice快速入门-SOAP和WSDL
webservice快速入门-SOAP和WSDL 什么是SOAP?SOAP:Simple Object Access Protocol SOAP:简单对象访问协议,简单对象访问协议(SOAP)是一种轻量的、简单的、基于 XML 的协议,它被设计成在 WEB 上交换结构化的和固化的信息。
3569 0
|
Java 网络架构
SOAP协议是RPC协议的升级版,出现了WSDL
背景 关于RPC协议的思考 RPC协议的组成部分 RPC协议=服务端+服务注册管理中心+客户端,构成客户端可远程调用服务端的方法,就跟调用本地方法一样方便。 Java实现RPC常用的框架RMI 服务注册管理中心常用的框架是ZooKeePer RPC服务端和客户端独立部署 RPC客户端必须包含服务端的接口类 RPC的限制 1、接口只能靠接口文档传递 2、传输内容的限制 SOAP协议 提供了WSDL标准,只需要访问服务地址,自动生成所有接口说明,方便统一 需要软件,朋友都找我。
969 0