Retrofit 2 之自定义Converter实现加密解密

原创 2016年05月31日 21:29:47

版权声明:本文为博主原创文章,未经博主允许不得转载。

如果你还不知道,Retrofit2是什么,请你移步到hangyang的博客,认真看他写的 Retrofit2 完全解析 探索与okhttp之间的关系的这篇文章,他是现在我认为最全,也是最好的一篇,有关Retrofit2和OKhttp3的使用文档。

等你认真,领悟了,实践了,可能你就会产生下列的需求,Retrofit 2 之如何自定义Converter来实现数据的加密解密。

以下是我的个人实践,对Retrofit2我是才接触,不是很深,我只是记录我自己的工作笔记,希望你们看见的时候不要见笑。

项目使用的依赖包:

  //retrofit2
    compile 'com.squareup.retrofit2:retrofit:2.0.1'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
    compile 'com.squareup.retrofit2:converter-gson:2.0.1'
    compile 'com.google.code.gson:gson:2.6.2'
    //okhttp
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
    //rxjava
    compile 'io.reactivex:rxjava:1.1.5'
    compile 'io.reactivex:rxandroid:1.2.0'     
                在build.gradle(Module.app)    dependencies {***}  中添加

1.构建Retrofit和okhttp客户端

   //配置okhttp3客户端
  OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).build();

//构建Retrofit
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://192.168.10.225:8080")  //.baseUrl  是设置连接的地址
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create()) //添加Gson转换器
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 添加Rxjava适配器 
                .build();

2.自定义转换器 JsonConverterFactory,新建响应与请求

/**
 * Created by zhang on 2016/5/31.
 * <p>
 * 自定义 json转换器
 */
public class JsonConverterFactory extends Converter.Factory {

                ………………
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {

        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new JsonResponseBodyConverter<>(gson, adapter);  //响应
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {

        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new JsonRequestBodyConverter<>(gson, adapter); //请求
    }


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

/**
 * Created by zhang on 2016/5/31.
 * <p>
 * 自定义请求RequestBody
 */
public class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
                    ……………………
    @Override
    public RequestBody convert(T value) throws IOException {
        //加密
        APIBodyData data = new APIBodyData();   
        Log.i("xiaozhang", "request中传递的json数据:" + value.toString());
        data.setData(XXTEA.Encrypt(value.toString(), HttpConstant.KEY));
        String postBody = gson.toJson(data); //对象转化成json
        Log.i("xiaozhang", "转化后的数据:" + postBody);
        return RequestBody.create(MEDIA_TYPE, postBody);
        ###这里需要,特别注意的是,request是将T转换成json数据。你要在T转换成json之后再做加密。再将数据post给服务器,同时要注意,你的T到底指的那个对象
    }

}


-----------------------------------------------------------------------------------
/**
 * Created by zhang on 2016/5/31.
 * 自定义响应ResponseBody
 */
public class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
                      ……………………
    @Override
    public T convert(ResponseBody responseBody) throws IOException {

        String response=responseBody.string();

            String strResult = response.substring(1, response.length() - 1);
            String result = XXTEA.Decrypt(strResult, HttpConstant.KEY);//解密
            Log.i("xiaozhang", "解密的服务器数据:" + result);
            PageBean pageBean=mGson.fromJson(result,PageBean.class);
        return (T) pageBean;
   ###需要注意的是,response是将string转换成T,string需要先解密成json再转换成T,同样要注意你的T指代的谁。

    }

}

3.改GsonConverterFactory.create()为自定义的Converter:

     // .addConverterFactory(JsonConverterFactory.create())  自定义

这是我的效果图:

这里写图片描述

以下为全部代码:

api接口:

 @POST("api/SQBY/SQSJ/get_shequ_list")
    Observable<PageBean> getXiaoQuLiBiaoResulttwo(@QueryMap Map<String, String> urlPostFix, @Body String data);

Retrofit和okhttp客户端:

   //配置okhttp3客户端
  OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).build();

//构建Retrofit
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://192.168.10.225:8080")  //.baseUrl  是设置连接的地址
                .client(okHttpClient)
                .addConverterFactory(JsonConverterFactory.create())//添加自定义转换器
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 添加Rxjava适配器 
                .build();

执行请求:

//传递的json数据
    JSONObject object = new JSONObject();
        try {
            object.put("opencode", "JNPKL3M438O");
            object.put("name", "");
            object.put("areaid", "");
            object.put("lng", 106.561581);
            object.put("lat", 29.564743);
            object.put("pageindex", "1");
            object.put("pagesize", "10");

        } catch (JSONException e) {
            e.printStackTrace();
        }
  //请求
    SelectPlotBizApi selectPlotBizApi= HttpHelper.createApi(SelectPlotBizApi.class);
     selectPlotBizApi.getXiaoQuLiBiaoResulttwo(HttpHelper.getUrlPostFix(), object.toString()) //后缀,json
      .subscribeOn(Schedulers.io())//执行在io线程
                .observeOn(AndroidSchedulers.mainThread())//主线程显示
                .subscribe(new Subscriber<PageBean>() {
                    @Override
                    public void onCompleted() {
                        Log.i("xiaozhang", "执行完成:");
                    }

            @Override
           public void onError(Throwable e) {
              Log.i("xiaozhang", "for执行失败:" + e);
           }

           @Override
           public void onNext(PageBean pageBean) {
              Log.i("xiaozhang", "线程中执行的,数据为" + pageBean.ResultJson);
            }
         });

自定义的Converter:


**
 * Created by zhang on 2016/5/31.
 * <p>
 * 自定义 json转换器
 */
public class JsonConverterFactory extends Converter.Factory {

    public static JsonConverterFactory create() {
        return create(new Gson());
    }

    public static JsonConverterFactory create(Gson gson) {
        return new JsonConverterFactory(gson);

    }

    private final Gson gson;

    private JsonConverterFactory(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
    }


    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {

        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new JsonResponseBodyConverter<>(gson, adapter); //响应
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {

        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new JsonRequestBodyConverter<>(gson, adapter); //请求
    }


}

_______________________________________________________________________________

/**
 * Created by zhang on 2016/5/31.
 * <p>
 * 自定义请求RequestBody
 */
public class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private final Gson gson;
    private final TypeAdapter<T> adapter;

    /**
     * 构造器
     */

    public JsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
    }


    @Override
    public RequestBody convert(T value) throws IOException {
        //加密
        APIBodyData data = new APIBodyData();
        Log.i("xiaozhang", "request中传递的json数据:" + value.toString());
        data.setData(XXTEA.Encrypt(value.toString(), HttpConstant.KEY));
        String postBody = gson.toJson(data); //对象转化成json
        Log.i("xiaozhang", "转化后的数据:" + postBody);
        return RequestBody.create(MEDIA_TYPE, postBody);
    }

}

---------------------------------------------------------------------------------
**
 * Created by zhang on 2016/5/31.
 * 自定义响应ResponseBody
 */
public class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Gson mGson;//gson对象
    private final TypeAdapter<T> adapter;

    /**
     * 构造器
     */
    public JsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.mGson = gson;
        this.adapter = adapter;
    }

    /**
     * 转换
     *
     * @param responseBody
     * @return
     * @throws IOException
     */
    @Override
    public T convert(ResponseBody responseBody) throws IOException {

        String response = responseBody.string();

        String strResult = response.substring(1, response.length() - 1);
        String result = XXTEA.Decrypt(strResult, HttpConstant.KEY);//解密
        Log.i("xiaozhang", "解密的服务器数据:" + result);
        PageBean pageBean = mGson.fromJson(result, PageBean.class);
        return (T) pageBean;


    }

}

传递APIBodyData数据类:

public class APIBodyData {



    private String data;

    public String getData() {return data;}

    public void setData(String data) {
        this.data = data;
    }


}

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android网络请求使用Retrofit+OKHTTP,如何实现参数加密

项目中网络请求框架使用Retrofit+OKHTTP,如果需要进行参数加密呢?第一想法就是通过拦截器实现,Retrofit及OKHTTP都支持拦截器,但是拦截器却没有提供获取请求参数内容的方法,实现起...
  • lml0710
  • lml0710
  • 2015年12月17日 21:10
  • 4049

android retrofit 实战自定义converter,解决相同接口返回不同数据的问题

square的retrofit是目前比较火的网络框架,我目前也在用 今天项目上遇到一个问题,就是请求同一个接口,可能返回不同的json格式 例如,访问一个登录接口,成功的时候,返回的是 {     "...
  • vinoMVP
  • vinoMVP
  • 2017年01月10日 23:51
  • 2444

Retrofit 2.0 自定义Converter

requestBodyConverter 不执行的解决办法: **参数要使用@Body这种形式,否则 request 方法会不起作用。** 在Retrofit中,无论是发送数据和接收数据,都是通过OK...
  • jdsjlzx
  • jdsjlzx
  • 2016年07月08日 14:27
  • 22516

Retrofit自定义Converter之StringConverterFactory

之前写过一篇 浅谈Retrofit封装-让框架更加简洁易用 里面采用的是GsonConverterFactory对于retrofit的返回类型是只能有 具体对象、jsonObject、jsonArra...

Retrofit添加公共请求参数以及添加自定义的ConverterFactory

public class HttpBaseInterceptor implements Interceptor { @Override public Response intercept...
  • Ser_Bad
  • Ser_Bad
  • 2017年05月27日 16:16
  • 295

Retrofit2学习番外——自定义Converter与CallAdapter

有关Retrofit2的自定义Converter与CallAdapter

retrofit 自定义请求参数加密 和自定义响应解密 带你走出那些坑

首先,感谢一叶飘舟。给我灵感。 以及他分享的博文,从源码的角度来实现参数的加解密。 其次,也感谢这位这篇文章 :http://blog.csdn.net/zr940326/article/deta...

Retrofit2.0 公共参数(固定参数)

请先阅读: Retrofit 动态参数(非固定参数、非必须参数)(Get、Post请求)在实际项目中,对于有需要统一进行公共参数添加的网络请求,可以使用下面的代码来实现:RestAdapter re...
  • jdsjlzx
  • jdsjlzx
  • 2016年07月29日 13:32
  • 12747

Retrofit 2.0 自定义Converter补充篇

请先阅读: Retrofit 2.0 自定义Converter在使用Retrofit请求数据时,一般都用Gson解析Json数据。有时候请求得到的 Json 字符串与返回值类型不对应,比如:{"er...
  • jdsjlzx
  • jdsjlzx
  • 2016年07月19日 21:21
  • 13449

Retrofit2.0的Converter使用

在Retrofit中, 不管是发送数据或是接收数据, 最基本都是通过OKHttp的RequestBody和ResponseBody来实现,但是通常为了方便,我们在定制协议的时候,不会直接使用原始的Re...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Retrofit 2 之自定义Converter实现加密解密
举报原因:
原因补充:

(最多只允许输入30个字)