假设我有以下使用@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
调用我的网络服务时,在 60 秒内,第 2 次、第 3 次调用等似乎要快得多,直到超过 60 秒。
但是,当我将 URI 粘贴到浏览器(Chrome)时,它似乎每次都会减慢 5 秒。而且我真的很困惑如何使用这种技术实际完成缓存。以下是我的问题:
- POSTER 是否真的查看标题
max-age
并决定何时获取数据? - 在客户端(web、android ....)中,当访问我的 web 服务时,我需要检查标头然后手动执行缓存还是浏览器已经缓存了数据本身?
- 有没有办法避免每次都从数据库中获取数据?我想我必须以某种方式将我的数据存储在内存中,但它可能会耗尽内存吗?
在本教程 中 JAX-RS 缓存教程:缓存实际上是如何工作的?第一行总是从数据库中获取数据:
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();
}