如何在Volley单例中统一附加Bearer Token请求头,避免代码重复?
这个需求太常见了,我之前做项目的时候也嫌每个请求手动加Token太繁琐,后来用了两种靠谱的方法解决,都能实现在Volley单例里统一处理请求头,彻底告别重复代码:
方法一:自定义基础Request类(兼容所有Volley版本)
创建一个所有业务请求都继承的基类,在这个基类里重写getHeaders()方法统一添加Token,这样所有子类请求都会自动带上Authorization头:
import com.android.volley.AuthFailureError; import com.android.volley.Response; import com.android.volley.StringRequest; import android.text.TextUtils; import java.util.HashMap; import java.util.Map; public class BaseAuthRequest extends StringRequest { public BaseAuthRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) { super(method, url, listener, errorListener); } @Override public Map<String, String> getHeaders() throws AuthFailureError { // 先获取父类的默认请求头 Map<String, String> headers = super.getHeaders(); if (headers == null) { headers = new HashMap<>(); } // 从你的Token管理类(比如SharedPreferences)获取Access Token String accessToken = YourTokenUtil.getSavedToken(); if (!TextUtils.isEmpty(accessToken)) { headers.put("Authorization", "Bearer " + accessToken); } return headers; } }
之后你的业务请求只需要继承这个基类就行,不用再写任何添加Token的代码:
public class UserProfileRequest extends BaseAuthRequest { public UserProfileRequest(Response.Listener<String> listener, Response.ErrorListener errorListener) { super(Method.GET, "https://your-api-domain/user/profile", listener, errorListener); } }
方法二:使用RequestInterceptor(Volley 1.1.0+ 推荐)
如果你的Volley版本是1.1.0或更高,可以利用RequestQueue的拦截器功能,在请求发送前统一注入Token,这种方法不需要修改现有请求类,更适合已经有大量请求的项目:
在你的Volley单例初始化代码中,添加一个请求拦截器:
import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.toolbox.Volley; import android.content.Context; import android.text.TextUtils; import java.util.HashMap; import java.util.Map; public class VolleySingleton { private static VolleySingleton instance; private RequestQueue requestQueue; private static Context appContext; private VolleySingleton(Context context) { appContext = context.getApplicationContext(); requestQueue = getRequestQueue(); } public static synchronized VolleySingleton getInstance(Context context) { if (instance == null) { instance = new VolleySingleton(context); } return instance; } public RequestQueue getRequestQueue() { if (requestQueue == null) { requestQueue = Volley.newRequestQueue(appContext); // 添加全局请求拦截器 requestQueue.addRequestQueueInterceptor(new RequestQueue.RequestInterceptor() { @Override public void intercept(Request<?> request) { Map<String, String> headers = request.getHeaders(); if (headers == null) { headers = new HashMap<>(); } String accessToken = YourTokenUtil.getSavedToken(); if (!TextUtils.isEmpty(accessToken)) { headers.put("Authorization", "Bearer " + accessToken); } // 更新请求的头信息 request.setHeaders(headers); } }); } return requestQueue; } public <T> void addToRequestQueue(Request<T> req) { getRequestQueue().add(req); } }
这样不管你用的是StringRequest、JsonArrayRequest还是自定义Request,只要通过这个单例的requestQueue发送,都会自动带上Bearer Token。
额外注意点
- 确保Token的获取逻辑是线程安全的,因为Volley的请求可能在后台线程执行
- 如果需要处理Token过期的情况,可以在拦截器或者基类的
getHeaders()方法里扩展逻辑(比如捕获401错误后刷新Token并重试请求) - 新项目推荐用方法一,结构更清晰;已有大量请求的项目优先用方法二,侵入性更低
内容的提问来源于stack exchange,提问作者Geoff
相关产品推荐
相关产品推荐

