我正在考虑引入某种缓存机制(比如HTML5本地存储),以尽可能避免频繁的RPC调用。我想得到关于如何在下面的代码中引入缓存的反馈,而不需要更改太多的体系结构(比如使用gwt-dispatch)。
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的最大可用存储大小是多少?浏览器如何管理不同应用程序/URL的LocalStorage?任何指针都将不胜感激。
发布于 2012-07-30 13:55:40
我建议添加一个处理缓存的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);
});
}
}
}当然,这是一个粗糙的示例,您必须改进代码以使其可靠。
发布于 2012-07-30 14:05:12
我确实花了很长时间来决定是否使用散列映射来缓存结果。
我的策略不是使用单例hashmap,而是一个存储静态缓存实例的单例通用对象类。我看不出为什么要加载一个哈希树分支级别过高的单个哈希图。
减少散列解析的数量
如果我知道我正在处理的对象是Employee、Address、Project,我将创建三个静态散列
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的散列中。只需创建静态实例
Employee CurrentEmployee, NextEmployee;这将完全避免需要任何散列解析。
避免污染全局命名空间
如果可能,将它们保留为类实例,而不是静态实例,以避免污染全局命名空间。
为什么要避免污染全局名称空间呢?因为,由于全局名称空间的混乱,多个类可能会无意中使用相同的名称,从而导致数不清的bug。
将缓存保持在离预期或使用位置最近的位置
如果可能,如果缓存主要用于某个类,请将缓存保留为该类中的类实例。并为另一个类需要从该缓存中获取数据的任何罕见实例提供eventbus事件。
这样你就会有一个可预期的模式
ZZZManager.getZZZ(id);在可能的情况下完成缓存,
否则/并通过提供putter和getter将其私有化。不要允许另一个类无意中重新实例化缓存,特别是如果有一天您的类变成了一个通用的实用程序库。另外,putter和getter有机会验证请求,以避免请求清除缓存或将应用程序推入异常,方法是直接向缓存提供缓存无法处理的键或值。
将这些原则转换为Javascript本地存储
GWT页面上写着
明智地使用命名约定可以帮助处理存储数据。例如,在名为MyWebApp的web应用程序中,与名为MyWebApp的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时将其直接写入到存储中呢?
内存约束-
我不能自称是这个问题的专家,但我预测hashmap的答案是浏览器上操作系统限制的最大内存。减去浏览器、插件和javascript等开销已经消耗的所有内存。
对于HTML5本地存储,GWT页面上写着
"LocalStorage:每个浏览器每个应用程序5MB。根据HTML5规范,用户可以在需要时增加此限制;但是,只有少数浏览器支持此限制。“
"SessionStorage:仅受系统内存的限制“
发布于 2012-07-31 00:18:44
由于您使用的是gwt-dispath,因此这里的一个简单解决方案是将gwt-dispath响应对象作为Map中的键对请求对象进行缓存。它很容易实现,而且类型不可知。您需要重写Request - equals()方法来查看请求是否已经在缓存中。如果是,则从缓存返回响应,否则调用服务器。
如果您所需要的只是会话缓存中的性能,那么IMO - LocalStorage在这里不是必需的。本地存储只是离线应用程序的必备项。
你可以看看这个- http://turbomanage.wordpress.com/2010/07/12/caching-batching-dispatcher-for-gwt-dispatch/
https://stackoverflow.com/questions/11714694
复制相似问题