@GET
方法的Web服务调用:@GET
@Path(value = "/user/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUserCache(@PathParam("id") String id, @Context HttpHeaders headers) throws Exception {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id", id);
SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
Cre8Mapper mapper = session.getMapper(Cre8Mapper.class);
// slow it down 5 seconds
Thread.sleep(5000);
// get data from database
User user = mapper.getUser(map);
if (user == null) {
return Response.ok().status(Status.NOT_FOUND).build();
} else {
CacheControl cc = new CacheControl();
// save data for 60 seconds
cc.setMaxAge(60);
cc.setPrivate(true);
return Response.ok(gson.toJson(user)).cacheControl(cc).status(Status.OK).build();
}
}
为了进行实验,在从数据库中获取数据之前,我会将当前线程放慢5秒。
当我使用Firefox Poster调用我的web服务时,在60秒内,第二次、第三次等等似乎要快得多,直到超过60秒。
然而,当我将URI粘贴到浏览器(Chrome)中时,它似乎每次都会减慢5秒。我真的很困惑这种技术究竟是如何进行缓存的。以下是我的问题:
- POSTER是否真的查看头部的
max-age
并决定何时获取数据? - 在客户端(Web、Android等)访问我的Web服务时,我需要检查头部然后手动执行缓存,还是浏览器已经自动缓存了数据?
- 有没有办法避免每次从数据库获取数据?我想我必须以某种方式将我的数据存储在内存中,但它可能会耗尽内存吗?
在这个教程JAX-RS caching tutorial中:
缓存实际上是如何工作的?第一行总是从数据库获取数据:
Book myBook = getBookFromDB(id);
那么它如何被认为是缓存的呢?除非代码不按照自上而下的顺序执行。
@Path("/book/{id}")
@GET
public Response getBook(@PathParam("id") long id, @Context Request request) {
Book myBook = getBookFromDB(id);
CacheControl cc = new CacheControl();
cc.setMaxAge(86400);
EntityTag etag = new EntityTag(Integer.toString(myBook.hashCode()));
ResponseBuilder builder = request.evaluatePreconditions(etag);
// cached resource did change -> serve updated content
if (builder == null){
builder = Response.ok(myBook);
builder.tag(etag);
}
builder.cacheControl(cc);
return builder.build();
}
TimeUnit.DAYS.toSeconds(1)
代替86400
。这样更容易阅读,而且无需进行解码努力。 ;) - fgeTimeUnit.SECONDS.sleep(5)
。 - fge