2012-07-30 59 views
2

我正在考慮引入某種緩存機制(如HTML5本地存儲)以儘可能避免頻繁的RPC調用。我想獲得有關如何在下面的代碼塊中引入緩存而不改變體系結構(如使用gwt-dispatch)的反饋。我能想到的來處理這個爲GWT RPC異步調用啓用緩存

void getData() { 

    /* Loading indicator code skipped */ 

    /* Below is a gwt-maven plugin generated singleton for SomeServiceAsync */ 
    SomeServiceAsync.Util.getInstance().getDataBySearchCriteria(searchCriteria, new AsyncCallback<List<MyData>>() { 

     public void onFailure(Throwable caught) { 
      /* Loading indicator code skipped */ 
      Window.alert("Problem : " + caught.getMessage()); 
     } 

     public void onSuccess(List<MyData> dataList) { 
      /* Loading indicator code skipped */ 
     } 
    }); 
} 

一種方法是有一個自定義MyAsyncCallback類中定義的onSuccess/onFailure處方法,然後做這樣的事情 -

void getData() { 

    AsyncCallback<List<MyData>> callback = new MyAsyncCallback<List<MyData>>; 

    // Check if data is present in cache 
    if(cacheIsPresent) 
     callback.onSuccess(dataRetrievedFromCache); 
    else 
    // Call RPC and same as above and of course, update cache wherever appropriate 
} 
從這個

除此之外,我有一個更多的問題。 LocalStorage適用於流行瀏覽器的最大存儲容量是多少?瀏覽器如何管理LocalStorage以適用於不同的應用程序/ URL?任何指針將不勝感激。

回答

2

我建議添加一個處理緩存的delegate class。代表類可能如下所示:

public class Delegate { 

    private static SomeServiceAsync service = SomeServiceAsync.Util.getInstance(); 

    private List<MyData> data; 

    public static void getData(Callback callback) { 
    if (date != null) { 
     callback.onSuccess(data); 
    } else { 
     service.getData(new Callback() { 
     public onSuccess(List<MyData> result) { 
      data = result; 
      callback.onSuccess(result); 
     }); 
    } 
    } 

} 

當然,這是一個粗略的示例,您必須完善代碼以使其可靠。

1

我花了很長時間來決定使用散列映射來緩存結果。

我的策略是不使用單例散列表,而是存儲緩存的靜態實例的單例公共對象類。我沒有看到加載具有過多級別的hashtree分支的單個hashmap的原因。

降低哈希分辨率

的金額。如果我知道,我處理的對象是員工,地址,項目,我將創建三個靜態哈希

final static private Map<Long, Employee> employeeCache = 
    new HashMap<Long, Employee>(); 
final static private Map<Long, Address> addressCache = 
new HashMap<Long, Address>(); 
final static private Map<String name, Project> projectCache = 
new HashMap<String name, Project>(); 

public static void putEmployee(Long id, Employee emp){ 
    employeeCache.put(id, emp); 
} 
public static Employee getEmployee(Long id){ 
    return employeeCache.get(id); 
} 

public static void putEmployee(Long id, Address addr){ 
    addressCache.put(id, addr); 
} 
public static Address getEmployee(Long id){ 
    return addressCache.get(id); 
} 

public static void putProject(String name, Address addr){ 
    projectCache.put(name, addr); 
} 
public static Address getProject(String name){ 
    return projectCache.get(name); 
} 

把它全部一張地圖會很毛茸茸。有效訪問和存儲數據的原則是 - 您確定的關於數據的信息越多,就越應該利用您擁有的信息來分離數據。它會降低訪問數據所需的散列分辨率級別。更不用說所有需要完成的風險和不確定類型的演員。

避免散列如果你能

如果你知道你總是有CurrentEmployee和NextEmployee, 避免將其儲存在員工的哈希值的一個值。只需創建靜態實例

Employee CurrentEmployee, NextEmployee; 

這樣可以避免需要任何散列分辨率。

避免污染全局命名空間

如果可能的話,讓他們爲類的實例,而不是靜態的情況下,爲了避免污染全局命名空間。

爲什麼要避免污染全局命名空間?因爲,由於全局名稱空間混淆,多於一個類會無意中使用相同的名稱,導致無數的錯誤。

保持高速緩存最近的地方,預計或使用

如果可能的話,如果緩存主要是針對某一類,保持高速緩存爲類中的一個類實例。併爲其他類需要從該緩存中獲取數據的罕見實例提供事件總線事件。

所以,你將有一個可預期的模式

ZZZManager.getZZZ(id); 

敲定如果可能的話緩存,

否則/並提供推杆和getter私有化了。不要讓另一個類無意中重新實例化緩存,特別是如果有一天你的類變成了一個通用實用程序庫。另外,推杆和getter有機會驗證請求,以避免請求消除緩存或通過直接使用緩存無法處理的鍵或值直接呈現緩存將應用程序推入Exception。

把這些原則爲JavaScript本地存儲

GWT的頁面說

明智地使用命名約定的可以處理存儲數據的幫助。例如,在名爲MyWebApp的Web應用程序中,與名爲Stock的UI表中的行關聯的鍵值數據可能具有以MyWebApp.Stock爲前綴的鍵名稱。

因此,補充你們班的HashMap,用比較簡陋代碼,

public class EmployeePresenter { 
    Storage empStore = Storage.getLocalStorageIfSupported(); 
    HashMap<Long, Employee> employeeCache; 

    public EmployeePresenter(){ 
    if (empStore==null) { 
     employeeCache = new HashMap<Employee>(); 
    } 
    } 

    private String getPrefix(){ 
    return this.getClass()+".Employee"; 
    //return this.getClass().getCanonicalName()+".Employee"; 
    } 

    public Employee putEmployee(Long id, Employee employee) 
    if (empStore==null) { 
     stockStore.setItem(getPrefix()+id, jsonEncode(employee)); 
     return; 
    } 
    employeeCache.put(id, employee); 
    } 

    public Employee getEmployee(Long id) 
    if (empStore==null) { 
     return (Employee) jsonDecode(Employee.class, stockStore.getItem(getPrefix()+id)); 
    } 
    return employeeCache(id); 
    } 
} 

因爲,在localstore是基於字符串而已,我假設你會寫自己的JSON編碼解碼器。另一方面,爲什麼不在收到回調的時候直接將json寫入商店呢?

內存限制?

我不能說這個問題的專業知識,但我預測hashmaps的答案是瀏覽器上操作系統限制的最大內存。減去瀏覽器已經消耗的所有內存,插件和JavaScript等等。 。

對於HTML5本地存儲的GWT頁說

「的localStorage:每瀏覽應用程序5MB根據HTML5規範,在需要時可以將此限制增加了用戶;然而,只有少數的瀏覽器支持此「。

「的sessionStorage:只有通過系統內存限制」由於您使用GWT-dispath這裏一個簡單的解決方案是緩存GWT-調度響應對象

+0

HTML5本地存儲在常規瀏覽器緩存中保存的數據以字符串形式加密。這不是安全的存儲。它不應該用於敏感數據,如社會安全號碼,信用卡號碼,登錄憑證等等。 – 2012-07-30 07:06:53

0

agains請求對象作爲一個地圖的關鍵。它易於實現和類型不可知。您將需要重寫Request-equals()方法以查看請求是否已經在緩存中。如果是,則返回緩存的響應,否則通過調用訪問服務器。

IMO - localStorage的是這裏不是必要的,如果你需要的是在性能會話緩存。本地存儲只適用於離線應用程序。

,你可以看看這個 - http://turbomanage.wordpress.com/2010/07/12/caching-batching-dispatcher-for-gwt-dispatch/

+0

正如我在問題中提到的,我*不*探索gwt-dispatch。 – Swapnil 2012-07-30 18:04:23

+0

即使沒有gwt-dispatch,你也可以很好地將該方法應用於你的代碼。在這種情況下,使用HashMap將searchCriteria對象存儲爲key,將ListData對象存儲爲值。這種方法非常通用,並且可以很好地緩存各種類型的數據請求與結果。您可以選擇使用您自己的Cacheable vs. Result接口來創建通用系統。 – Gautam 2012-07-30 18:44:35

+0

是的,但這個問題不是關於如何設計/實現緩存。這更多關於阿德里安。 B回答。不管怎麼說,還是要謝謝你。 – Swapnil 2012-08-02 04:55:17