Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java REST方法-执行一个";普通的;方法调用优先于其他方法_Java_Android_Rest_Asynchronous_Retrofit - Fatal编程技术网

Java REST方法-执行一个";普通的;方法调用优先于其他方法

Java REST方法-执行一个";普通的;方法调用优先于其他方法,java,android,rest,asynchronous,retrofit,Java,Android,Rest,Asynchronous,Retrofit,我有一个android应用程序,可以调用RESTAPI。restapi由JWT保护,当用户登录到应用程序时,我获得了android的令牌。令牌将在60分钟后过期 在我的android应用程序中,我有不同的类,它们总共包含50-60个REST调用。android应用程序正在使用改造连接到这些REST方法。我有一些方法在执行另一个后需要工作,这些方法在第一个方法的onResponse方法中 我编写了一个名为Token的特殊类,其中它set和get变量中的JWT令牌。每个REST调用都从这个类中获取令

我有一个android应用程序,可以调用
REST
API。restapi由
JWT
保护,当用户登录到应用程序时,我获得了android的令牌。令牌将在60分钟后过期

在我的android应用程序中,我有不同的类,它们总共包含50-60个REST调用。android应用程序正在使用
改造
连接到这些REST方法。我有一些方法在执行另一个后需要工作,这些方法在第一个方法的
onResponse
方法中

我编写了一个名为
Token
的特殊类,其中它
set
get
变量中的JWT令牌。每个REST调用都从这个类中获取令牌

无论如何,由于其余部分由
JWT
保护,因此我必须在50分钟后重新创建令牌。我首先要检查
token
类中的
token
变量是否即将过期,它有一个特殊的方法
whenWillExpire()
来告诉我令牌何时过期。如果是,则再次调用RESTAPI并获取新令牌

这种情况是,由于我无法判断在哪个REST调用上必须重新创建令牌,因此我必须在
任何
REST调用之前执行此令牌过期检查,并在调用所选REST方法之前获取新令牌(如果已过期)。例如,假设我有一个名为
renew()
的方法,该方法检查令牌并通过REST工作从服务器获取它。任何其他REST调用都应在执行
renew()
后运行<代码>续订()
应在每次REST调用请求时首先运行。下面是此方法的一个示例

private void renew(String token) {

if(token expired){
    Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
            .create();

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(RestCommon.URL)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();

GetNewToken endPoint = retrofit.create(GetNewToken.class);
Call<ResponseBody> call = endPoint.getNewToken();
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
         // Good. Now we have the token. Call other methods here.
      }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}); 
}
   else
     {
       //Not expired. Call other methods.
     }
   }
private void续订(字符串令牌){
如果(令牌已过期){
Gson Gson=new GsonBuilder()
.setDateFormat(“yyyy-MM-dd'T'HH:MM:ss”)
.create();
改装改装=新改装.Builder()
.baseUrl(restcomon.URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
GetNewToken端点=翻新.create(GetNewToken.class);
Call Call=endPoint.getNewToken();
call.enqueue(新回调(){
@凌驾
公共响应(响应、改装){
//很好。现在我们有了令牌。在这里调用其他方法。
}
@凌驾
失效时的公共无效(可丢弃的t){
t、 printStackTrace();
}
}); 
}
其他的
{
//未过期。请调用其他方法。
}
}

那么,在执行请求的方法之前,如何确保
renew()
在每个REST请求中运行?这个的最佳设计是什么?我有50-60个REST方法,用不同的名称复制上述代码并在其中添加其他REST调用肯定不是一个好模式。

定义所有API端点:

public interface MyApi {
    @GET("item/{id}")
    Call<Item> getItemById(@Path("id") String id, @Header("Authorization") String auth)

    @DELETE("item/{id}")
    Call<String> deleteItemById(@Path("id") String id, @Header("Authorization") String auth)

    @POST("auth")
    Call<String> getNewToken(@Field("token") String currentToken);// or other params needed by getNewToken

    //...etc
}
公共接口MyApi{
@获取(“项/{id}”)
调用getItemById(@Path(“id”)String id,@Header(“Authorization”)String auth)
@删除(“项/{id}”)
调用deleteItemById(@Path(“id”)String id,@Header(“Authorization”)String auth)
@发布(“授权”)
调用getNewToken(@Field(“token”)字符串currentToken);//或getNewToken所需的其他参数
//…等等
}
包装器类:

public class MyApiManager{ //?? chose other name if u want :)

    private MyApi myApi = null;
    private static MyApiManager instance = null;

    public MyApiManager getInstance(){
        if(instance == null){
            instance = new MyApiManager();
        }
        return instance;
    }

    private MyApiManager(){
        Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.host.name")
        //other setting before build() ...
        .build();

        myApi = retrofit.create(MyApi.class);
    }

    //-------- General methods, like check token expired...

    private boolean checkAndGetNewToken(){
        if(token expired){
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    //note here using myApi directly to avoid recursive calls for checkAndGetNewToken()
                    Response<String> response = myApi.getNewToken(token).execute();
                    Token.set(response);//update your token
                }//run()
            });
            t.start();
            t.join();
        }//token exp
        return true;
    }//checkToken

    //------ wrapper methods for each API endpoint

    public Call<Item> getItemById(String id) throws TokenExpiredException{
        checkTokenExpiration();
        return myApi.getItemById(id, "Authorization:Bearer "+Token.get());
    }

    public Call<Item> deleteItemById(String id) throws TokenExpiredException{
        checkTokenExpiration();
        return myApi.deleteItemById(id, "Authorization:Bearer "+Token.get());
    }

    public Call<Item> getNewToken(String currentToken) throws TokenExpiredException{
        checkTokenExpiration();
        return myApi.getNewToken(currentToken);
    }
}
public类myapimager{//?如果需要,请选择其他名称:)
私有MyApi MyApi=null;
私有静态MyApiManager实例=null;
公共MyApiManager getInstance(){
if(实例==null){
实例=新的MyApiManager();
}
返回实例;
}
私人物业经理(){
改装改装=新改装.Builder()
.baseUrl(“https://api.host.name")
//生成()之前的其他设置。。。
.build();
myApi=reformation.create(myApi.class);
}
//--------一般方法,如检查令牌过期。。。
私有布尔checkAndGetNewToken(){
如果(令牌已过期){
线程t=新线程(新的可运行线程(){
@凌驾
公开募捐{
//注意这里直接使用myApi来避免对checkAndGetNewToken()的递归调用
Response-Response=myApi.getNewToken(token.execute();
Token.set(response);//更新您的令牌
}//运行()
});
t、 start();
t、 join();
}//代币出口
返回true;
}//支票代币
//------每个API端点的包装器方法
公共调用getItemById(字符串id)抛出TokenExpiredException{
checkTokenExpiration();
返回myApi.getItemById(id,“Authorization:Bearer”+Token.get());
}
公共调用deleteItemById(字符串id)抛出TokenExpiredException{
checkTokenExpiration();
返回myApi.deleteItemById(id,“Authorization:Bearer”+Token.get());
}
公共调用getNewToken(字符串currentToken)抛出TokenExpiredException{
checkTokenExpiration();
返回myApi.getNewToken(currentToken);
}
}
用法示例:

public class SomeClass {
    public void someMethod(){
        MyApiManager.getInstance().getItem("102").enqueue(new Callback<Item>() {
            @Override
            public void onResponse(Response<Item> response, Retrofit retrofit) {
                callApiStageB(response.getBody().getId()); //?
            }

            @Override
            public void onFailure(Throwable t) {
                t.printStackTrace();
                //show a toast ...
            }
        });
    }

    public void callApiStageB(String id){
        MyApiManager.getInstance().deleteItemById(id).enqueue(new Callback<String>() {
            @Override
            public void onResponse(Response<String> response, Retrofit retrofit) {
                //....more nested api-calls, or do anything else
            }

            @Override
            public void onFailure(Throwable t) {
                t.printStackTrace();
                //show a toast ...
            }
        });
    }
}
公共类SomeClass{
公共方法(){
MyApiManager.getInstance().getItem(“102”).enqueue(新回调(){
@凌驾
公共响应(响应、改装){
callApiStageB(response.getBody().getId());/?
}
@凌驾
失效时的公共无效(可丢弃的t){
t、 printStackTrace();
//举杯。。。
}
});
}
public void callApiStageB(字符串id){
MyApiManager.getInstance().deleteItemById(id).enqueue(新回调()){
@凌驾
公共响应(响应、改装){
//..更多嵌套api调用,或执行其他操作
}
@凌驾
失效时的公共无效(可丢弃的t){
t、 printStackTrace();
//举杯。。。