参考
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);
}
}));