在ServerResource发送的Representation上设置ETAG / LastModified

时间:2012-01-26 08:32:44

标签: caching restlet etag

我知道我可以在Representation / Repre sentationInfo上设置ETAG和LastModified属性。 但我有一个像这样实现的简单资源:

public class AccountServerResource extends ServerResource implements AccountResource {

    private static Logger log = Logger.getLogger(Acc​ountServerResource.c​lass.getName());

    @Override
    public Account retrieve() {
        User user = getClientInfo().getUser();
        AccountDAO dao = new AccountDAO();
        Account ret = dao.getAccountByEmai​l(user.getEm​ail());
        log.info("retrieved " + ret);
        // getResponse().getEntity() == null at this point !!!
        // ---> cannot do this : getResponse().getEntity().setModificationDate(ret.getLastMod​ified());
        return ret;
    }   
}

此时此表示尚未附加到回复中。 何时/如何设置ETAG / LastModified标签?

这里的推荐做法是什么?

--- --- UPDATE

我没有运气就试过这种方法:

@Override
public Account retrieve() {
        User user = getClientInfo().getUser();
    AccountDAO dao = new AccountDAO(user.getN​amespace());
        AccountDAO dao = new AccountDAO();
        Account ret = dao.getAccountByEmai​l(user.getEm​ail());
    log.info("retrieved " + ret);
    setOnSent(new StrongEtagCallback​<Account>(ret));​
    return ret;
}

像这样执行StrongEtagCallback:

public class StrongEtagCallback<T extends DomainResource> implements Uniform {

    private static SimpleDateFormat df = new SimpleDateFormat("dd​MMyyyyHHmmssSSS");
    private DomainResource d;

    public StrongEtagCallback(T domainResource) {
        d = domainResource;
    }

    @Override
    public void handle(Request request, Response response) {
        String eTag = d.getClass().getSimpleName() + "-" + d.getId() + "-" + df.format(d.getLastModified());
        response.getEntity().setTag(new Tag(eTag, false));
    }
}

我的所有实体都实现了DomainResource,要求它们拥有ID和LastModified日期。

但它不起作用。我真的希望这个有用,非常优雅!

正在调用StrongEtagCallback,ETAG在实体上设置服务器端。我的Wireshark和我的GWT客户端在响应的响应中看到了E-TAG标头。现在潜水更深。

2 个答案:

答案 0 :(得分:2)

在我自己研究这个问题时,我注意到在Restlet讨论板上由koma发起的parallel thread,其中Tim Peierls提供了另一种更好的解决方案,即覆盖Resource.toRepresentation()。

正如koma在该线程中指出的那样,覆盖ServerResource.handle()导致条件匹配失败(我不确定为什么?),因此这种方法存在问题。

Tim Peierls提供的覆盖代码示例:

@Override public Representation toRepresentation(Object source, Variant target) {
    Representation rep = super.toRepresentation(source, target);
    if (source instanceof HasLastModified) {
        HasLastModified hlm = (HasLastModified) source;
        rep.setModificationDate(hlm.getLastModified());
    }
    if (source instanceof HasEtag) {
        HasEtag he = (HasEtag) source;
        rep.setTag(he.gettag());
    }
    return rep;
}

答案 1 :(得分:1)

最终的解决方案是使返回域实体成为局部变量并覆盖ServerResource的handle()方法。这是安全的,因为javadoc声明:

  

为每个处理的调用创建一个ServerResource实例   一次只能访问一个帖子

所以实现如下:

private Account ret = null;

@Override
public Account retrieve() {
    User user = getClientInfo().getUser();
    AccountDAO dao = new AccountDAO();
    ret = dao.getAccountByEmail(UserServiceFactory.getUserService().getCurrentUser().getEmail());
    // getResponse().getEntity().setModificationDate(ret.getLastModified());
    // lastModified = ret.getLastModified();
    log.info("retrieved " + ret);
    //setOnSent(new StrongEtagCallback<Account>(ret));
    return ret;
}

@Override
public Representation handle() {
    Representation representation = super.handle();
    if (ret != null) {
        new StrongEtagCallback<Account>(ret).handle(getRequest(), getResponse());
    }
    return representation;
}

现在发送了ETAG标题:

HTTP/1.1 200 OK
Content-Type: application/x-java-serialized-object+gwt; charset=UTF-8
ETag: "Account-104-27012012003721199"
Date: Thu, 26 Jan 2012 23:44:32 GMT
Accept-Ranges: bytes
Server: Restlet-Framework/2.1rc1
Transfer-Encoding: chunked

PS:我的第一个设置回调setOnSent的解决方案在响应提交后被激活,这就是为什么这个解决方案不起作用的原因。我实际上期望一个类似的钩子或某种有点setNext() Restlet来进行后处理。毕竟,回调实现了Uniform接口。 IMO,这将更适合Restlet的整体架构。