我正在处理一个需要一些属性(用户在运行时设置)的组件,以使其按预期工作。
最初,我只是使用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)}" />
但这不会返回我想要的值。
答案 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 ,否则将无法识别。