Caching 在ServerResource发送的表示上设置ETAG/LastModified

Caching 在ServerResource发送的表示上设置ETAG/LastModified,caching,restlet,etag,Caching,Restlet,Etag,我知道我可以在Representation/Repre上设置ETAG和LastModified属性​句子信息。 但我有一个简单的资源实现如下: public class AccountServerResource extends ServerResource implements AccountResource { private static Logger log = Logger.getLogger(Acc​ountServerResource.c​lass.getName());

我知道我可以在Representation/Repre上设置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;
    }   
}
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));
    }
}
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/LastModified标记

这里的推荐做法是什么

---更新---

我尝试了这种方法,但运气不好:

@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;
}
@覆盖
公共帐户检索(){
User User=getClientInfo().getUser();
AccountDAO=新的AccountDAO(user.getN​amespace());
AccountDAO=新AccountDAO();
Account ret=dao.getAccountByEmai​l(user.getEm)​ail());
日志信息(“已检索”+ret);
设置事件(新的StrongEtagCallback​(ret));​
返回ret;
}
StrongEtagCallback的实现如下:

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;
    }   
}
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));
    }
}
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;
}
公共类StrongEtagCallback实现统一{
私有静态SimpleDataFormat df=新SimpleDataFormat(“dd​MMYYYYHMMSSSS”);
私有域资源d;
公共StrongEtagCallback(T域资源){
d=域资源;
}
@凌驾
公共无效句柄(请求、响应){
字符串eTag=d.getClass().getSimpleName()+“-”+d.getId()+“-”+df.format(d.getLastModified());
response.getEntity().setTag(新标记(eTag,false));
}
}
我的所有实体都实现DomainResource,这要求它们具有ID和LastModified日期

但它不起作用。我真的很期待这个工作,它是非常优雅的


不过,正在调用StrongEtagCallback,即实体上的ETAG集合服务器端。我的Wireshark或GWT客户端在响应的响应上看到一个E-TAG头。现在深入研究。

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

为处理的每个调用创建一个ServerResource实例,并 一次只能由一个线程访问

因此,实现如下所示:

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;
    }   
}
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));
    }
}
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;
}

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

在我自己研究这个问题时,我注意到了一个由koma在Restlet讨论板上发起的项目,其中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;
}