存储App Engine分页的光标

时间:2012-10-09 21:43:04

标签: google-app-engine google-cloud-datastore

我正在尝试使用App Engine的RPC和GWT(它是一个应用程序引擎连接项目)实现分页。

如何将RPC中的查询结果和Web安全游标对象传递给GWT客户端?

我见过使用servlet的例子,但我想知道如何在没有servelt的情况下做到这一点。

我已经考虑过使用memcache将光标缓存在服务器上但是我不确定这是否合适或者应该使用什么作为密钥(会话标识符我会假设,但我不确定如何处理App Engine)。

示例项目的链接太棒了,我一直都找不到。

2 个答案:

答案 0 :(得分:2)

好的,所以最好的方法是将光标作为字符串存储在客户端上。

要做到这一点,你必须创建一个可传输的包装类,这样你就可以通过可以保存结果列表和游标字符串的RequestFactory将它传回客户端。为此,您可以创建一个普通的POJO,然后创建一个代理。

这是POJO的代码:

public class OrganizationResultsWrapper {

    public List<Organization> list;
    public String webSafeCursorString;

    public List<Organization> getList() {
        return list;
    }

    public void setList(List<Organization> list) {
        this.list = list;
    }

    public String getWebSafeCursorString() {
        return this.webSafeCursorString;
    }

    public void setWebSafeCursorString(String webSafeCursorString) {
        this.webSafeCursorString = webSafeCursorString;
    }
}

代理:

@ProxyFor(OrganizationResultsWrapper.class)
public interface OrganizationResultsWrapperProxy extends ValueProxy{

    List<OrganizationProxy> getList();
    void setList(List<OrganizationProxy> list);

    String getWebSafeCursorString();
    void setWebSafeCursorString(String webSafeCursorString);

}

设置你的服务和requestFactory分别使用POJO和代理

// service class method
@ServiceMethod
public OrganizationResultsWrapper getOrganizations(String webSafeCursorString) {
    return dao.getOrganizations(webSafeCursorString);
}

// request factory method
Request<OrganizationResultsWrapperProxy> getOrganizations(String webSafeCursorString); 

然后确保并运行RPC向导,以便验证过程运行,否则您将在服务器上收到请求上下文错误。

以下是我的数据访问类中的实现:

public OrganizationResultsWrapper getOrganizations(String webSafeCursorString) {
    List<Organization> list = new ArrayList<Organization>();
    OrganizationResultsWrapper resultsWrapper = new OrganizationResultsWrapper();

    Query<Organization> query = ofy().load().type(Organization.class).limit(50);

    if (webSafeCursorString != null) {
        query = query.startAt(Cursor.fromWebSafeString(webSafeCursorString));
    }

    QueryResultIterator<Organization> iterator = query.iterator();
    while (iterator.hasNext()) {
        list.add(iterator.next());
    }

    resultsWrapper.setList(list);
    resultsWrapper.setWebSafeCursorString(iterator.getCursor().toWebSafeString());

    return resultsWrapper;
}

答案 1 :(得分:0)

第二个选项是将webSafeCursorString保存在memcache中,正如您已经提到的那样。

我的想法是这样的:

  1. 客户端始终发送请求,如“getMyObjects(Object ... myParams,int maxResults,String clientPaginationString)”。 clientPaginationString是唯一创建的,如下所示

  2. 服务器接收请求并查看内存缓存,如果有关键clientPaginationString的webSafeCursorString

    1. 如果服务器什么都找不到,他会创建查询并将webSafeCursorString保存到memcache中,并将clientPaginationString作为键。 - &GT;返回结果

    2. 如果服务器找到webSafeCursorString,则用它重新启动查询并返回结果

  3. 问题是如何清理memcache以及如何查找唯一的clientPaginationString:

    唯一的clientPaginationString应该是当前UserId +当前查询的参数+ timestemp。这应该工作得很好!

    我真的想不出如何清理memcache的简单方法,但我认为我们根本不需要清理它。 我们可以将所有webSafeCursorStrings和timestemps + params + userid存储在一个包含地图的WebSafeCursor-Class中,并将所有这些存储在memcache中...并在一段时间内清除这些类(时间戳早于...)。

    我能想到的一个改进是使用在服务器上创建的密钥(userSessionId + servicename + servicemethodname + params)将webSafeCursorString保存在内存缓存中。但是,重要的是客户端发送信息,如果他对新查询感兴趣(memcache被覆盖)或想要下一个分页结果(从memcache获取webSafeCursorString)。重新加载页面应该工作。浏览器中的第二次点击是我认为的问题......

    你会说什么?