将retrofit2集成到同时具有webservice和http请求的Android项目中的解决方案

本文介绍了如何在既有webService又有http请求的Android项目中集成retrofit2。首先,文章阐述了适用场景和retrofit2的基本介绍,然后通过实例讲解了如何配置依赖、进行http请求以及处理webService请求,特别是针对webService的特殊处理。在集成过程中,遇到了OkHttp3依赖冲突的问题,通过删除ksoap中冲突的库解决了问题。最后,文章总结了集成过程中的关键点和注意事项,并提供了其他学习资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

retrofit2集成(webService、http)

适用环境

1、项目中既有webService服务,也有http服务;
2、项目原有服务是webService或者http其中的一种,由于需求变更等原因要更换服务类型,同时要在不影响原来的服务请求的情况下进行网络框架重构;
3、写服务的换人了;<或者服务人员想装逼,彰显他会多种服务语言>

retrofit2简单介绍

retrofit是由Square公司出品的针对于Android和Java的类型安全的Http客户端。
简单的说就是一种网络请求框架,对okHttp的封装,使用面向接口的方式进行网络请求,利用动态生成的代理类封装了网络接口请求的底层,其将请求返回javaBean,对网络认证 REST API进行了很好对支持此,使用Retrofit将会极大的提高我们应用的网络体验。

【其实自己是看了github上的网络框架使用统计,排名第一的就是retrofit,所以就去稍稍的研究了一下,发现还挺好用,毕竟这热度可不是水军给刷上去的。】

下面就以我自己的项目中的例子来给大家演示一下今天的核心内容:

实例讲解

一、情景重现

为了迎合后台服务人员(以前公司的后台只会写webService)的服务类型,我们移动端选择采用比较常用ksoap网络请求框架来请求webService服务,首先以图片的形式看一下项目中ksoap网络请求的封装类。
封装好的ksoap网络请求帮助类

以上就是原来项目中用到的ksoap网络请求帮助类,看起来也还OK,但是在实际的项目中,每到一次网络请求就要new出来一个handler或者asyncTask去处理网络请求,并且代码写起来很长很冗余,导致一个页面有多个请求的时候,光关于网络请求的代码就一大堆。另外原来的项目也灭有框架可言,基本大部分的代码都在activity或者fragment中,导致界面工作效率过低,代码过于混乱。
【这里有个不大不小的坑,注意图片中红色部分,留着到后面再讲QAQ】

基于这样的情况,项目组经过商议后决定要重构项目,其中就包括网络请求框架。要求在不改变以前程序代码的基础下进行代码重构。所以经过慎重考虑后,决定将retrofit2集成进我们的项目中去。

二、retrofit集成

1、首先导入retrofit2的相关依赖:

    //retrofit网络框架
    compile 'com.squareup.retrofit2:retrofit:2.3.0'          //retrofit2.3.0类库
    compile'com.squareup.retrofit2:converter-scalars:2.3.0'  //关于字符串的转换器
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'    //关于gson的转换器
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1' //okhttpClient的log拦截器

2、http请求:
依赖包导入成功后就可以放肆的利用retrofit2进行实验了,首先用一个简单的http请求测试一下是否能走通。

    public interface PostApi {
    /**
     * 上传错误信息接口
     * */
    @POST("api/OPERATION_ERROR_STATISTICS")
    Call<ResponseBody> postError(@Body ErrorBean bean);
    }

以上是一个简单的post请求接口。
【实体类就不贴了,自定义任何一个实体类都可以】
然后是请求的方法及回调:

 public void errorPost(List<CrashBean> list){

        //创建retrofit
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ActionNet.BASE_URL)
                .client(getOkHttpClient())
                .addConverterFactory(GsonConverterFactory.create()) 
                .build();

        PostApi api = retrofit.create(PostApi.class);
        ErrorBean bean = new ErrorBean();
        bean.setData(list);
        Call<ResponseBody> call = api.postError(bean);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    if(response.body() != null){
                        String result = response.body().string();
                        Log.e(TAG+"Error", "onResponse: "+result);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.e(TAG+"Error", "onFailure: ");
            }
        });
    }

retrofit2的具体实现我就不说了,相信大家都已经了解过retrofit2了。
程序走了一遍可以走通,证明了retrofit2是可以正常使用的。

3、retrofit2请求webService

好了,轮到本文重头戏上场了。
首先,尝试着使用retrofit2请求webService:
【当然对于这个刚开始我是一脸懵逼的,要不是网上有一些关于retrofit2请求webService的文章,我还真的不知道从何下手,毕竟webService的请求接口中注解有点儿复杂】
/**
* 获取补丁版本
* */
@Headers({“Content-Type: text/xml;charset=UTF-8”, “SOAPAction: http://tempuri.org/getNewAppPatch“}) //请求的Action,类似于方法名
@POST(“GetTJWebService.asmx”)
Call getNewAppPatch(@Body String envelope);

看到webService请求接口里的请求头了吧,超复杂的感觉。【注意我的请求实体类是String,使用String是为了所有的请求都能公用一个类,所以就把实体类转换成String并进行封装(当然simplexml的转换器可以自动将实体类进行解析,但是这样太麻烦,每一个请求都要写一大堆转换类)】
首先要知道webService服务是以xml的形式进行请求并返回数据,这里给大家贴一下webService的请求
webService请求
webService返回

可以看到,webService的请求和返回都是有固定格式的要求(这里用的是soap1.1版本),所以这里为了使所有的webService请求都能适配,我这里封装了一个自定义的请求及返回数据的处理类,即webService的请求和接收都是将参数或者返回数据处理成String字符串进行请求和接收。代码如下:

public class Node {
    public static String toStart(String name){
        return "&lt;"+name+"@gt;";
    }

    public static String toEnd(String name){
        return "&lt;/"+name+"&gt;";
    }

    public static String getRequest(String namespace, Map<String,String> map){
        StringBuffer sbf = new StringBuffer();

        String startStr = "<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"
                +"      <"+namespace+" xmlns=\"http://tempuri.org/\">\n";

        sbf.append(startStr);

        for (Map.Entry<String,String> entry : map.entrySet()){
            sbf.append("            <"+entry.getKey()+">"+entry.getValue()+"</"+entry.getKey()+">\n");
        }
        String endStr = "       </"+namespace+">\n"
                +"  </soap:Body>\n"
                +"</soap:Envelope>";

        sbf.append(endStr);

        return sbf.toString();
    }
}

这是请求的封装,下面是接收的封装:

public Map<String,String> dealResponse(Response<ResponseBody> response){
        Map<String,String> map = new HashMap<>();
        String head = response.raw().request().header("SOAPAction");
        String url = response.raw().request().url().toString();
        String type = null,data = null,res = null;
        try {
            if(head != null){                                                                   //webService请求
                String name = head.replace(AppNet.NAME_SPACE, "");
                type = url+"/"+name;
                data = response.body().string().replaceAll("&lt;","<").replaceAll("&gt;",">");
                res = StringUtils.substringBetween(data,"<"+name+"Result>","</"+name+"Result>");
            }else {                                                                             //Http请求
                type = url;
                data = response.body().string();
                res = data;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        map.put("data",res);
        map.put("url",type);
        return map;
    }

这样请求和接收的转换都有了,现在就来测试一下请求webService。
请求接口上面已经贴过了,下一步就是创建retrofit,这里我进行了一下封装。

//创建retrofit
public void creatRetrofit(){
    if(retrofit == null){
        OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();

        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient client = okHttpClient.connectTimeout(2, TimeUnit.MINUTES)
                .writeTimeout(2, TimeUnit.MINUTES)
                .readTimeout(2, TimeUnit.MINUTES)
                .addInterceptor(httpLoggingInterceptor)
                .build();

        retrofit = new Retrofit.Builder()
                .baseUrl(this.BASE_URL)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();
    }
    if(mService == null){
        mService = retrofit.create(UserService.class);
    }
}

注意:ScalarsConverterFactory一定要加上,不然无法将String字符串转换成xml的请求格式,这个坑我可是看了好久才搞出来,一定要注意细节!
其中UserService是我的接口类。
然后就是发出请求:

public void getVerson(String xml, Callback<ResponseBody> callback){
    Call<ResponseBody> call = mService.getNewAppPatch(xml);
    call.enqueue(callback);
}

请求之后是回调:

    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        if(response.body() != null){
            map = model.dealResponse(response);
            data = map.get("data");
            url = map.get("url");
            if(model.isWebService(response)){
                //进行xml解析
                switch (url){
                    case "":
                        break;
                }
            }else {
                //进行json解析
                switch (url){
                    case "":
                        break;
                }
            }
        }else {
            Log.e("fail", "requestFailed");
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.e("error", "requestError");
    }

【这里的回调和上面的返回数据转换,我把webService和http都进行了区分,这样不管是webService还是http都可以公用一个回调,适用于一个页面既有webService也有http请求,并且都是多个请求。】

本以为这样就可以万事大吉,但是点一下运行,程序报错了,我们来看看报错内容吧:
报错信息

一目了然,依赖包冲突,而且是OkHttp3的依赖包冲突。心想,我的项目里没有导入OkHttp啊,哪来的冲突?于是乎我就在项目中进行寻找,还真让我找到了:
ksoap的jar包
原来如此,ksoap的jar包里包含了okhttp3,而且retrofit是强制封装了OkHttp3,所以才会有冲突,这样的话就只好去重了啊,我的方法是这样的,把ksoap包里的okhttp3和okio这两个包给删掉,然后我们在文章顶部中soapUtils类里,把红色部分改为HttpTransportSE就可以了。
这里写图片描述
然后再运行,项目完完整整的跑出来了。这就是将retrofit2集成到同时具有webService和http请求的项目中去的解决方案了。

总结

1、把webService的请求和接收封装起来,这样使请求更加方便。
2、在retrofit2请求webService的时候,如果要使用String转换的话一定要加上ScalarsConverterFactory的转换器;
3、ksoap的jar包里是有okhttp请求的,所以retrofit和ksoap会有冲突依赖,根据实际情况解除冲突;
4、本文没有具体的说明retrofit请求http和webService的教程,如果大家不是很了解,建议去看看其他博主的博客,如:
http://blog.youkuaiyun.com/lmj623565791/article/details/51304204 retrofit2完全解析
http://www.jianshu.com/p/b865c855a1e8 retrofit2 + OkHttp + WebService请求
5、建议你的后台人员只写一种服务,因为这样的多种请求真是要搞死人QAQ。

本博主第一次写这么长的文章,希望大家多多支持,有什么不对的还希望大家多多指正。
代码还没来得及上传到github,如有需要请留言。
谢谢侬!(鞠躬)

ps:主要解决在webservice中,我们想从另外一个项目调用webservice项目的接口,也就是跨项目调用接口 这里主要用到了xfire wsdl 废话不说了 直接上东西 1. 首先新建一个项目 2. 在src下创建两个文件: a) 第一个是你想要访问的webservice的接口,比如我想访问的接口是 ReleaseService 那就在当前项目创建一个ReleaseService接口(接口中的方法必须你想要访问的webservice的接口中的方法相同) b) 第二个是你的调用类 3. 导入相应的jar包,这些包不能引用,一定要复制到lib文件夹下面在引用 4. 具体的实现代码 TestWebService方法的代码: package com.isanta.webServiceTest; import java.io.InputStream; import java.net.MalformedURLException; import java.util.Properties; import java.util.Scanner; import org.codehaus.xfire.XFireFactory; import org.codehaus.xfire.client.XFireProxyFactory; import org.codehaus.xfire.service.Service; import org.codehaus.xfire.service.binding.ObjectServiceFactory; public class TestWebService { /** * @param args */ public static void testWebService() throws MalformedURLException, Exception{ // TODO Auto-generated method stub /** *这里是我的参数放在了properties文件中,我在读取里面的参数,这里我们也可以通过方法传参数 *如 : testWebService(String url,String xMlStr)() 那么在调用的时候就可以直接传进来了 *url 是你访问的webservice 的tomcat 的服务器地址 */ Properties pro = new Properties(); InputStream in = null; in = TestWebService.class.getResourceAsStream("/request.properties"); pro.load(in); String url = pro.getProperty("url"); String xMLstr = pro.getProperty("xMLstr"); Service s=new ObjectServiceFactory().create(ReleaseService.class); XFireProxyFactory xf=new XFireProxyFactory(XFireFactory.newInstance().getXFire()); System.out.println("url="+url); try { //这里就是获取webservice的接口的实例对象 ReleaseService seleaseService=(ReleaseService) xf.create(s,url); System.out.println("进入接口----------------->请求报文:"+xMLstr); //这里就是调用你需要的接口的方法 String st=seleaseService.queryReceiptDatas(xMLstr); System.out.print(st); } catch(Exception e) { e.printStackTrace(); } } } 5. 将整个项目打包成jar 6. 将打好的jar包引入到你想要调用的项目中,然后就想 正常的代码一样来调用,如: import java.net.MalformedURLException; import com.isanta.webServiceTest.TestWebService; public class Test { public static void main(String[] args) throws MalformedURLException, Exception { TestWebService.testWebService(); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值