如何从 Java 类访问组件属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19217412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 15:09:48  来源:igfitidea点击:

How to access component properties from a Java Class

javataglibaem

提问by bongman1612

I am working on a component which requires some properties (that the user sets during run time) for it to work as intended.

我正在开发一个组件,它需要一些属性(用户在运行时设置)才能按预期工作。

Initially, I was simply using a properties.get('foo')to fetch the needed property from my component, but I'm trying to remove all traces of script-let code from my component jsp file.

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

How do I fetch this property 'foo' (which is set during runtime on my component) within my Java code? I remember reading somewhere that using a ValueMap was the best way, so I tried using this:-

我如何在我的 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;
    } 

and this in my jsp:- <c:set var="refProperties" value="${xyz:getResourceProperties(properties.path,slingRequest)}" />

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

But this doesn't return the value I want.

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

采纳答案by jedatu

This simplest method to accomplish this is to include the /libs/foundation/global.jspand just use the propertiesobject already in scope ${properties.foo}.

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

Include the global.jsp at the top of the component jsp like so:

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

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

As the comments in the file indicate, it basically registers the Sling (sling), CQ (cq), and JSTL (c,fmt,fn) taglib namespaces for use in the JSP.

正如文件中的注释所示,它基本上注册了在 JSP 中使用的 Sling(吊索)、CQ(cq)和 JSTL(c,fmt,fn)taglib 命名空间。

Then, with the help of the cq:defineObjectstaglib, it brings many helpful objects into scope.

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

<cq:defineObjects />

Here is the list:

这是清单:

@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")

This means that by simply using the cq:defineObjects taglib you already have access to the properties ValueMap through JSP Expression Language (EL). No additional conversion is required to access the properties within the JSP.

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

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

To access the properties within your own Java taglib or bean you would just pass the appropriate object to your code using the standard JSTL tags. You could pass the whole request, the current resource, or just the properties. Passing the whole request gives your Java code access to the current resource and all the objects created by the cq:defineObjects taglib including the properties ValueMap.

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

In JSP:

在 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>

In 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;
}

回答by OmP

Get the JCR session in your Java file, then iterate through the nodes like content/your_site_name/node/some_parsys. Then you can get the values which are set by the author at run time.

在您的 Java 文件中获取 JCR 会话,然后遍历像content/your_site_name/node/some_parsys. 然后你可以得到作者在运行时设置的值。

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

回答by Tomek R?kawek

In this particular case you are trying to create Map<String, Object>containing all resource properties. This map would be the same as propertiesobject (which is also a Map), so I guess the whole method is redundant (and - as you write - it doesn't work). propertiesobject doesn't contain pathmethod and probably that's the reason it doesn't work.

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

What's more, you may have used request.getResource()(instead of getting resolver and resource by path). Also, instead of adapting the resourceto ValueMapyou may have simple pass propertiesfrom the JSP.

更重要的是,您可能已经使用过request.getResource()(而不是通过路径获取解析器和资源)。此外,而不是适应resourceValueMap你可能简单的通过properties从JSP。

More general, if you want to extract logic from JSP to Java class, I think it's a good idea to create some kind of modelclass, passing slingRequestto it's constructor and then invoking its methods in the JSP. Example:

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

GET.jsp

获取.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 "";
    }
}

Please notice that if you invoke ${model.firstMethod}you need to add getprefix to the method name (getFirstMethod()).

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

回答by santiagozky

I would use the useBean tag to create an instance of a class that can give you whatever info you need:

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

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

Then just create a setter in the class.

然后只需在类中创建一个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;
}

Then in your jsp:

然后在你的jsp中:

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

回答by bongman1612

Well I did manage to answer my own question. All I did was to use resource.pathin my jsp.

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

resourcehere refers to the component in question, and so using the path I was able to create my ValueMapcorrectly.

这里的资源是指有问题的组件,因此使用路径我能够正确创建我的ValueMap

So, the code in my jspfile is as follows:-

所以,我的jsp文件中的代码如下:-

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

Using this, I can now reference any property of the component that I want:-

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

${refProperties.foo}

In order to use resource.path, we must also include global.jsp, else it will not be recognised.

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