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

来源:互联网 发布:cimatrone11编程教程 编辑:程序博客网 时间:2024/06/07 10:36

 首先,感谢一叶飘舟。给我灵感。

以及他分享的博文,从源码的角度来实现参数的加解密。

其次,也感谢这位这篇文章 :http://blog.csdn.net/zr940326/article/details/51549310

 技术性人员就是不喜欢多啰嗦,直接来看代码吧。

首先要了解这个东西   --------  ConverterFactory。


这是retrofit 里面一个比较重要的类,他管理着request 和response ,要想实现自己需求的请求和参数,他是两者的桥梁。

(PS:retrofit 的封装是一门艺术,这里就不多讲了,基本的配置以及结合RX来实现 的文章已经很多了,自己去好好看看)


好的,接下来我们看下 Converter工厂的源码,直接从as 贴了

public interface Converter<F, T> {    T convert(F var1) throws IOException;    public abstract static class Factory {        public Factory() {        }        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {            return null;        }        public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {            return null;        }        public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {            return null;        }    }}

三部分组成:请求 、响应、StringConverter

我们再来看看retrofit 给我提供的Converter

public final class GsonConverterFactory extends Factory {    private final Gson gson;    public static GsonConverterFactory create() {        return create(new Gson());    }    public static GsonConverterFactory create(Gson gson) {        return new GsonConverterFactory(gson);    }    private GsonConverterFactory(Gson gson) {        if(gson == null) {            throw new NullPointerException("gson == null");        } else {            this.gson = gson;        }    }    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {        TypeAdapter adapter = this.gson.getAdapter(TypeToken.get(type));        return new GsonResponseBodyConverter(this.gson, adapter);    }    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {        TypeAdapter adapter = this.gson.getAdapter(TypeToken.get(type));        return new GsonRequestBodyConverter(this.gson, adapter);    }}
好,就此我们了解到, 我们需要在request 和response 上来做文章了

这里要注意,看一下request和response  方法返回的是什么,是的返回了对应的converter。这两个的源码自己点进去看吧。


下面贴一下自己的requestconverter

public class MyRequestConverter<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 MyRequestConverter(Gson gson, TypeAdapter<T> adapter) {        this.gson = gson;        this.adapter = adapter;    }    @Override    public RequestBody convert(T value) throws IOException {        Log.e("数据", "转换前:" + value.toString());        Log.e("数据", "转化后:" + Base64_Utils.encryptBASE64(value.toString()));        return RequestBody.create(MEDIA_TYPE,                Base64_Utils.encryptBASE64(value.toString()).substring(0,Base64_Utils.encryptBASE64(value.toString()).length()-3));    }}

我这里简单的urlencode +base64加密。实际中根据需求来,注释已经写的很详细了。


下面贴一下封装的ServiceFactory

public class ServiceFactory {    private final Gson gson;    private ServiceFactory(){        gson = new GsonBuilder()                .setDateFormat("yyyy-MM-dd hh:mm:ss")                .create();    }    private static class SingleHolder{        private static final ServiceFactory INSTANCE = new ServiceFactory();    }    public static ServiceFactory getInstacne(){        return SingleHolder.INSTANCE;    }    //create a service    public <S> S createService(Class<S> serviceClass) {        String baseUrl = "";        try {            Field field1 = serviceClass.getField("BASE_URL");            baseUrl = (String) field1.get(serviceClass);        } catch (NoSuchFieldException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.getMessage();            e.printStackTrace();        }        Retrofit retrofit = new Retrofit.Builder()                .baseUrl(baseUrl)                .client(getOkHttpClient())                .addConverterFactory(MyConverterFactory.create())                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .build();        return retrofit.create(serviceClass);    }    private final static long DEFAULT_TIMEOUT = 10;    private OkHttpClient getOkHttpClient() {        //定制OkHttp        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();        //设置超时时间        httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);        httpClientBuilder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);        httpClientBuilder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);        httpClientBuilder.addInterceptor(new Interceptor() {            @Override            public Response intercept(Chain chain) throws IOException {                Request request = chain.request();                Request.Builder builder1 = request.newBuilder();                Request build = builder1.addHeader("USER-AGENT", clientType + "," +                        deviceId + "," +                        mobileBrand + "," +                        phoneModel + "," +                        systemName_versionNumber + "," +                        APP_versionNumber + "," +                        SDK_versionNumber + "," +                        pushNumber + "," +                        networkType + "," +                        APP_internalVersionNumber + "," +                        applicationMarketName + "," +                        screenResolution + "," +                        API_interfaceVersionNumber).                        build();                return chain.proceed(build);            }        });        //设置缓存//        File httpCacheDirectory = new File(FileUtils.getCacheDir(SolidApplication.getInstance()), "OkHttpCache");//        httpClientBuilder.cache(new Cache(httpCacheDirectory, 10 * 1024 * 1024));        return httpClientBuilder.build();    }

使用自定义的converter 要在retrofit 中添加自己的converter即可。


下面看一下接口API

@POST("/index/index/sms_code")Observable<BaseResopnse> sms_code(@Body String data);

接下来我们看实际的调用。

JSONObject jsonObject  = new JSONObject();try {    jsonObject.put("phone","15888810472");    jsonObject.put("check",1);} catch (JSONException e) {    e.printStackTrace();}ServiceFactory.getInstacne()        .createService(UserInfoService.class)        .sms_code(jsonObject.toString())        .observeOn(AndroidSchedulers.mainThread())        .subscribeOn(Schedulers.io())        .subscribe(new ResultSubcriber() {            @Override            public void onSuccess(String str) {                Toast.makeText(getActivity(),"成功"+str,Toast.LENGTH_LONG).show();            }            @Override            public void _onError(Throwable e) {                Toast.makeText(getActivity(),"失败----"+e,Toast.LENGTH_LONG).show();            }        });
好了,这样就实现类请求数据响应数据的加解密。

注意这么几点:

1,参数要使用@Body这种形式,否则 request 方法会不执行。

2,请求和响应的操作在响应的Converter里做处理。

3,搭建request 和response 的桥梁。

4,添加桥梁依赖


原创粉丝点击