如何从Java类访问组件属性

时间:2013-10-07 05:04:14

标签: java taglib cq5 aem

我正在处理一个需要一些属性(用户在运行时设置)的组件,以使其按预期工作。

最初,我只是使用properties.get('foo')从我的组件中获取所需的属性,但我正在尝试从组件jsp文件中删除所有脚本代码的痕迹。

如何在Java代码中获取此属性'foo'(在我的组件的运行时期间设置)?我记得在某处读过使用ValueMap是最好的方法,所以我尝试使用它: -

public static Map<String, Object> getResourceProperties(String path,
            SlingHttpServletRequest request) {
        ResourceResolver resourceResolver = request.getResourceResolver();
        Map<String, Object> props= new HashMap<String, Object>();
        Resource resource = resourceResolver.getResource(path);
        if (null != resource) {
            props.putAll(resource.adaptTo(ValueMap.class));
        }
        return props;
    } 

这是我的jsp: - <c:set var="refProperties" value="${xyz:getResourceProperties(properties.path,slingRequest)}" />

但这不会返回我想要的值。

5 个答案:

答案 0 :(得分:5)

实现此目的的最简单方法是包含/libs/foundation/global.jsp,只使用范围properties中已有的${properties.foo}对象。

将global.jsp包含在组件jsp的顶部,如下所示:

<%@include file="/libs/foundation/global.jsp"%>

正如文件中的注释所示,它基本上注册了Sling(sling),CQ(cq)和JSTL(c,fmt,fn)taglib名称空间以供JSP使用。

然后,在cq:defineObjects taglib的帮助下,它将许多有用的对象带入范围。

<cq:defineObjects />

以下是清单:

@param slingRequest SlingHttpServletRequest
@param slingResponse SlingHttpServletResponse
@param resource the current resource
@param currentNode the current node
@param log default logger
@param sling sling script helper

@param componentContext component context of this request
@param editContext edit context of this request
@param properties properties of the addressed resource (aka "localstruct")
@param pageManager page manager
@param currentPage containing page addressed by the request (aka "actpage")
@param resourcePage containing page of the addressed resource (aka "myPage")
@param pageProperties properties of the containing page
@param component current CQ5 component
@param designer designer
@param currentDesign design of the addressed resource  (aka "actdesign")
@param resourceDesign design of the addressed resource (aka "myDesign")
@param currentStyle style of the addressed resource (aka "actstyle")

这意味着只需使用cq:defineObjects标记库,您就可以通过JSP表达式语言(EL)访问属性ValueMap。访问JSP中的属性不需要额外的转换。

<c:out value="${properties.foo}" />

要访问您自己的Java taglib或bean中的属性,您只需使用标准JSTL标记将相应的对象传递给您的代码。您可以传递整个请求,当前资源或仅传递属性。传递整个请求使您的Java代码可以访问当前资源以及cq:defineObjects taglib创建的所有对象,包括属性ValueMap。

在JSP中:

<jsp:useBean id="mybean" scope="request" class="com.my.impl.TheBean">
   <jsp:setProperty name="mybean" property="slingRequest" value="${slingRequest}"/>
   <jsp:setProperty name="mybean" property="resource" value="${resource}"/>
   <jsp:setProperty name="mybean" property="properties" value="${properties}"/>
</jsp:useBean>

在bean中:

public void setSlingRequest(final SlingHttpServletRequest slingRequest) {
    this.slingRequest = slingRequest;
    // Use the one created by cq:defineObjects
    this.properties = (ValueMap)this.slingRequest.getAttribute("properties");
    // OR adapt the resource
    this.properties = this.slingRequest.getResource().adaptTo(ValueMap.class);
}

public void setResource(final Resource resource) {
    this.resource = resource;
    this.properties = this.resource.adaptTo(ValueMap.class);
}

public void setProperties(final ValueMap properties) {
    this.properties = properties;
}

答案 1 :(得分:1)

在这种特殊情况下,您尝试创建包含所有资源属性的Map<String, Object>。这个映射与properties对象(也是Map)相同,所以我猜整个方法都是多余的(并且 - 当你写的时候 - 它不起作用)。 properties对象不包含path方法,可能这就是它不起作用的原因。

更重要的是,您可能已经使用request.getResource()(而不是通过路径获取解析器和资源)。此外,您可以从JSP中轻松传递resource,而不是将ValueMap调整为properties

更一般地说,如果你想从JSP提取逻辑到Java类,我认为创建某种model类,将slingRequest传递给它的构造函数然后调用它的方法是个好主意。在JSP中。例如:

<强> GET.jsp

<c:set var="model" value="<%= new MyModel(slingRequest) %>" />
Result of the first method: ${model.firstValue}<br/>
Result of the second method: ${model.secondValue}

<强> MyModel.java

public class MyModel {
    private final SlingHttpServletRequest request;

    private final Resource resource;

    private final ValueMap properties;

    public MyModel(SlingHttpServletRequest request) {
        this.request = request;
        this.resource = request.getResource();
        this.properties = resource.adaptTo(ValueMap.class);
    }

    public String getFirstMethod() {
        // do some clever things
        return "";
    }

    public String getSecondMethod() {
        // do more clever things
        return "";
    }
}

请注意,如果您调用${model.firstMethod},则需要在方法名称get)中添加getFirstMethod()前缀。

答案 2 :(得分:1)

我会使用useBean标记来创建一个类的实例,它可以为您提供所需的任何信息:

<jsp:useBean id="mycomponent" scope="request" class="com.company.components.SomeComponent">
   <jsp:setProperty name="mycomponent" property="request" value="<%= slingRequest %>"/>
</jsp:useBean>

然后在课堂上创建一个setter。

 public void setRequest(final SlingHttpServletRequest request) {
    this.request = request;
    //or more likely an init() method that inits all your props
    //you could even use reflection to look for props that match all the field names
    //to init them automatically
    ValueMap props=request.getResource().adaptTo(ValueMap.class)
    this.interestingProp= props.get("interestingProp");
}

public String getInterestingProp(){
   return this.interestingProp;
}

然后在你的jsp:

<c:out value="${mycomponent.interestingProp}"/>

答案 3 :(得分:0)

在Java文件中获取JCR会话,然后遍历节点 比如content/your_site_name/node/some_parsys。然后,您可以获取作者在运行时设置的值。

if(node.hasProperty("title")){
    String title=node.getProperty().getValue().getString();
}

答案 4 :(得分:0)

我确实设法回答了我自己的问题。我所做的只是在我的jsp中使用resource.path

resource 这里指的是有问题的组件,所以使用我能够正确创建 ValueMap 的路径。

因此,我的 jsp 文件中的代码如下: -

<c:set var="refProperties" value="${xyz:getResourceProperties(resource.path,slingRequest)}"\>

使用它,我现在可以引用我想要的组件的任何属性: -

${refProperties.foo}

要使用resource.path,我们还必须包含 global.jsp ,否则将无法识别。