【问题标题】:Caching contents of a page?缓存页面内容?
【发布时间】:2010-07-10 03:00:57
【问题描述】:

我正在生成如下页面内容:

// index.jsp
<%
    List<Horse> horses = database.getHorses();
    for (Horse it : horses) {
        %>
        <div><%= it.getName() %></div>
       <%
    }
%>

是否可以在jsp文件末尾抓取整个页面内容,并将其转储为String,如:

String page = this.getPrintWriter().toString();

我只是好奇这是否可能。我可能会尝试将页面缓存为字符串,但需要重写我的页面生成以在一个 StringBuilder 中构建所有内容,例如:

StringBuilder sb = new StringBuilder();
sb.append("<div>"); sb.append(it.getName()); sb.append("</div>");
...
<%= sb.toString() %>
String cached = sb.toString();

谢谢

【问题讨论】:

  • 为什么?你想用“缓存”值做什么?答案取决于此。
  • 我正在使用谷歌应用引擎,它有一个内存缓存 - 我可以获取整个页面内容的字符串值,并将其放入内存缓存中。下次用户请求该页面时,我可以立即从 memcache 中转储整个内容。我当然可以缓存单个 Horse 对象并重新生成内容,它至少可以让我免于访问数据库 - 只是不确定什么是更好的做法 - 谢谢
  • 是用户特定的内容吗? IE。数据特定于每个访问者。还是应用程序范围内的常量? IE。只需在 webapp 启动期间加载一次并永久使用而无需重新加载?
  • 是的,它是特定于每个用户的数据 - 每个用户将拥有不同的马匹 - 他们可以修改该列表,但不会经常发生 - 所以我认为它可能很酷只缓存整个页面内容。

标签: google-app-engine jsp servlets


【解决方案1】:

由于它是特定于用户的数据,因此您不能为此使用 GAE's memcache。这是一个应用程序范围的缓存。我只是将它存储在会话范围内。

HttpSession session = request.getSession();
List<Horse> horses = (List<Horse>) session.getAttribute("horses");
if (horses == null) {
    horses = database.getHorses();
    session.setAttribute("horses", horses);
}

也就是说,尽量避免使用 scriptlets。以上可以完美地在 Servlet 类中完成,您可以使用 JSTL c:forEach 显示它们,如下所示:

<c:forEach items="${horses}" var="horse">
    <div>${horse.name}</div>
</c:forEach>

仅调用PrintWriter#toString() 无法捕获生成的页面内容。 StringBuilder 的想法很有趣,但真的不值得。正如您提到的那样,缓存动态内容几乎没有什么好处。

在这种情况下,您在页面缓存方面所能做的最好的事情就是利用网络浏览器的默认任务来缓存 GET 请求。

另见

【讨论】:

  • 我可能会误解,但 gae 并不关心它是否是用户特定的数据——我只会把它放在一个唯一的键中,比如:cache.put(username+'_horses', stringOfHorses);。我觉得可以吗?是的,我需要停止使用脚本来生成页面。
  • 或者session.getId()获取的会话ID。毕竟,我不认为这是有益的。您可能会在缓存中复制Horse 对象,并且您仍然希望在会话到期时将其从缓存中删除,否则缓存可能会崩溃。缓存对应用程序范围的数据更有意义。例如。您想在下拉列表等中显示的常量值。您还可以在 webapp 启动期间将 all Horse 对象放在缓存中的 Map 中,并从那里而不是从数据库中获取它们。反过来,我只质疑从中检索 特定 Horse 对象的速度......
【解决方案2】:

我将创建一个 HttpServlet,它只从真实页面(任何类型的页面,也包括 JSP)中检索页面内容。然后缓存它。

下次用户发出相同的请求时,它会尝试从内存缓存中获取数据,如果存在,则仅检索内存缓存内容。 当然,您必须检查参数、用户 ID 等。这会改变缓存页面上的内容。

这样您还可以完全控制缓存大小(您可以在 PUT 期间设置缓存过期,限制缓存页数等)

顺便说一句.. 带有会话数据存储的answer 将不起作用!!。会话数据仅保留在单个服务器上。由于 appengine 在一些非常大的集群(许多机器)上运行,它不能确保来自同一个客户端的两个相同请求将由同一台机器提供服务 - 因此会话数据将无法访问!

当我尝试制作进度条时,我很难学到这一点;)

编辑 似乎会话现在正在与 appengine 一起使用,并且在所有服务器之间共享(正如谷歌所说,他们正在内部使用 memcache)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-05
    • 2014-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多