apipage java,了解AEM中的Java API最佳实践

了解Java API最佳实践

Adobe Experience Manager(AEM)构建于一个丰富的开放源码软件堆栈上,它公开了许多在开发过程中使用的Java API。 本文探讨了主要API,以及它们的使用时间和用途。

AEM基于4个主要Java API集构建。

Adobe Experience Manager (AEM)

产品抽象,如页面、资产、工作流等

Apache SlingWeb Framework

REST和基于资源的抽象,如资源、值映射和HTTP请求。

JCR(Apache Jackrabbit Oak)

数据和内容抽象,如节点、属性和会话。

OSGi (Apache Felix)

OSGi应用程序容器抽象,如服务和(OSGi)组件。

Java API首选项“经验法则”

一般规则是首选API/抽象以下顺序:

AEM

Sling

JCR

OSGi

如果AEM提供API,则首选它而非Sling、JCR和OSGi。 如果AEM不提供API,则优先Sling而非JCR和OSGi。

此顺序是一般规则,表示存在例外。 中断此规则的可接受理由有:

众所周知的例外,如下所述。

所需功能在更高级别的API中不可用。

在现有代码(自定义或AEM产品代码)的上下文中操作,该代码本身使用较不首选的API,而移动到新API的成本是不合理的。

与创建混合,使用较低级别的API更好。

AEM API

AEM API提供特定于按产品分类的使用案例的抽象和功能。

例如,AEM PageManager和Page API为AEM中表示网页的cq:Page节点提供抽象。

虽然这些节点可通过Sling API作为资源使用,而JCR API作为节点使用,但AEM API为常见用例提供抽象。 使用AEM API可确保产品和AEM的自定义和扩展之间的一致行为。

com.adobe.与com.day。 API

AEM API具有由以下Java包标识的包内首选项(按首选项顺序排列):

com.adobe.cq

com.adobe.granite

com.day.cq

com.adobe.cq 支持产品用例, com.adobe.granite 而支持跨产品平台用例,如工作流或任务(在产品之间使用:AEM Assets、站点等)。

com.day.cq 包含“原始”API。这些API解决了在Adobe获取[!DNL Day CQ]之前和/或之前存在的核心抽象和功能。 除非com.adobe.cq或com.adobe.granite提供(较新的)备选项,否则这些API是受支持的,不应避免。

Content Fragments和Experience Fragments等新抽象是在com.adobe.cq空间中构建的,而不是下面描述的com.day.cq。

查询API

AEM支持多种查询语言。 3种主要语言为JCR-SQL2、XPath和AEM 查询 Builder。

最重要的问题是在整个代码库中保持一致的查询语言,以降低理解的复杂性和成本。

所有查询语言都有效的性能用户档案,因为Apache Oak将它们传输到JCR-SQL2以进行最终查询执行,而与查询时间本身相比,转换到JCR-SQL2的时间可忽略不计。

首选的API是AEM 查询 Builder,它是最高级抽象,为查询构建、执行和检索结果提供了强大的API,并提供以下内容:

简单、参数化的查询构建(查询参数建模为映射)

OOTB预测支 持常见查询要求

可扩展的API,允许开发自定义查询谓词

注意

AEM QueryBuilder API会泄露ResourceResolver对象。 要减轻此漏洞,请遵循此代码示例。

Sling API

Apache Sling 是支持AEM的REST风格的Web框架。Sling 提供HTTP请求路由,将JCR节点建模为资源,提供安全上下文等。

Sling API具有为扩展而构建的额外优势,这意味着与扩展性较低的JCR API相比,使用API构建的应用程序的行为 Sling 更简单、安全。

Sling API的常用

JCR API

JCR(Java内容存储库)2.0 API是JCR实施规范的一部分(对于AEM,为Apache Jackrabbit Oak)。 所有JCR实施都必须符合并实施这些API,因此,它是与AEM内容交互的最低级API。

JCR本身是一个基于层次/树的NoSQL数据存储AEM用作其内容存储库。 JCR拥有大量受支持的API,从内容CRUD到查询内容。 尽管有这种强大的API,但与更高级别的AEM和Sling抽象相比,它们仍很少被青睐。

总是喜欢JCR API,而不是Apache Jackrabbit Oak API。 JCR API用于与JCR存储库​交互,而Oak API用于​实现 JCR存储库。

对JCR API的常见误解

虽然JCR是AEM内容存储库,但其API并非与内容交互的首选方法。 相反,您更喜欢AEM API(页面、资产、标记等) 或Sling Resource API,因为它们提供了更好的抽象。

注意

JCR API的会话和节点接口在AEM应用程序中的广泛使用是代码味。 请确保不应改用Sling API。

JCR API的常用

JCR观察(监听JCR事件)

创建深层节点结构

虽然Sling API支持创建资源,但JCR API在JcrUtils和JcrUtil中具有方便的方法,可加快创建深层结构的速度。

OSGi API

OSGi API与更高级别的API(AEM、Sling和JCR)之间几乎没有重叠,使用OSGi API的需求非常少,并且需要高级AEM开发专业知识。

OSGi与Apache Felix API

OSGi定义了所有OSGi容器必须实现和符合的规范。 AEM OSGi实施Apache Felix也提供了几个自己的API。

相对于Apache Felix API(org.apache.felix),首选OSGi API(org.osgi)。

OSGi API的常用

用于声明OSGi服务和组件的OSGi注释。

用于动态代码内取消/注册OSGi服务/组件的OSGi API。

当不需要条件式OSGi服务/组件管理时(通常情况下),最好使用OSGi DS 1.2注释。

规则的例外

以下是上述定义的规则的常见例外。

AEM Asset API

而com.day.cq资产API则为AEM资产管理用例提供了更多免费工具。

Granite Assets API支持低级资产管理用例(版本、关系)。

查询API

AEM QueryBuilder不支持某些查询函数,如subgenties、拼写检查和索引提示等其它不常用函数。 要查询这些函数,首选JCR-SQL2。

Sling Servlet注册

Sling 过滤器注册

有用的代码片段

以下是有用的Java代码片段,它们使用讨论的API说明常见用例的最佳实践。 这些片段还说明了如何从较不首选的API移动到较首选的API。

到Sling ResourceResolver的JCR会话

自动关闭Sling ResourceResolver

自AEM 6.2起,Sling ResourceResolver在try-with-resources语句中为AutoClosable。 使用此语法,不需要显式调用resourceResolver .close()。

@Reference

ResourceResolverFactory rrf;

...

Map authInfo = new HashMap();

authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, jcrSession);

try (ResourceResolver resourceResolver = rrf.getResourceResolver(authInfo)) {

// Do work with the resourceResolver

} catch (LoginException e) { .. }

手动关闭的Sling ResourceResolver

如果不能使用上述自动关闭技术,则必须手动关闭finally块中的ResourceResolver。

@Reference

ResourceResolverFactory rrf;

...

Map authInfo = new HashMap();

authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, jcrSession);

ResourceResolver resourceResolver = null;

try {

resourceResolver = rrf.getResourceResolver(authInfo);

// Do work with the resourceResolver

} catch (LoginException e) {

...

} finally {

if (resourceResolver != null) { resourceResolver.close(); }

}

JCR到Sling Resource的路径

Resource resource = ResourceResolver.getResource("/path/to/the/resource");

JCR节点到Sling Resource

Resource resource = resourceResolver.getResource(node.getPath());

Sling Resource 到AEM资产

建议的方法

DamUtil.resolveToAsset(..)根据需要,通过 dam:Asset 向上遍历树,解析位于“资产”对象下的任何资源。

Asset asset = DamUtil.resolveToAsset(resource);

替代方法

使资源适应资产需要资源本身作为dam:Asset节点。

Asset asset = resource.adaptTo(Asset.class);

Sling 资源至AEM页

建议的方法

pageManager.getContainingPage(..) 根据需要向上 cq:Page 走树,解析位于Page对象下的任何资源。

PageManager pageManager = resourceResolver.adaptTo(PageManager.class);

Page page = pageManager.getContainingPage(resource);

Page page2 = pageManager.getContainingPage("/content/path/to/page/jcr:content/or/component");

替代方法

使资源适应页面需要资源本身作为cq:Page节点。

Page page = resource.adaptTo(Page.class);

阅读AEM页面属性

使用Page对象的getter获取已知属性(getTitle()、getDescription()等) 和page.getProperties()以获取用于检索其他属性的[cq:Page]/jcr:content ValueMap。

Page page = resource.adaptTo(Page.class);

String title = page.getTitle();

Calendar value = page.getProperties().get("cq:lastModified", Calendar.getInstance());

阅读AEM资产元数据属性

资产API提供了从[dam:Asset]/jcr:content/metadata节点读取属性的简便方法。 请注意,这不是ValueMap,不支持第2个参数(默认值和自动类型转换)。

Asset asset = resource.adaptTo(Asset.class);

String title = asset.getMetadataValue("dc:title");

Calendar lastModified = (Calendar) asset.getMetadata("cq:lastModified");

读取Sling Resource属性

当属性存储在AEM API(Page, Asset)无法直接访问的位置(属性或相对资源)中时,Sling资源和ValueMaps可用于获取数据。

ValueMap properties = resource.getValueMap();

String value = properties.get("jcr:title", "Default title");

String relativeResourceValue = properties.get("relative/propertyName", "Default value");

在这种情况下,AEM对象可能必须转换为Sling Resource以有效定位所需的属性或子资源。

AEM页至Sling Resource

Resource resource = page.adaptTo(Resource.class);

AEM资产到Sling Resource

Resource resource = asset.adaptTo(Resource.class);

使用Sling的ModifableValueMap写入属性

使用Sling的ModiableValueMap将属性写入节点。 这只能写入直接节点(不支持相对属性路径)。

请注意,对.adaptTo(ModifiableValueMap.class)的调用要求对资源具有写入权限,否则将返回null。

ModifiableValueMap properties = resource.adaptTo(ModifiableValueMap.class);

properties.put("newPropertyName", "new value");

properties.put("propertyNameToUpdate", "updated value");

properties.remove("propertyToRemove");

resource.getResourceResolver().commit();

创建AEM页面

在AEM中正确定义和初始化页面时,需要始终使用PageManager创建页面,就像使用页面模板一样。

String templatePath = "/conf/my-app/settings/wcm/templates/content-page";

boolean autoSave = true;

PageManager pageManager = resourceResolver.adaptTo(PageManager.class);

pageManager.create("/content/parent/path", "my-new-page", templatePath, "My New Page Title", autoSave);

if (!autoSave) { resourceResolver.commit(); }

创建Sling资源

ResourceResolver支持创建资源的基本操作。 创建更高级抽象时(AEM页面、资产、标记等) 使用各自经理提供的方法。

resourceResolver.create(parentResource, "my-node-name", new ImmutableMap.Builder()

.put("jcr:primaryType", "nt:unstructured")

.put("jcr:title", "Hello world")

.put("propertyName", "Other initial properties")

.build());

resourceResolver.commit();

删除Sling资源

ResourceResolver支持删除资源。 创建更高级抽象时(AEM页面、资产、标记等) 使用各自经理提供的方法。

resourceResolver.delete(resource);

resourceResolver.commit();

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值