Android Retrofit2+okhttp3中文传参乱码问题之一

导致后台接收乱码原因:因为接口传参时,使用用了拦截器添加公共参数,而Post请求在拦截时,使用得时FormBody重新构建得参数表单。其内部得编码格式是固定的,无法设置。
查看FormBody编码方式源码:

override fun contentType() = CONTENT_TYPE
...
companion object {//可以看到FormBody表单内容编码方式不是UTF-8的
    private val CONTENT_TYPE: MediaType = "application/x-www-form-urlencoded".toMediaType()
  }

添加公共参数原代码:

if (method.equals("POST")) {
            if (oldRequest.body() instanceof FormBody) {
                FormBody.Builder bodyBuilder = new FormBody.Builder();//Charset.forName("UTF-8")
                FormBody formBody = (FormBody) oldRequest.body();
                for (int i = 0; i < formBody.size(); i++) {//---------------注意:一定需要将原来的参数添加到FormBody.Builder里面,等全部参数添加完后,再生成新连接
                    //Log.e("okhttp","formbody里面的参数:"+i+formBody.name(i)+":"+formBody.value(i));
                    bodyBuilder.add(formBody.name(i), formBody.value(i));
                }
                for (Map.Entry params : mUrlParamsMap.entrySet()) {
                    //原本写法
                    //formBody=bodyBuilder.add(params.getKey(),params.getValue()).build();
                    //修改
                    //POST请求方法添加公共参数
                    bodyBuilder.add(params.getKey(), params.getValue());
                    //Log.e("okhttp","公共参数Post"+params.getKey()+":"+params.getValue());
                }
                formBody = bodyBuilder.build();//修改
                for (int i = 0; i < formBody.size(); i++) {
                    //Log.e("okhttp","body里面的参数:"+i+formBody.name(i)+":"+formBody.value(i));
                }
                newRequest = oldRequest.newBuilder().post(formBody).build();
                Response response = chain.proceed(newRequest);
                String content = response.body().string();

                MediaType contentType = response.body().contentType();
                //Log.e("okhttp","执行拦截添加Post"+content+":"+newRequest.toString());
                printUrl(newRequest, formBody);

                return response.newBuilder()
                        .body(ResponseBody.create(content, contentType))
                        .build();
            }

修改后代码:(把表单FormBody转换成RequestBody避免表单自动为参数进行编码)

if (method.equals("POST")) {
            if (oldRequest.body() instanceof FormBody) {
                FormBody.Builder bodyBuilder = new FormBody.Builder();//Charset.forName("UTF-8")
                FormBody formBody = (FormBody) oldRequest.body();
                for (int i = 0; i < formBody.size(); i++) {//---------------注意:一定需要将原来的参数添加到FormBody.Builder里面,等全部参数添加完后,再生成新连接
                    //Log.e("okhttp","formbody里面的参数:"+i+formBody.name(i)+":"+formBody.value(i));
                    bodyBuilder.add(formBody.name(i), formBody.value(i));
                }
                for (Map.Entry params : mUrlParamsMap.entrySet()) {
                    //原本写法
                    //formBody=bodyBuilder.add(params.getKey(),params.getValue()).build();
                    //修改
                    //POST请求方法添加公共参数
                    bodyBuilder.add(params.getKey(), params.getValue());
                    //Log.e("okhttp","公共参数Post"+params.getKey()+":"+params.getValue());
                }

                StringBuffer sb = new StringBuffer();
                formBody = bodyBuilder.build();//修改
                for (int i = 0; i < formBody.size(); i++) {
                    //Log.e("okhttp","body里面的参数:"+i+formBody.name(i)+":"+formBody.value(i));
                    sb.append(formBody.name(i)+"="+formBody.value(i)+"&");
                }
                RequestBody requestBody = RequestBody.create(FORM_CONTENT_TYPE, sb.toString());
                //.addHeader("Content-Type","application/x-www-form-urlencoded; charset=utf-8")
                newRequest = oldRequest.newBuilder().post(requestBody).build();
                Response response = chain.proceed(newRequest);
                String content = response.body().string();

                MediaType contentType = response.body().contentType();
                //Log.e("okhttp","执行拦截添加Post"+content+":"+newRequest.toString());
                printUrl(newRequest, formBody);

                return response.newBuilder()
                        .body(ResponseBody.create(content, contentType))
                        .build();
            }

传参编码处理:

//参数传入前,使用URLDecoder.decode(getChnlType(),"UTF-8")编码
if ("single".equals(indexBean.getConditionType())&&!TextUtils.isEmpty(getChnlTypeKey())
                    &&!TextUtils.isEmpty(getChnlType())){
                map.put(getChnlTypeKey(),URLDecoder.decode(getChnlType(),"UTF-8"));
            }

到此,问题解决

你可能感兴趣的:(Android Retrofit2+okhttp3中文传参乱码问题之一)