Foreword:
Recently, Android uses the Retrofit framework to make network requests, which has become very popular, but online examples or existing request background servers are generally based on the Rest method, that is, the parameters sent when sending the request are generally directly placed in the header or path path, which is a bit more complicated Put the parameters in the form to request. If the background is based on the WebService method, the data format sent is SOAP-type XML data, and everyone generally uses the ksoap framework to request. If a client has two background services, using two network frameworks in the client code is generally not what you want. With the continuous update of the Retrofit framework, it should be the general trend for this framework to make network requests. However, using Retrofit to make Webservice requests, there are too few online resources. After searching for these two days, only two related documents and one demo were found:
Article 1: http://m.blog.csdn.net/article/details?id=51133893 This is a reprint written by a Taiwanese, only fragmentary code, without explaining the data assembly from beginning to end. There is no demo that can be run directly, nor did it clearly explain the different SOAP versions, and the requests are very different;
Article 2: http://m.blog.csdn.net/article/details?id=51163808 This is the author’s own practice, I have to say that it took a lot of effort, but the data assembly is not clear, nor is it shown Demo. And when the author sent the request, he passed the requested model directly as a string, which did not play out retrofit’s SimpleXmlConverterFactory The powerful advantage.
Example: The demo download address is https://github.com/asanchezyu/RetrofitSoapSample, I have to say, this is One can run a complete demo, but this is based on SOAP Version 1.2. For different SOAP versions, the request is still quite different. Moreover, there is no data in the author’s return, and the analysis return data cannot be seen.
Look I want to transfer back to the ksoap camp several times with this piece of information on the Internet. But as a developer, you can’t copy other people’s code all the time. Programmers who don’t use their brains are not good programmers. I was determined to use Retrofit to successfully request Webservice data. After two days of research, I finally paid off and successfully requested the data.
SOAP The Webservice testing tool general is based on the SoapUI tool. After importing the project, this tool can clearly view the methods included in the WebService, the SOAP version, and the request parameters of each method. You can also directly simulate network requests and view the returned results. The specific usage of SoapUI will not be mentioned here. The following is tested with the project http://www.webservicex.net/uszip.asmx?WSDL. The method included in the project is shown on the left, and the request is sent in the middle. xml package, on the right is the xml data returned by the server.
If you have successfully called the function, you can also use the Charles Packet Capture Tool to see the package of the requested data.
This is a screenshot of a successful request for webservice using the retrofit framework
The request body can be clearly viewed through the SoapUI tool, and the implementation will be easier. The following specifically talk about how to use Retrofit to implement SOAP WebService network requests.
Implementation:
1. SOAP version
Different SOAP versions require different namespaces. For details, you can use the SoapUI tool or ask the back-end developers to see the SoapEnvelop source code.
As can be seen from the above figure, the namespaces of 1.0, 1.1, 1.2 versions are somewhat different, This will affect subsequent requests for writing Envelope package encapsulation.
span>
2. Preparatory work, because WebService data request and return are all in xml format, needImport the dependency package parsed by Retrofit xml (the three classes of stax|stax-api|xpp3 need to be excluded, otherwise an error will be reported during compilation)
compile("com.squareup.retrofit2:converter-simplexml:2.0.0 -beta3"){ exclude module: 'stax' < /strong>exclude module: 'stax-api ' exclude module: 'xpp3' strong>}
3. Writing Retrofit request object, including request base address, request header Content-Type is set to text/xml;charset=UTF-8, converter is set toSimpleXmlConverterFactory.
- /**
- * Server Retrofit variable initialization
- * Created by SmileXie on 16/7/16.
- < span class="comment">*/
- public span>classJXHDRetrofitGenerator{
- < /li>
- privatestatic Strategy strategy = newAnnotationStrategy();
- private span>staticSerializerserializer=newPersister( strategy);
- private< /span>static OkHttpClient.Builder okHttpClient=new OkHttpClient.Builder();
- privatestaticRetrofit.BuilderretrofitBuilder=new span>Retrofit.Builder()
- .addConverterFactory(SimpleXmlConverterFactory.create(serializer))
>
- .baseUrl(Const ant.BASE_URL); //Requested webservice base address
- publicstatic
S createService(ClassserviceClass){- okHttpClient.interceptors().add(newInterceptor(){
- @Override /span>
- public okhttp3.Response intercept(Interceptor.Chain chain) span>throws IOException{
- Request original= chain.request();
- Request.Builder requestBuilder=original.newBuilder()
- .header(“Content-Type”,“text/xml;charset=UTF-8”)//Add request header
- .method( original.method(), original.body());
- Request request = requestBuilder .build();
- returnchain.proceed(request);
- < span>
- OkHttpClient client = okHttpClient.connectTimeout(2, TimeUnit.MINUTES)< /span>
- .writeTimeout(2, TimeUnit.MINUTES)< /li>
- .readTimeout(
2 , TimeUnit.MINUTES)- .build();
- Retrofitretrofit=retrofitBuilder.client(client).build();
- return< /span>retrofit.create(serviceClass);
- }
4. Write request function
5. Assembly request Request Model
The main assembly xml data is as follows:
1) Assemble the outermost soapenv:Envelope. The request here involves the namespace. Different SOAP versions are different. The following is the SOAP1.1 version:
< span style="font-size:18px">If your server is SOAP1.2 version, the namespace should be written like this, the prefix can be defined by yourself, but it must correspond to the prefix in @Element.
- / **
- * Created by SmileXie on 16/7/15.
- */
- @Root(name="soapenv:Envelope")
- @NamespaceList({
- < span> @Namespace(reference="http://www.w3.org/2001/XMLSchema-instance ", prefix="xsi"),
- @Namespace(reference="http://www.w3.org /2 001/XMLSchema", prefix="xsd"),
- @Namespace(reference="http://schemas.xmlsoap.org/soap /encoding/", prefix="enc"),
- @Namespace(reference="http://schemas. xmlsoap.org/soap/envelope/", prefix="soapenv")
- })
- publicclass RoleInfoRequestEnvelope{
- @Element(name="soapenv:Body", required=false)
- public RoleInfoRequestBody body;
- @Element (name="soapenv:Header", required=false )
- public String aHeader;< /span>
- }
< pre style="font-family:Menlo; background-color:rgb(255,255,255)">
- @Root(name=" soap12:Envelope")
- @NamespaceList({ < /span>
- @Namespace(prefix="xsi", reference="http://www.w3.org/2001/XMLSchema-instance" ),
- @Namespace(prefix="xsd", reference="http://www.w3.org/2001/XMLSchema"), li>
- @Namespace(prefix="soap12" span>, reference="http://www.w3.org/2003/05/soap-envelope")
- })
2)Assemble the outermostBody part:< /span>< /span>
- / **
- * User role returns to body
- * Created by SmileXie on 16/7/15.
- */
- @Root (name="soapenv:Body", strict=false )
- publicclass span> RoleInfoRequestBody{
- @Element(name= "getroleinfo", required=false)
- publicUserInfoBaseRequestgetroleinfo;
- }
3) Assemble the getrolinfo part:
- /**
- * User information
- * Created by SmileXie on 16/7/15.< /span>
- */
- publicclassUserInfoBaseRequest{< /span>
- @Element( name="token", required=false)) span>
- public String token; li>
- @Element(name="userId")
- public String userid;
- @Element(name="userType")
- publicString userType;
- span>
- public String getToken(){
- returntoken;
- span>
- }
So far, the Request part is assembled. All request variables can be written as private, and then assigned with the setter method. Because there is no data modification involved, the author uses all public.
< pre style="font-family:Menlo; background-color:rgb(255,255,255)">
6. Write request Response Model
If you don’t know the format of the returned data in advance, you can skip writing this part first, and use ResponseBody to receive the returned data directly. Use the packet capture tool to check the Response part to get the returned result of the data, and then write it.
< /pre>The received data format is the same as that of the Request Model, which is parsed layer by layer . Retrofit uses SAX parsing by default, so every label needs to be parsed, or it will not report an error.
< pre style="font-family:Menlo; background-color:rgb(255,255,255)">1) parse the outermost soapevn:Envelope
< li class="alt">/**
- * User role Return to general information
- * Created by SmileXie on 16/7/15.< /span>
- */
- @Root(na me="soapenv:Envelope")
- @NamespaceList({
- @Namespace(reference="http://www.w3.org/2001/XMLSchema-instance", prefix= "xsi"),
- @Namespace span>(reference="http://www.w3.org/2001/XMLSchema", prefix=< span class="string">"xsd"),
- @Namespace(reference="http://schemas.xmlsoap.org/soap/encoding/",prefix= "enc"),
- @Namespace(reference="http://schemas.xmlsoap.org/soap/envelope/" ,Prefix="soapenv")
- } )
- publicclass RoleInfoResponseEnvelope{
- @Element(name= "Body")
- public RoleInfoResponseBody body;
- } li>
2) Parse soapenv:Body part
- /**
- * User role returns to body
- * Created by SmileXie on 16/7/15.
- */
- @Root(name="Body")
- publicclassRoleInfoResponseBody{< /span>
- < /li>
- @Element(name="getroleinfoResponse", required=false)
- public RoleInfoResponse roleInfoResponse;
- }
3)Analysis
span>getroleinfoResponsepart
- /**
- * User role return< /li>
- * Created by SmileXie on 16/7/15.
- */
- < li>@Root(name="getroleinfoResponse") span>
- @NamespaceList({ li>
- @Namespace(reference = "http://www.w3.org /2001/XMLSchema-instance", prefix = "xsi"< /span>),
- @Namespace(reference = "http://www.w3.org/2001/XMLSchema", prefix = "xsd"),
- @Namespace(reference = "http://schemas.xmlsoap.org/soap/encoding/", prefix = "enc"),
- @Namespace(reference = "http://schemas.xmlsoap.org/soap/envelope", prefix = "env"),
- @Namespace(reference = "http://schemas.xmlsoap.org/soap/encoding/", prefix = "encodingStyle"),
- })
- public class RoleInfoResponse {
- @Attribute(name = "encodingStyle")
- public String encodingStyle;
- @Element(name = "getroleinfoReturn")
- public RoleInfoResponseReturn reolInfo;
- }
4)解析最里一层,getroleinfoReturn部分最里边的数据其实是String型,直接用@Text注解获取,我们这里返回的是一个json,最后转用Gson来解析的。
- /**
- * 用户角色返回
- * Created by SmileXie on 16/7/18.
- */
- @Root(name = "getroleinfoReturn")
- @Namespace(reference = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")
- public class RoleInfoResponseReturn {
- @Attribute(name = "type")
- public String xsiType;
@Text ()- public String message;
- }
7. 编写请求代码
- private void testSOAP() {
- JXHDInterfaceFun apiService = JXHDRetrofitGenerator.createService(JXHDInterfaceFun.class);
- RoleInfoRequestEnvelope requestEnvelope = new RoleInfoRequestEnvelope(); //soapenv:Envelope
- RoleInfoRequestBody requestBody = new RoleInfoRequestBody(); // body
- UserInfoBaseRequest baseRequest = new UserInfoBaseRequest(); // getroleinfo
- baseRequest.userid = "liliting";
- baseRequest.userType = "2";
- requestBody.getroleinfo = baseRequest;
- request Envelope.body = requestBody;
- Call
call = apiService.getRoleInfo(requestEnvelope); - call.enqueue(new Callback
() { - @Override
- public void onResponse(Response
response) { - Util.stopProgressDialog();
- RoleInfoResponseEnvelope roleInfoResponseEnvelope = response.body();
- if (roleInfoResponseEnvelope != null ) {
- String message = roleInfoResponseEnvelope.body.roleInfoResponse.reolInfo.message;
- BaseResponse baseResponse = GsonUtil.getJsonObject(message, BaseResponse.class);
- if(baseResponse != null) {
- RoleInfoResponse roleResponse = GsonUtil.getJsonObject(baseResponse.getMessage(), RoleInfoResponse.class);
- String roleType = roleResponse.getRoles();
- }
}- }
- @Override
- public void onFailure(Throwable t) {
- Util.stopProgressDialog();
- Toast.makeText(SendMessageActivity.this, getString(R.string.load_fail), Toast.LENGTH_SHORT).show();
- }
- });
- }
采用Retrofit进行WebServi ce请求,上面代码完整显示了请求数据的封装,返回数据的解析,请求函数的编写,Retrofit对象组装,请求代码等。稍候我会把在项目实施中遇到的一些问题进行总结,并把相应代码整理成demo,供大家参考。
后记:
两种框架对比:
用Retrofit进行WebService请求,在组装请求数据时,需要进行Envelop,Body,RequestMode的组装,至少要用到3个类;
在解析返回的XML数据时,也要进行Envelop,Body,ResponseModel的解析,至少需要用3个类。
这样Retrofit框架比ksoap框架进行WebService请求,类变多了,但并没有变麻烦。这样写使整个请示都清晰了,开发者可以清楚看到数据的组装。
用ksoap请求,请求头公共的,可以写在一起,请求的对象只需要通过HashMap传值过去,ksoap会相应的组装body部分;
返回的对象解析只需要用到一个类,比WebService编写简单。
但ksoap需要单独写个AsyncTask来进行网络请求,而Retrofit包含了同步和异步请求框架,不用开发者单独写线程请求。
且Retrofit结合RxJava,现在变得越来越流行起来。
具体大家如何决择,还得具体情况具体分析。
--------------------我是华丽的分隔线-----------------------
这两天写了个demo,利用Retrofit网络框架进行WebService SOAP1.1请求,以请求天气预报为例,天气预报的请求网址为:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getWeatherbyCityName
这里边也很详情的说明了SOAP1.1和SOAP1.2请求model和返回mo del的数据格式。
工程下载地址为:
https://github.com/xiewenfeng/RetorfitWebServiceSample
转自:http://blog.csdn.net/smileiam/article/details/51957232
- /**
- * 服务器Retrofit变量初始化
- * Created by SmileXie on 16/7/16.
- */
- public class< /span> JXHDRetrofitGenerator {
- 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); //请求的webservice基址
- public static
S createService(ClassserviceClass) {- 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(2, TimeUnit. MINUTES)
- .writeTimeout(2, TimeUnit.MINUTES)
- .readTimeout(2, TimeUnit.MINUTES)
- .build();
- Retrofit retrofit = retrofitBuilder.client(client).build();
- return retrofit.create(serviceClass);
- }
- }
[java] view plain copy[java] view plain copy
- /**
- * 定义请求接口
- * Created by SmileXie on 16/7/15.
- */
- public interface JXHDInterfaceFun {
- @Headers({“SOAPAction: getRoleinfo”})//请求的Action,类似于方法名
- @POST(“service?wsdl”)//请求的地址
- Call
getRoleInfo(@Body RoleIn foRequestEnvelope requestEnvelope); - }
[java] view plain copy[java] view plain copy
- /**
- * Created by SmileXie on 16/7/15.
- */
- @Root(name = “soapenv:Envelope”)
- @NamespaceList( {
- @Namespace(reference = “http://www.w3.org/2001/XMLSchema-instance”, prefix = “xsi”),
- @Namespace(reference = “http://www.w3.org/2001/XMLSchema”, prefix = “xsd”),
- @Namespace(reference = “http://schemas.xmlsoap.org/soap/encoding/”, prefix = “enc”),
- @Namespace(reference = “http://schemas.xmlsoap.org/soap/envelope/”, prefix = “soapenv “)
- })
- public class RoleInfoRequestEnvelope {
- @Element(name = “soapenv:Body”, required = false)
- public RoleInfoRequestBody body;
- @Element(name = “soapenv:Header”, required = false)
- public String aHeader;
- }
p>
[java] view plain copy[java] view plain copy
- @Root(name = “soap12: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 = “soap12”, reference = “http://www.w3.org/2003/05/soap-envelope”) }) [java] view plain copy[java] view plain copy
- /**
- * 用户角色返回body
- * Created by SmileXie on 16/7/15.
- */
- @Root(name = “soapenv:Body”, strict = false)
- public class RoleInfoRequestBody {
- @Element(name = “getroleinfo”, required = false)
- public UserInfoBaseRequest getroleinfo;
- }
[java] view plain copy[java] view plain copy
- /**
- * 用户信息
- * Created by SmileXie on 16/7/15.
- */
- public class UserInfoBaseRequest {
- @Element (name = “token”, required = false)
- public String token;
- @Element(name = “userId”)
- public String userid;
- @Element(name = “userType”)
- public String userType;
- public String getToken() {
- return token;
- }
- }
[java] view plain copy[java] view plain copy
- /**
- * 用户角色返回总信息
- * Created by SmileXie on 16/7/15.
- */
- @R oot(name = “soapenv:Envelope”)
- @NamespaceList({
- @Namespace(reference = “http://www.w3.org/2001/XMLSchema-instance”, prefix = “xsi”),
- @Namespace(reference = “http://www.w3.org/2001/XMLSchema”, prefix = “xsd”),
- @Namespace(reference = “http://schemas.xmlsoap.org/soap/encoding/”, prefix = “enc”),
- @Namespace(reference = “http://schemas.xmlsoap.org/soap/envelope/”, prefix = “soapenv”)
- })
- public class RoleInfoResponseEnvelope {
- @Element(name = “Body”)
- public RoleInfoResponseBody body;
- }
[java] view plain copy[java] view plain copy
- /**
- * 用户角色返回body
- * Created by SmileXie on 16/7/15.
- */
- @Root(name = “Body”)
- public class RoleInfoResponseBody {
- @Element(name = “getroleinfoResponse”, required = false)
- public RoleInfoResponse roleInfoResponse;
- }
[java] view plain copy[java] view plain copy
- /**
- * 用户角色返回
- * Created by SmileXie on 16/7/15.
- */ < /span>
- @Root(name = “getroleinfoResponse”)
- @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/encoding/”, prefix = “enc”),
- @Namespace(reference = “http://schemas.xmlsoap.org/soap/envelope”, prefix = “env”),
- @Namespace(reference = “http://schemas.xmlsoap.org/soap/encoding/”, prefix = “encodingStyle”),
- })
- public class RoleInfoResponse {
- @Attribute(name = “encodingStyle”)
- public span> String encodingStyle;
- @Element(name = “getroleinfoReturn”)
- public RoleInfoResponseReturn reolInfo;
- }
[java] view plain copy[java] view plain copy
- /**
- * 用户角色返回
- * Created by SmileXie on 16/7/18.
- */
- @Root(name = “getroleinfoReturn”)
- @Namespace(reference = “http://www.w3.org/2001/XMLSchema-instance”, prefix = “xsi”)
- public class RoleInfoResponseReturn {
- @Attribute(name = “type” span>)
- public String xsiType;
- @Text()
- public String message;
- }
[java] view plain copy[java] view plain copy
- private void testSOAP() {
- JXHDInterfaceFun apiService = JXHDRetrofitGenerator.createService(JXHDInterfaceFun.class);
- RoleInfoRequestEnvelope requestEnvelope = new RoleInfoRequestEnvelope(); //soapenv:Envelope
- RoleInfoRequestBody requestBody = new RoleInfoRequestBody(); // body
- UserInfoBaseRequest baseRequest = new UserInfoBaseRequest(); // getroleinfo
- baseRequest.userid = “liliting”;
- baseRequest.userType = “2”;
- requestBody.getroleinfo = baseRequest;
- requestEnvelope.body = requestBody;
- Call
call = apiService.getRoleInfo(requestEnvelope); - call.enqueue(new Callback
() { - @Override
- public void onResponse(Response
response) { - Util.stopProgressDialog();
- RoleInfoResponseE nvelope roleInfoResponseEnvelope = response.body();
- if (roleInfoResponseEnvelope != null ) {
- String message = roleInfoResponseEnvelope.body.roleInfoResponse.reolInfo.message;
- BaseResponse baseResponse = GsonUtil.getJsonObject(message, BaseResponse.class);
- if(baseResponse != null) {
- RoleInfoResponse roleResponse = GsonUtil.getJsonObject(baseResponse.getMessage(), RoleInfoResponse.class);
- String roleType = roleResponse.getRoles();
- }
- }
- }
- @Override
- public void onFailure(Throwable t) {
- Util.stopProgressDialog();
- Toast.makeText(SendMessageActivity.this, getString(R.string.load_fail), Toast.LENGTH_SHORT).show();
- }
- });
- }
[java] view plain copy[java] view plain copy
WordPress database error: [Table 'yf99682.wp_s6mz6tyggq_comments' doesn't exist]
SELECT SQL_CALC_FOUND_ROWS wp_s6mz6tyggq_comments.comment_ID FROM wp_s6mz6tyggq_comments WHERE ( comment_approved = '1' ) AND comment_post_ID = 3470 ORDER BY wp_s6mz6tyggq_comments.comment_date_gmt ASC, wp_s6mz6tyggq_comments.comment_ID ASC