【问题】解决Retrofit中为Post请求设置统一参数

博客围绕Retrofit中为Post请求设置统一参数的问题展开。使用RequestBody发送请求无法添加统一参数,FormBody又存在与后台要求不匹配的问题。给出两种解决方案,一是自定义RequestBody并在拦截器中添加统一参数,二是通过建造者模式链式调用添加参数,还介绍了BaseModel的使用方式。

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

问题:Retrofit中为Post请求设置统一参数

情景:使用RequestBody发送Post请求,无法添加统一参数,换成FormBody网上倒是有很多解决方案,但是FormBody一方面MediaType跟后台要求的对应不上(不确定这个对请求有没有影响),另一方面只能传String参数(如果有什么方法可以传递其他参数欢迎留言补充),跟后台的要求对不上。

解决方案:

1.自定义RequestBody

import java.io.IOException;
import java.nio.charset.Charset;

import javax.annotation.Nullable;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.internal.Util;
import okio.BufferedSink;
/**
 *@description 自定义RequestBody,解决POST请求时拦截器添加统一参数问题
 *@author mxm
 *@creatTime 2018/10/24  下午6:13
 */
public class PostJsonBody extends RequestBody {

        private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        private static final Charset charset = Util.UTF_8;

        private String content;

        public PostJsonBody(String content) {
            this.content = content;
        }

        public String getContent() {
            return content;
        }

        @Nullable
        @Override
        public MediaType contentType() {
            return JSON;
        }

        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            byte[] bytes = content.getBytes(charset);
            if (bytes == null) throw new NullPointerException("content == null");
            Util.checkOffsetAndCount(bytes.length, 0, bytes.length);
            sink.write(bytes, 0, bytes.length);
        }

        public static RequestBody create(String content) {
            return new PostJsonBody(content);
        }
}


其实就是个中转站,先把我们的参数用JsonString的方式存着,然后在拦截器中解析出来,加上统一的参数,再重新建立一个RequestBody 发送出去。

2、在拦截器中添加统一参数(这里的Gson设置是为了解决jsonString转map时会出现Int被转成Double的问题

public class BaseParamsInterceptor implements Interceptor {
    Gson gson;
    public BaseParamsInterceptor(TokenProvider tokenProvider) {
        this.gson = new GsonBuilder()
                .registerTypeAdapter(
                        new TypeToken<HashMap<String, Object>>(){}.getType(),
                        new JsonDeserializer<HashMap<String, Object>>() {
                            @Override
                            public HashMap<String, Object> deserialize(
                                    JsonElement json, Type typeOfT,
                                    JsonDeserializationContext context) throws JsonParseException {

                                HashMap<String, Object> hashMap = new HashMap<>();
                                JsonObject jsonObject = json.getAsJsonObject();
                                Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
                                for (Map.Entry<String, JsonElement> entry : entrySet) {
                                    hashMap.put(entry.getKey(), entry.getValue());
                                }
                                return hashMap;
                            }
                        }).create();
    }
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request.Builder requestBuilder = request.newBuilder();
        if (request.method().equals("POST")) {
            RequestBody requestBody = request.body();
            if (requestBody instanceof PostJsonBody) {
                String content = ((PostJsonBody) requestBody).getContent();
                HashMap<String, Object> hashMap = gson.fromJson(content, new TypeToken<HashMap<String, Object>>(){}.getType());
                //添加统一参数
                hashMap.put("auth_token", tokenProvider.getAuthToken());
                //end
                requestBuilder.post( RequestBody.create(MediaType.parse("application/json; charset=utf-8"), gson.toJson(hashMap)));
            }
        }
        return chain.proceed(requestBuilder.build());
    }
}

3、使用方法没什么变化(记得设置拦截器)

        map.put("shop_id", Integer.valueOf(userAuthManager.getShopId()));

        final RequestBody requestBody = PostJsonBody.create(GsonUtil.toJson(map));

2018年11月27日15:20:28

这种方式不太好,不过也能实现功能,目前没有发现什么问题,现在我换了种方式,通过建造者模式(不知道用的对不对,正在学设计模式,如果错了后面改进吧)链式调用添加参数

public class ParamsBuilder {
    static{
        gson=new Gson();
    }
    private static Gson gson;
    private Map<String,Object> map;
    ParamsBuilder(){
        this.map=new HashMap<>();
    }
    /**
     * 添加参数
     */
    public ParamsBuilder addParams(String key, Object value) {
        if (TextUtils.isEmpty(key)) {
            throw new NullPointerException("key 不能为空");
        }
        map.put(key, value);
        return this;
    }

    /**
     * 添加全局参数
     */
    public ParamsBuilder addCommonMap() {
        //添加统一参数
        addParams("auth_token",UserAuthManager.getInstance().getAuthToken());
        return this;
    }
    /**
     * 返回map集合
     */
    public Map bulid(){
        return map;
    }
    /**
     * 返回json字符串
     */
    public String toJson(){
        return gson.toJson(map);
    }
    /**
     * 返回RequestBody
     */
    public RequestBody toRequestBody(){
        return RequestBody.create(
                MediaType.parse("application/json; charset=utf-8"),toJson());
    }
}

BaseModel:

public class BaseModel {
    protected ApiService service;

    public BaseModel() {
        service = ApiManager.getInstance().getApiService();
    }
    /**
     * 链式添加参数
     */
    protected ParamsBuilder getBuilder(){
        return new ParamsBuilder();
    }
}

使用方式,在Model中继承BaseModel,然后在方法中通过addCommonMap()就能添加统一参数,其实就是简单的写在基类里面了。

RequestBody requestBody = getBuilder()
                .addCommonMap()
                .addParams("start_time",startTime)
                .addParams("end_time",endTime).toRequestBody();

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值