1

我创建了几乎在每个页面中都使用的文章复合组件。此 CC 从数据库加载数据并将其插入到视图中。要使用这个 CC,我只需要调用<cc:article id="article-id"/>,所以它使用起来非常简单。问题是我需要在每个请求上从数据库加载数据,所以这不是最好的解决方案。我想优化它,但我不知道如何。在我写下我必须解决这个问题的想法之前,让我们看看 cc 最重要的部分是什么样的:

这是CC

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" ...>

    <h:body>
        <cc:interface componentType="articleFacesComponent">
            <cc:attribute name="articleId" required="true" />
            <cc:attribute name="editable" type="boolean" default="false" required="false" />
            <cc:attribute name="styleClass" default="article" required="false" />
        </cc:interface>
        <cc:implementation>
            <h:outputStylesheet library="cc" name="js/article.css" />
            <div class="#{cc.attrs.styleClass}">
                ...
                    <!-- here I load article from FacesComponent -->
                    <h:outputText value="#{cc.article.text}" escape="false" />
                ...
            </div>
        </cc:implementation>
    </h:body>
</html>

这是 cc 使用的 FacesComponent

import entity.Article;
import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;
import javax.persistence.EntityManager;
import service.DatabaseManager;

@FacesComponent("articleFacesComponent")
public class ArticleFacesComponent extends UINamingContainer {

    private Article article;
    private EntityManager em;

    public Article getArticle() {
        if (article==null) {
            init();
        }
        return article;
    }

    private void init() {
        em = DatabaseManager.getInstance().em();
        Object idObj = getAttributes().get("articleId");
        if (idObj != null) {
            String id = String.valueOf(idObj);
            if (id != null) {
                article = em.find(Article.class, id);
                if (article == null) {
                    article = new Article(id);
                }
            }
        }
    }

}

首先我想写下这个解决方案有什么问题:

  1. 我需要在每个请求上从数据库加载数据
  2. FacesComponent 看起来很难看,因为我无法将托管 bean 注入其中,甚至无法调用 PostContruct。
  3. 我每次都getArticle()需要调用,因为 cc 属性在构造函数中不可见。init()

它应该如何工作?

  1. FacesComponent 不应从数据库加载数据。
  2. 我应该能够将托管 bean 注入 FacesComponent。可能吗?
  3. 我应该可以在 FacesComponent 中调用 PostContruct。

我有什么想法可以解决这个问题?

  1. 我认为我可以创建线程安全类,它将从数据库加载数据并将其存储在List. 这个解决方案的优点是我只会从 db 加载数据一次,但缺点是我需要将所有文章保存在内存中。现在我有大约 30 篇文章,所以它可以以这种方式工作,但将来可能有 300 或 3000 篇文章,所以它会浪费内存。
  2. 缓存视图。创建解决方案以创建静态视图并将它们存储在将加载它们的缓存目录中。也许 JSF 有一些动态视图的缓存解决方案?
4

1 回答 1

1

至于具体问题,JSF 实用程序库OmniFaces有一个<o:cache>组件,它允许您在确定的时间段内将组件生成的 HTML 输出缓存在会话中,甚至在特定键上的应用程序范围内。另请参阅展示页面

于 2013-04-26T11:48:43.717 回答