Retrofit & WebService

1,983 阅读3分钟
原文链接: blog.csdn.net

1. 前言

最近工作中需要使用到WebService接口,个人比较喜欢Restful的接口风格,对WebService不是很了解。

Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是:通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。

而对于我们移动开发人员而言,它就是一种数据交互的通道。我们需要了解他的请求结构体和响应结构体。

2. WebService调试工具SoapUI

SoapUI是一个开源测试工具,通过soap/http来检查、调用、实现Web Service的功能/负载/符合性测试。该工具既可作为一个单独的测试软件使用,也可利用插件集成到Eclipse,maven2.X,Netbeans 和intellij中使用。SoapUI Pro是SoapUI的商业非开源版本,实现的功能较开源的SoapUI更多。
(找不到资源的可以在文章下方留言)
这里写图片描述

3. 接口分析(以getMobileCodeInfo为例)

ws.webxml.com.cn/WebServices… 为测试例子

这里写图片描述
这里写图片描述

从上面两个图可以看到我们得请求体和响应体的结构和内容,以XML格式作为数据交互的结构类型。

4. 程序设计

4.1 添加依赖

    implementation 'com.squareup.okhttp3:okhttp:3.8.0'
    implementation 'com.parkingwang:okhttp3-loginterceptor:0.5'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    implementation('com.squareup.retrofit2:converter-simplexml:2.3.0') {
        exclude module: 'stax'
        exclude module: 'stax-api'
        exclude module: 'xpp3'
    }

4.2 请求体设计

从请求体XML结构而言

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://WebXml.com.cn/">
   <soap:Header/>
   <soap:Body>
      <web:getMobileCodeInfo>
         <!--Optional:-->

         <!--Optional:-->
         <web:mobileCode>18507152743</web:mobileCode>
      </web:getMobileCodeInfo>
   </soap:Body>
</soap:Envelope>

最外层soap:Envelope
其次soap:Body
最后web:getMobileCodeInfo,而web:getMobileCodeInfo中有一个mobileCode我们可以用变量表示,所以创建如下三个类:
MobileCodeRequestEnvelope.java

@Root(name = "soap:Envelope")
@NamespaceList({
        @Namespace(prefix = "xsi", reference = "http://www.w3.org/2001/XMLSchema-instance"),
        @Namespace(prefix = "xsd", reference = "http://www.w3.org/2001/XMLSchema"),
        @Namespace(prefix = "soap", reference = "http://www.w3.org/2003/05/soap-envelope")
})
public class MobileCodeRequestEnvelope {

    @Element(name = "soap:Body", required = false)
    private MobileCodeRequestBody body;

    public MobileCodeRequestBody getBody() {
        return body;
    }

    public void setBody(MobileCodeRequestBody body) {
        this.body = body;
    }
}

MobileCodeRequestBody.java

@Root(name = "soap:Body", strict = false)
public class MobileCodeRequestBody {
    @Element(name = "getMobileCodeInfo", required = false)
    private MobileCodeRequestData mMobileCodeRequestData;

    public MobileCodeRequestData getMobileCodeRequestData() {
        return mMobileCodeRequestData;
    }

    public void setMobileCodeRequestData(
            MobileCodeRequestData mobileCodeRequestData) {
        mMobileCodeRequestData = mobileCodeRequestData;
    }
}

MobileCodeRequestData.java

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

    public String getMobileCode() {
        return mobileCode;
    }

    public void setMobileCode(String mobileCode) {
        this.mobileCode = mobileCode;
    }
}

4.3 响应体设计

从响应体XML而言

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <getMobileCodeInfoResponse xmlns="http://WebXml.com.cn/">
         <getMobileCodeInfoResult>18507152743:湖北 武汉 湖北联通GSM卡</getMobileCodeInfoResult>
      </getMobileCodeInfoResponse>
   </soap:Body>
</soap:Envelope>

最外层soap:Envelope
其次soap:Body
然后getMobileCodeInfoResponse,最后getMobileCodeInfoResult,我们可以用变量表示,所以创建如下三个类:

MobileCodeResponseEnvelope.java

@Root(name = "soap:Envelope")
@NamespaceList({
        @Namespace( prefix = "xsi", reference = "http://www.w3.org/2001/XMLSchema-instance"),
        @Namespace( prefix = "xsd", reference = "http://www.w3.org/2001/XMLSchema"),
        @Namespace( prefix = "soap", reference = "http://www.w3.org/2003/05/soap-envelope")
})
public class MobileCodeResponseEnvelope {
    @Element(name = "Body", required = false)
    private MobileCodeResponseBody mMobildCodeResponseBody;

    public MobileCodeResponseBody getMobildCodeResponseBody() {
        return mMobildCodeResponseBody;
    }

    public void setMobildCodeResponseBody(
            MobileCodeResponseBody mobildCodeResponseBody) {
        mMobildCodeResponseBody = mobildCodeResponseBody;
    }
}

MobileCodeResponseBody.java

@Root(name = "Body")
public class MobileCodeResponseBody {
    public MobileCodeResponseInfo getMobileCodeResponseInfo() {
        return mMobileCodeResponseInfo;
    }

    public void setMobileCodeResponseInfo(
            MobileCodeResponseInfo mobileCodeResponseInfo) {
        mMobileCodeResponseInfo = mobileCodeResponseInfo;
    }

    @Element(name = "getMobileCodeInfoResponse", required = false)
    private MobileCodeResponseInfo mMobileCodeResponseInfo;
}

MobileCodeResponseInfo.java

@Root(name = "getMobileCodeInfoResponse",strict = false)
public class MobileCodeResponseInfo {

    public String getMobileCodeResult() {
        return MobileCodeResult;
    }

    public void setMobileCodeResult(String mobileCodeResult) {
        MobileCodeResult = mobileCodeResult;
    }

    @Element(name = "getMobileCodeInfoResult", required = false)
    private String MobileCodeResult;
}

4.4 接口设计

public interface mobileCodeApi {
    @Headers({
            "Content-Type: text/xml",
            "Accept-Charset: utf-8"
    })
    @POST("MobileCodeWS.asmx")
    Call<MobileCodeResponseEnvelope> getMobileCodeInfo(
            @Body MobileCodeRequestEnvelope requestEnvelope);
}

4.5 Retrofit创建

public class Retrofitance {
    private static Strategy strategy = new AnnotationStrategy();
    private static Serializer serializer = new Persister(strategy);

    private static OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();

    private static Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
            .addConverterFactory(SimpleXmlConverterFactory.create(serializer))
            .baseUrl(Constant.BASE_URL);


    public static <T> T createMobileCodeService(Class<T> serviceClass) {
        okHttpClient.interceptors().add(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
                Request original = chain.request();

                Request.Builder requestBuilder = original.newBuilder()
                        .header("Content-Type", "text/xml;charset=UTF-8")
                        .method(original.method(), original.body());

                Request request = requestBuilder.build();
                return chain.proceed(request);
            }
        });

        OkHttpClient client = okHttpClient.connectTimeout(1, TimeUnit.MINUTES)
                .addInterceptor(new LogInterceptor())
                .writeTimeout(1, TimeUnit.MINUTES)
                .readTimeout(1, TimeUnit.MINUTES)
                .build();
        Retrofit retrofit = retrofitBuilder.client(client).build();
        return retrofit.create(serviceClass);
    }
}

4.6 请求数据

        mobileCodeApi apiService = Retrofitance.createMobileCodeService(mobileCodeApi.class);
        MobileCodeRequestEnvelope requestEnvelope = new MobileCodeRequestEnvelope();
        MobileCodeRequestBody requestBody = new MobileCodeRequestBody();
        MobileCodeRequestData requestData = new MobileCodeRequestData();

        requestData.setMobileCode("18507152743");
        requestBody.setMobileCodeRequestData(requestData);
        requestEnvelope.setBody(requestBody);

        Call<MobileCodeResponseEnvelope> call = apiService.getMobileCodeInfo(requestEnvelope);
        call.enqueue(new Callback<MobileCodeResponseEnvelope>() {
            @Override
            public void onResponse(Call<MobileCodeResponseEnvelope> call,
                    Response<MobileCodeResponseEnvelope> response) {
                MobileCodeResponseEnvelope mobileCodeResponseEnvelope = response.body();
                if (mobileCodeResponseEnvelope != null) {
                    Toast.makeText(MainActivity.this, "请求成功", Toast.LENGTH_SHORT).show();
                    String result =
                            mobileCodeResponseEnvelope.getMobildCodeResponseBody()
                                    .getMobileCodeResponseInfo().getMobileCodeResult();
                    mTvMobileResult.setText(result);
                    System.err.println("yidong -- result = " + result);
                }
            }

            @Override
            public void onFailure(Call<MobileCodeResponseEnvelope> call, Throwable t) {
                System.err.println("yidong -- onFailure");
                Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
            }
        });

4.7 效果

这里写图片描述

5. 源码地址

RetrofitWebService