JCR API 或 Apache Sling

JCR API or Apache Sling

我读了很多文章,例如 JCR vs Apache Sling,但我对使用什么感到困惑。一些作者建议使用 JCR API 来优化性能,其余的则支持 Apache Sling,因为它的编写速度更快并且在长 运行 中更具可读性和可维护性。我有一些问题:

我认为 Maciej Matuszewski 在他的演讲中已经用尽了这个主题 JCR, Sling or AEM? Which API should I use and when?

在大多数情况下,建议使用更高级别的 Apache Sling API,而在需要考虑性能时则需要 JCR。然而,重要的是要知道这两种情况之间的界限。

Maciej 注意到在不考虑任何缓存的情况下打开常规 AEM 页面大约有 1 毫秒的差异。在这种情况下,完全没有必要关注性能。相反,我们应该专注于编写可读、可理解、减少到最低限度并重用已经存在的 APIs、框架、util 类 的代码,这些代码已经被适当的单元测试和同行评审覆盖,而不是从头开始重新发明轮子。基于此,我们也应该更喜欢 AEM 层而不是 Sling 层。

根据我的经验,我认为JCR应该在很少的场景下使用,主要是遍历CRX数据库的大量数据,并且无法通过任何搜索实现API。

所以区别就像使用 C# 或 C++ 作为计算机游戏开发的编程语言 - 在某些情况下,它足以保持更高 API 为了开发方便,但在某些情况下它是要求降低并开始使用 C++ 指针。

但是,最重要的是不要在您的实现中混合这两个抽象层。

从一个非常典型的答案开始,'IT DEPENDS'

请考虑以下场景以供您理解:

场景一:读取当前资源所在页面的标题。

方法 1: 利用出色的 Sling API 处理所有可用上下文 objects,例如 currentPage、资源、pageManager、wcmmode 以及 Java 控制器中的更多(Sling 模型/WCMUSe class)。

// get the page that contains this resource.
// If the resource is a page the resource is returned. Otherwise it 
// walks up the parent resources until a page is found.
Page page = pageManager.getContainingPage(resource);

// Check if the returned page object isn't null
if(page != null){
    return page.getTitle();
}

方法 2: 使用 JCR API 的:

// assign the current resource node to parent Node to check 
// if the current resoure in itself is a page
Node parentNode = currentNode;
while (parentNode.getProperty("jcr:PrimaryTpe").getString() != "cq:Page" ){
    parentNode = parentNode.getParent();
}
// The page Title
String pageTitle = null;

// find the jcr:content node of the page and return the 
// jcr:title property of that node
if(parentNode.hasNode("jcr:content"){
    Node jcrContentNode = parentNode.getNode("jcr:Content");
    pageTitle = jcrContentNode.getProperty("jcr:title").getValue().getString();
} 
 return pageTitle;

In this scenario, obviously the Sling API's win by a huge margin on the ease of access and usability. I have never experienced any performance issue with the Sling APIs in comparison to the JCR APIs.

场景2:将您网站的第一级页面节点(考虑/content/mywebsite/en为0级)的标题更改为大写字母。

方法: 在需要对 JCR 存储库进行某些 one-time 更改的情况下,您应该使用 JCR API创建一个独立的 Java 应用程序来执行此类任务,而不是创建一个不必要的组件、它的控制器、一个不必要的页面来放置该组件,然后在控制器中使用 Sling API 来执行这些任务。

//Create a connection to the CQ repository running on local host 
Repository repository = JcrUtils.getRepository("http://localhost:4502/crx/server");

//Create a Session
Session session = repository.login( new SimpleCredentials("username", "password".toCharArray()),"crx.default");

//Create a node that represents the root node
Node root = session.getRootNode(); 

// Get the level ZERO node
Node homepageNode = root.getNode("/content/mywebsite/en");

NodeIterator iter = homePageNode.getNodes;
while(iter.hasNext){
    // if next node is of primarty type cq:Page
    // get its jcr:content node and 
    // set its jcr:title property to uppercase letters.
}

Rule of Thumb:

If you want access to your AEM repository from within the AEM application use Sling APIs over JCR APIs they are:

  1. higher APIs than JCR (have a lot of predefined methods to do a lot of work)
  2. provide access to all the Global Context objects inside the controller
  3. very easy to use

but in case if you need to accces your repository for large scale opertaions, (generally one time changes) choose to work with a standalone Java application using the JCR APIs.