Show Menu
主题×

HTL Java Use-API

The HTML Template Language (HTL) Java Use-API enables an HTL file to access helper methods in a custom Java class through data-sly-use . 这允许将所有复杂的业务逻辑封装在Java代码中,而HTL代码只处理直接标记生产。
Java Use-API对象可以是简单的POJO,通过POJO的默认构造函数由特定实现进行实例化。
Use-API POJO还可以使用以下签名公开一个名为init的公共方法:
    /**
     * Initializes the Use bean.
     *
     * @param bindings All bindings available to the HTL scripts.
     **/
    public void init(javax.script.Bindings bindings);

bindings 射可包含为当前执行的HTL脚本提供上下文的对象,Use-API对象可以使用这些对象进行处理。

简单示例

我们将开始没有use类的HTL组件。 它由一个文件组成, /apps/my-example/components/info.html

/apps/my-example/component/info/info.html

<div>
    <h1>${properties.title}</h1>
    <p>${properties.description}</p>
</div>

我们还为此组件添加一些内容,以在以下位置进行渲染 /content/my-example/ :

http://<host>:<port>/content/my-example.json

{
    "sling:resourceType": "my-example/component/info",
    "title": "My Example",
    "description": "This Is Some Example Content."
}

访问此内容时,将执行HTL文件。 在HTL代码中,我们使用上下文 properties 对象访问当前资源并 title 显示 description 它们。 输出HTML将为:

view-source:http://<host>:<port>/content/my-example.html

<div>
    <h1>My Example</h1>
    <p>This Is Some Example Content.</p>
</div>

添加Use类

息组 件本身不需要use类来执行其(非常简单)函数。 但是,在某些情况下,您需要做在HTL中无法完成的事情,因此需要使用类。 但请记住以下几点:
仅当某些操作无法在HTL中完成时,才应使用use类。
例如,假定您希望组件 info 显示资源的 title description 属性,但全部以小写形式显示。 由于HTL没有用于小写字符串的方法,因此您需要use-class。 我们可以通过添加一个Java use-class并按如下方式更改 info.html 来实现:

/apps/my-example/component/info/info.html

<div data-sly-use.info="Info">
    <h1>${info.lowerCaseTitle}</h1>
    <p>${info.lowerCaseDescription}</p>
</div>

/apps/my-example/component/info/Info.java

package apps.my_example.components.info;

import com.adobe.cq.sightly.WCMUsePojo;

public class Info extends WCMUsePojo {
    private String lowerCaseTitle;
    private String lowerCaseDescription;

    @Override
    public void activate() throws Exception {
        lowerCaseTitle = getProperties().get("title", "").toLowerCase();
        lowerCaseDescription = getProperties().get("description", "").toLowerCase();
    }

    public String getLowerCaseTitle() {
        return lowerCaseTitle;
    }

    public String getLowerCaseDescription() {
        return lowerCaseDescription;
    }
}

在以下各节中,我们将遍历代码的不同部分。

本地与捆绑Java类

Java use-class可以通过两种方式安装: 本地 捆绑 。 此示例使用本地安装。
在本地安装中,Java源文件将放在HTL文件的旁边,位于同一存储库文件夹中。 该源将按需自动编译。 无需单独的编译或打包步骤。
在捆绑安装中,必须使用标准AEM捆绑部署机制在OSGi捆绑包中编译和部署Java类(请参 阅捆绑Java类 )。
use类特定于相 关组件时,建议使用本地Java use-class。
Java代码实现从多个HTL组件 访问的服务时,建议使用捆绑的Java使用类。

Java包是存储库路径

当使用本地安装时,use-class的包名称必须与存储库文件夹位置的名称匹配,路径中的任何连字符都替换为包名称中的下划线。
在本例中, Info.java 位于以下位 /apps/my-example/components/info 置,因此软件包是 apps.my_example.components.info :

/apps/my-example/component/info/Info.java

package apps.my_example.components.info;

import com.adobe.cq.sightly.WCMUsePojo;

public class Info extends WCMUsePojo {

   ...

}

在AEM开发中,建议在存储库项目名称中使用连字符。 但是,连字符在Java包名称中是非法的。 因此,必须将 存储库路径中的所有连字符转换为包名称中的下划线

扩展 WCMUsePojo

虽然有多种将Java类与HTL集成的方法(请参阅替代方 WCMUsePojo 法),但最简单的方法是扩展 WCMUsePojo 类:

/apps/my-example/component/info/Info.java

package apps.my_example.components.info;

import com.adobe.cq.sightly.WCMUsePojo;

public class Info extends WCMUsePojo

    ...
}

初始化类

从扩展use类时,通过 WCMUsePojo 覆盖方法来执行 activate 初始化:

/apps/my-example/component/info/Info.java

...

public class Info extends WCMUsePojo {
    private String lowerCaseTitle;
    private String lowerCaseDescription;

    @Override
    public void activate() throws Exception {
        lowerCaseTitle = getProperties().get("title", "").toLowerCase();
        lowerCaseDescription = getProperties().get("description", "").toLowerCase();
    }

...

}

上下文

通常, 激活方 法用于根据当前上下文(例如,当前请求和资源)预计算和存储HTL代码中所需的值(在成员变量中)。
WCMUsePojo 提供对HTL文件中可用的同一组上下文对象的访问(请参阅 全局对象 )。
在扩展的类中,可 WCMUsePojo 以使用名称访问上下文对象
或者,常用的上下文对象也可以通过相应的便捷方 法直接访问 :

Getter方法

use-class初始化后,将运行HTL文件。 在此阶段,HTL通常会拉入use-class的各个成员变量的状态,并呈现这些变量以进行演示。
要从HTL文件中访问这些值,必须根据以下命名约定在use-class中定义自定义getter方法:
  • 表单的方法将 getXyz 在HTL文件中显示一个名为的对象属性 xyz
在以下示例中,这些方 getTitle 法和 getDescription 结果导致对象属性 title ,并在 description HTL文件的上下文中变得可访问:

/apps/my-example/component/info/Info.java

...

public class Info extends WCMUsePojo {

    ...

    public String getLowerCaseTitle() {
        return lowerCaseTitle;
    }

    public String getLowerCaseDescription() {
        return lowerCaseDescription;
    }
}

data-sly-use属性

data-sly-use 属性用于初始化HTL代码中的use类。 在我们的示例 data-sly-use 中,属性声明我们要使用类 Info 。 我们只能使用类的本地名称,因为我们使用的是本地安装(已将Java源文件放在与HTL文件相同的文件夹中)。 如果使用捆绑安装,则必须指定完全限定的类名。

/apps/my-example/component/info/info.html

<div data-sly-use.info="Info">
    <h1>${info.lowerCaseTitle}</h1>
    <p>${info.lowerCaseDescription}</p>
</div>

本地标识符

HTL文 info 件中使用标 data-sly-use.info 识符(在中的点之后)来标识类。 声明后,此标识符的范围在文件中是全局的。 它不限于包含语句的元 data-sly-use 素。

/apps/my-example/component/info/info.html

<div data-sly-use.info="Info">
    <h1>${info.lowerCaseTitle}</h1>
    <p>${info.lowerCaseDescription}</p>
</div>

获取属性

然后, info 该标识符用于访问对象属性 title , description 以及通过getter方法和公开的 Info.getTitle 对象 Info.getDescription

/apps/my-example/component/info/info.html

<div data-sly-use.info="Info">
    <h1>${info.lowerCaseTitle}</h1>
    <p>${info.lowerCaseDescription}</p>
</div>

输出

现在,当我们访 /content/my-example.html 问时,它将返回以下HTML:

view-source:http://<host>:<port>/content/my-example.html

<div>
    <h1>my example</h1>
    <p>this is some example content.</p>
</div>

超越基础

在本节中,我们将介绍一些超越上述简单示例的其他功能:
  • 将参数传递到use类。
  • 捆绑的Java用类。
  • 替代 WCMUsePojo

传递参数

在初始化时,参数可以传递给use类。 例如,我们可以执行以下操作:

/content/my-example/component/info/info.html

<div data-sly-use.info="${'Info' @ text='Some text'}">
    <h1>${info.lowerCaseTitle}</h1>
    <p>${info.lowerCaseDescription}</p>
    <p>${info.upperCaseText}</p>
</div>

在此,我们传递一个名为的参数 text 。 use-class然后将我们检索的字符串加上并显示结果 info.upperCaseText 。 以下是调整后的使用类:

/apps/my-example/component/info/Info.java

package apps.my_example.components.info;

import com.adobe.cq.sightly.WCMUsePojo;

public class Info extends WCMUsePojo {

    ...

    private String reverseText;

    @Override
    public void activate() throws Exception {

        ...

        String text = get("text", String.class);
        reverseText = new StringBuffer(text).reverse().toString();

    }

    public String getReverseText() {
        return reverseText;
    }

    ...
}

通过方法访问该参 WCMUsePojo <T> T get(String paramName, Class<T> type)
就我们而言,声明:
get("text", String.class)
然后,该字符串通过以下方法进行反转和公开:
getReverseText()

仅从数据密码模板传递参数

尽管上述示例在技术上是正确的,但实际上当相关值在HTL代码的执行上下文中可用时(或者,试用,该值是静态的,如上所述),从HTL传递值来初始化使用类并没什么意义。
其原因是use-class将始终具有与HTL代码相同的执行上下文的访问权限。 这就引出了最佳实践的一个要点:
仅当在文件中使用use-class时,才应将参数传递到use-class,该文件本身是从另一个HTL文件中调用的, data-sly-template 其中包含需要传递的参数。
例如,让我们在现有示例旁边 data-sly-template 创建一个单独的文件。 我们将调用新文件 extra.html 。 它包含一 data-sly-template 个名为 extra :

/apps/my-example/component/info/extra.html

<template data-sly-template.extra="${@ text}"
          data-sly-use.extraHelper="${'ExtraHelper' @ text=text}">
  <p>${extraHelper.reversedText}</p>
</template>

模板 extra 采用单个参数 text 。 然后,它使用本地名 ExtraHelper 初始化Java extraHelper use-class,并将模板参数的值 text 传递给它作为use-class参数 text
模板的主体获取属性( extraHelper.reversedText 实际调用该属性)并 ExtraHelper.getReversedText() 显示该值。
我们还会调整现有模 info.html 板,以使用此新模板:

/apps/my-example/component/info/info.html

<div data-sly-use.info="Info"
     data-sly-use.extra="extra.html">

  <h1>${info.lowerCaseTitle}</h1>
  <p>${info.lowerCaseDescription}</p>

  <div data-sly-call="${extra.extra @ text=properties.description}"></div>

</div>

该文 info.html 件现在包 data-sly-use 含两个语句,其中一个是导入Java Info use-class的原始语句,另一个是导入本地名称下的模板文件的新语句 extra
请注意,我们可能已将模板块放在文件 info.html 中以避免第二个模板 data-sly-use ,但单独的模板文件更常见、可重用。
Info 像以前一样使用,调用其getter方 getLowerCaseTitle() getLowerCaseDescription() 并通过其相应的HTL属性 info.lowerCaseTitle info.lowerCaseDescription
然后,对模 data-sly-call 板执行 extra 一个操作,并将值 properties.description 作为参数传递 text
Java use-class已更 Info.java 改为处理新文本参数:

/apps/my-example/component/info/ExtraHelper.java

package apps.my_example.components.info;

import com.adobe.cq.sightly.WCMUsePojo;

public class ExtraHelper extends WCMUsePojo {
    private String reversedText;
    ...

    @Override
    public void activate() throws Exception {
        String text = get("text", String.class);
        reversedText = new StringBuilder(text).reverse().toString();

        ...
    }

    public String getReversedText() {
        return reversedText;
    }
}

text 数被检索为 get("text", String.class) ,值被反转,并通过getter作为HTL reversedText 对象可用 getReversedText()

捆绑的Java类

对于捆绑使用类,必须使用标准OSGi捆绑部署机制在AEM中编译、打包和部署该类。 与本地安装不同,use-class包声 明应正 常命名:

/apps/my-example/component/info/Info.java

package org.example.app.components;

import com.adobe.cq.sightly.WCMUsePojo;

public class Info extends WCMUsePojo {
    ...
}

并且,语 data-sly-use 句必须引用完全限定的类名,而不是只引用本地类名:

/apps/my-example/component/info/info.html

<div data-sly-use.info="org.example.app.components.info.Info">
  <h1>${info.title}</h1>
  <p>${info.description}</p>
</div>

替代 WCMUsePojo

创建Java用类的最常见方法是扩展 WCMUsePojo 。 但是,还有许多其他选项。 要了解这些变体,了解HTL语句在内 data-sly-use 部的工作方式会有所帮助。
假定您有以下语 data-sly-use 句:
<div data-sly-use. localName =" UseClass ">
系统按如下方式处理该语句:
(1)
  • 如果与HTL文件位 UseClass.java 于同一目录中存在本地文件,请尝试编译并加载该类。 如果成功,请转到(2)。
  • 否则,解 UseClass 释为完全限定的类名称,并尝试从OSGi环境加载它。 如果成功,请转到(2)。
  • 否则,解 UseClass 释为HTL或JavaScript文件的路径并加载该文件。 如果goto成功(4)。
(2)
  • 尝试调整当前 Resource UseClass 。 如果成功,请转到(3)。
  • 否则,请尝试将当前版本调 Request 整为 UseClass 。 如果成功,请转到(3)。
  • 否则,尝试使用 UseClass 零参数构造函数实例化。 如果成功,请转到(3)。
(3)
  • 在HTL中,将新改编或创建的对象绑定到名称 localName
  • UseClass 果实 io.sightly.java.api.Use 现,则调用方 init 法,传递当前执行上下文(以对象的形 javax.scripting.Bindings 式)。
(4)
  • UseClass 果是包含模板的HTL文件的路 data-sly-template 径,请准备模板。
  • 否则, UseClass 如果是JavaScript use-class的路径,请准备use-class(请参 阅JavaScript Use-API )。
有关上述描述的几个要点:
  • 任何可从中调整、 Resource 可从中 Request 调整或具有零参数构造函数的类都可以是使用类。 类无需扩展甚至 WCMUsePojo 实现 Use
  • 但是,如果use-class实 现了 ,则其方法将自 Use init 动与当前上下文一起调用,从而允许您将初始化代码放置在依赖于该上下文的位置。
  • 扩展的使用类 WCMUsePojo 只是实现的一个特殊情况 Use 。 它提供了方便的上下文方法,并 activate 且自动调用其方法 Use.init

直接实现接口使用

创建use类的最常见方法是扩展, WCMUsePojo 但也可以直接实现接 io.sightly.java.api.Use 口本身。
该接 Use 口仅定义一种方法:
初始化 init 类时,将调用该方法,该类具有 Bindings 一个对象,该对象包含所有上下文对象以及传递到use-class的任何参数。
必须使用对象显式实现所有附 WCMUsePojo.getProperties() 加功能(如等效 javax.script.Bindings 功能)。 例如:

Info.java

import io.sightly.java.api.Use;

public class MyComponent implements Use {
   ...
    @Override
    public void init(Bindings bindings) {

        // All standard objects/binding are available
        Resource resource = (Resource)bindings.get("resource");
        ValueMap properties = (ValueMap)bindings.get("properties");
        ...

        // Parameters passed to the use-class are also available
        String param1 = (String) bindings.get("param1");
    }
    ...
}

当您希望将现有类 Use 的子类用 WCMUsePojo 作use-class时,自己实现接口而不是扩展。

从资源调整

另一个选项是使用可调整的辅助类 org.apache.sling.api.resource.Resource
假设您需要编写一个HTL脚本来显示DAM资产的mimetype。 在这种情况下,您知道调用HTL脚本时,它将位于用nodetype包装JCR Resource 的上下文 Node dam:Asset
您知道节点 dam:Asset 具有如下结构:

存储库结构

{
  "content": {
    "dam": {
      "geometrixx": {
        "portraits": {
          "jane_doe.jpg": {
            ...
          "jcr:content": {
            ...
            "metadata": {
              ...
            },
            "renditions": {
              ...
              "original": {
                ...
                "jcr:content": {
                  "jcr:primaryType": "nt:resource",
                  "jcr:lastModifiedBy": "admin",
                  "jcr:mimeType": "image/jpeg",
                  "jcr:lastModified": "Fri Jun 13 2014 15:27:39 GMT+0200",
                  "jcr:data": ...,
                  "jcr:uuid": "22e3c598-4fa8-4c5d-8b47-8aecfb5de399"
                }
              },
              "cq5dam.thumbnail.319.319.png": {
                  ...
              },
              "cq5dam.thumbnail.48.48.png": {
                  ...
              },
              "cq5dam.thumbnail.140.100.png": {
                  ...
              }
            }
          }  
        }
      }
    }
  }
}

此处,我们将作为示例项目geometrixx的一部分显示AEM默认安装附带的资产(JPEG图像)。 资产被调用, jane_doe.jpg 其mimetype被调 image/jpeg 用。
要从HTL中访问资产,您可以在语 com.day.cq.dam.api.Asset 句中声明为 data-sly-use 类,然后使用get方法 Asset 检索所需的信息。 例如:

mimetype.html

<div data-sly-use.asset="com.day.cq.dam.api.Asset">
  <p>${asset.mimeType}</p>
</div>

该语 data-sly-use 句指示HTL将当前代码改 Resource 编为 Asset 一个代码,并为它指定本地名称 asset 。 然后,它调用 getMimeType 使用 Asset HTL getter短格式的方法: asset.mimeType .

根据请求调整

还可以使用任何可适应 org.apache.sling.api.SlingHttpServletRequest
与上述情况一样,可从中调整 Resource 的使用类在语句 SlingHttpServletRequest 中可指定 data-sly-use 。 执行时,当前请求将与给定的类相适应,并且生成的对象将在HTL中可用。