Retrofit2拦截器,只在特定方法中使用token
Retrofit2 interceptor, using token only in specific methods
我想在 Retrofit2
中使用 authorization
。我选择了 interceptor
方式,因为几乎所有方法都需要 authorization
,除了我正在获取令牌以进一步用于其他方法的方法。
我的问题是:我怎样才能做到这一点?
我将访问令牌存储在 SharedPreferences
中。我的第一个想法是:“我可以在我的 RetrofitClient
class 中检索它,并根据令牌是否为 null 或它是否具有值来创建合适的 Retrofit
实例 "(添加或不添加 .client()
。
不幸的是,这并不容易,因为需要 Context
才能获得偏好。
我不知道如何将它传递到 RetrofitClient
class 或如何进入它。
这是我的 RetrofitClient
class:
public class RetrofitClient {
public static final String BASE_URL = "http://localhost";
public static Retrofit retrofit = null;
private RetrofitClient() {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
//.client(getRequestHeader())
.build();
}
/*OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer" + )
}
})*/
public static synchronized Retrofit getInstance() {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
public Api getApi() {
return retrofit.create(Api.class);
}
}
我的 getRequestHeader()
是我之前设置超时的方法。
我想创建这样的实例:
private RetrofitClient() {
tokenService.token = null;
tokenService.readToken(ApplicationContext.getInstance());
if (tokenService.token == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
} else {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client) //I have interceptor here with access token
.build();
}
}
然后:
RetrofitClient.getInstance().create(Api.class).getToken()
//获取令牌
RetrofitClient.getInstance().create(Api.class).someMethod()
//当我得到Token
这是好方法吗?
只需在 RetrofitClient 或其他视情况添加 SharedPreferences 作为构造函数参数即可
您可以通过以下方式进行:
首先使用单例实例
创建首选项class
Preferences
public class Preferences {
public static Preferences INSTANCE;
private final String PREFERENCE_FILE = "my_preferences";
public final String PREF_TOKEN = "pref_user_token";
private SharedPreferences mPrefs;
private SharedPreferences.Editor mEdit;
private Preferences() {
Application app = MyApplicationClass.getInstance();
mPrefs = app.getSharedPreferences(PREFERENCE_FILE, Context.MODE_PRIVATE);
mEdit = mPrefs.edit();
}
// Returns singleton instance
public static Preferences getInstance() {
if (INSTANCE == null)
INSTANCE = new Preferences();
return INSTANCE;
}
public String getToken() {
return Preferences.getInstance().mPrefs.getString(PREF_TOKEN, "");
}
public void saveToken(String value) {
mEdit.putString(PREF_TOKEN, value);
mEdit.apply();
}
}
然后在你的 RetrofitClient class 中改变如下:
RetrofitClient
public class RetrofitClient {
public static final String BASE_URL = "http://localhost";
public static Retrofit retrofit = null;
private RetrofitClient() {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(mClient)
.build();
}
OkHttpClient mClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer" + Preferences.getInstance().getToken())
}
})
public static synchronized Retrofit getInstance() {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
public Api getApi() {
return retrofit.create(Api.class);
}
}
您可以使用在您的应用程序运行时可用的应用程序上下文。从您的应用中获取 class:
public class MyApp extends Application {
private static MyApp instance;
@Override
public void onCreate() {
super.onCreate();
instance = this;
//other code
}
public static MyApp getInstance() {
return instance;
}
然后只需使用 MyApp.getInstance()
即可在您需要的地方获取上下文。通过这种方法,您可以实现您之前的想法,并在 RetrofitClient
class.
中获得 SharedPreferences
不要忘记将您的应用 class 添加到清单中。
更新:
您只创建了一次改造实例,因此如果您在拥有令牌时创建它 - 您将始终使用它,而应用程序仍然存在。
我认为,好的做法是在拦截器中检查令牌。像这样:
new Interceptor() {
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
if (tokenService.token == null) {
return chain.proceed(request);
} else {
return chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer" + tokenService.token).build());
}
}
}
另外,我不知道你的 tokenService 是如何工作的。但请记住,最好始终检查令牌的共享首选项,如果您在注销时清除它。因为您的 tokenService 可能会保留令牌字符串,即使它已在共享首选项中被清除。
我想在 Retrofit2
中使用 authorization
。我选择了 interceptor
方式,因为几乎所有方法都需要 authorization
,除了我正在获取令牌以进一步用于其他方法的方法。
我的问题是:我怎样才能做到这一点?
我将访问令牌存储在 SharedPreferences
中。我的第一个想法是:“我可以在我的 RetrofitClient
class 中检索它,并根据令牌是否为 null 或它是否具有值来创建合适的 Retrofit
实例 "(添加或不添加 .client()
。
不幸的是,这并不容易,因为需要 Context
才能获得偏好。
我不知道如何将它传递到 RetrofitClient
class 或如何进入它。
这是我的 RetrofitClient
class:
public class RetrofitClient {
public static final String BASE_URL = "http://localhost";
public static Retrofit retrofit = null;
private RetrofitClient() {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
//.client(getRequestHeader())
.build();
}
/*OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer" + )
}
})*/
public static synchronized Retrofit getInstance() {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
public Api getApi() {
return retrofit.create(Api.class);
}
}
我的 getRequestHeader()
是我之前设置超时的方法。
我想创建这样的实例:
private RetrofitClient() {
tokenService.token = null;
tokenService.readToken(ApplicationContext.getInstance());
if (tokenService.token == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
} else {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client) //I have interceptor here with access token
.build();
}
}
然后:
RetrofitClient.getInstance().create(Api.class).getToken()
//获取令牌
RetrofitClient.getInstance().create(Api.class).someMethod()
//当我得到Token
这是好方法吗?
只需在 RetrofitClient 或其他视情况添加 SharedPreferences 作为构造函数参数即可
您可以通过以下方式进行:
首先使用单例实例
创建首选项classPreferences
public class Preferences {
public static Preferences INSTANCE;
private final String PREFERENCE_FILE = "my_preferences";
public final String PREF_TOKEN = "pref_user_token";
private SharedPreferences mPrefs;
private SharedPreferences.Editor mEdit;
private Preferences() {
Application app = MyApplicationClass.getInstance();
mPrefs = app.getSharedPreferences(PREFERENCE_FILE, Context.MODE_PRIVATE);
mEdit = mPrefs.edit();
}
// Returns singleton instance
public static Preferences getInstance() {
if (INSTANCE == null)
INSTANCE = new Preferences();
return INSTANCE;
}
public String getToken() {
return Preferences.getInstance().mPrefs.getString(PREF_TOKEN, "");
}
public void saveToken(String value) {
mEdit.putString(PREF_TOKEN, value);
mEdit.apply();
}
}
然后在你的 RetrofitClient class 中改变如下:
RetrofitClient
public class RetrofitClient {
public static final String BASE_URL = "http://localhost";
public static Retrofit retrofit = null;
private RetrofitClient() {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(mClient)
.build();
}
OkHttpClient mClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer" + Preferences.getInstance().getToken())
}
})
public static synchronized Retrofit getInstance() {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
public Api getApi() {
return retrofit.create(Api.class);
}
}
您可以使用在您的应用程序运行时可用的应用程序上下文。从您的应用中获取 class:
public class MyApp extends Application {
private static MyApp instance;
@Override
public void onCreate() {
super.onCreate();
instance = this;
//other code
}
public static MyApp getInstance() {
return instance;
}
然后只需使用 MyApp.getInstance()
即可在您需要的地方获取上下文。通过这种方法,您可以实现您之前的想法,并在 RetrofitClient
class.
不要忘记将您的应用 class 添加到清单中。
更新: 您只创建了一次改造实例,因此如果您在拥有令牌时创建它 - 您将始终使用它,而应用程序仍然存在。 我认为,好的做法是在拦截器中检查令牌。像这样:
new Interceptor() {
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
if (tokenService.token == null) {
return chain.proceed(request);
} else {
return chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer" + tokenService.token).build());
}
}
}
另外,我不知道你的 tokenService 是如何工作的。但请记住,最好始终检查令牌的共享首选项,如果您在注销时清除它。因为您的 tokenService 可能会保留令牌字符串,即使它已在共享首选项中被清除。