2014-11-02 107 views
0

我正在開發一個使用改進的休息客戶端。其餘服務器使用oauth作爲身份驗證。對於這個任務,我不必關心令牌過期。所以基本上我首先對令牌進行請求,然後將其附加到所有後續調用。 截至目前,我正在使用兩個類。一個獲取訪問令牌,另一個訪問另一個。我想我想合併這兩個......但我不知道該怎麼做。其餘客戶端設計決策

第一類只有一個方法需要用戶名和密碼以及改進的回調接口。我喜歡回調的簡單性,但希望以某種方式將其抽象化,以便在需要時可以輕鬆地將改造改爲其他。

public class RequestAccessToken implements IRequestAccessToken { 
    private String username; 
    private String password; 

    private IRestAPI client; 


    public RequestAccessToken() 
    { 
     RestAdapter restAdapter = new RestAdapter.Builder() 
       .setEndpoint(Config.ENDPOINT) 
       .build(); 
     client = restAdapter.create(IRestAPI.class); 
    } 

    @Override 
    public void requestAccessToken(String username, String password, Callback callback) { 
     String grantType = Config.grantType; 
     String clientId = Config.clientId; 
     String clientSecret = Config.clientSecret; 

     client.getAccessToken(grantType, username, password, clientId, clientSecret, callback); 
    } 
} 

第二類將訪問令牌作爲構造函數參數並將其附加到所有http請求。

public class RestClient implements IRestClient { 
    private static final String TAG = RestClient.class.getSimpleName(); 
    private IRestAPI client; 

    public RestClient(final String accessToken) 
    { 
     RequestInterceptor requestInterceptor = new RequestInterceptor() 
     { 
      @Override 
      public void intercept(RequestFacade request) { 
       request.addHeader("Authorization", "Bearer " + accessToken); 
      } 
     }; 

     RestAdapter restAdapter = new RestAdapter.Builder() 
       .setEndpoint(Config.ENDPOINT) 
       .setRequestInterceptor(requestInterceptor) 
       .build(); 
     client = restAdapter.create(IRestAPI.class); 
    } 

    @Override 
    public List<User> requestUsers() { 
     return client.requestUsers(); 
    } 

    @Override 
    public List<Soemthing> requestSomething() { 
     return client.requestSomething(); 
    } 

    @Override 
    public List<SoemthingElse> requestSomethingElse() { 
     return client.requestSomethingElse(); 
    } 
} 

我會喜歡一些輸入和建議如何更好地做到這一點,也許合併兩個類。我正在考慮使RequestAccessToken的requestAccessToken方法成爲RestClient類的靜態成員。至少會合並這兩個班級。但我使用工廠來創建RestClient,如果我在我的代碼中聲明瞭一個靜態方法,我會使用緊密耦合...建議?

回答

0

在討論這個地方後,我想出了以下代碼。

public class RestClient implements IRestClient { 
    private static final String TAG = RestClient.class.getSimpleName(); 
    private IRestAPI client; 
    private String username; 
    private String password; 
    private RequestAccessToken requestAccessToken; 
    private Access access; 

    private static RestClient singleton; 

    // TODO: use Dagger 
    public static RestClient getInstance() 
    { 
     if(singleton == null) 
     { 
      singleton = new RestClient(); 
     } 
     return singleton; 
    } 

    /** 
    * Access declared as private to prevent instantiation outside of this class. 
    */ 
    private RestClient() 
    { 
     requestAccessToken = new RequestAccessToken(); 
    } 

    /** 
    * Request an access token. 
    * 
    * @return A string containing the access token 
    */ 
    public String requestAccessToken(String username, String password) 
    { 
     this.username = username; 
     this.password = password; 
     this.access = requestAccessToken.requestAccessToken(username, password); 
     return this.access.getAccess_token(); 
    } 

    /** 
    * Wrapper for {@link #requestAccessToken(String, String) requestAccessToken} 
    * @return 
    */ 
    public String requestAccessToken() 
    { 
     if(username == null || password == null) { 
      throw new IllegalArgumentException("missing user/pass"); 
     } 
     return requestAccessToken(username, password); 
    } 

    /** 
    * Eventually we want to look at Access.getExpires_in() and return weather or not the token is 
    * expired. 
    * 
    * @return value indicating weather or not the token is expired. 
    */ 
    public boolean isAccessTokenExpired() 
    { 
     return false; 
    } 

    /** 
    * Return an instance of a rest client with a valid access token. 
    * @return 
    */ 
    private IRestAPI getClient() 
    { 
     if(access == null) 
     { 
      requestAccessToken(); 
     } 
     if(isAccessTokenExpired()) 
     { 
      // Refresh token 
     } 
     if(client == null) { 
      RequestInterceptor requestInterceptor = new RequestInterceptor() { 
       @Override 
       public void intercept(RequestFacade request) { 
        request.addHeader("Authorization", "Bearer " + access.getAccess_token()); 
       } 
      }; 

      RestAdapter restAdapter = new RestAdapter.Builder() 
        .setEndpoint(Config.ENDPOINT) 
        .setLogLevel(RestAdapter.LogLevel.FULL) 
        .setRequestInterceptor(requestInterceptor) 
        .build(); 
      client = restAdapter.create(IRestAPI.class); 
     } 
     return client; 
    } 

    /** 
    * Login to the api and get a access token. 
    * 
    * @param username 
    * @param password 
    */ 
    @Override 
    public void login(String username, String password) 
    { 
     Log.d(TAG, "login"); 
     requestAccessToken(username, password); 
    } 

    /** 
    * Request a list of organizations. 
    * @return List of Organizations. 
    */ 
    @Override 
    public List<Organization> requestOrganizations() { 
     Log.d(TAG, "requestOrganizations"); 
     // TODO: error handling 
     // TODO: caching... which isn't http 
     return getClient().requestOrganizations(); 
    } 

    // Add more api requests here 

} 
+0

當然,僅查看訪問令牌的到期日期是不夠的。萬一令牌過期,該類應處理從服務器返回的錯誤消息...但它不會。 – user672009 2014-11-06 11:42:11