从复合组件获取 bean class
Get bean class from composite component
我有复合组件:
<my:component value="#{bean.property1.property2}/>
从复合组件中,我需要获取 class of bean.property1
才能读取其注释。
我通过以下代码完成:
ValueExpression valueExpression = expressionFactory.createValueExpression(FacesContext.getCurrentInstance().getELContext(),
"#{bean.property1}", Object.class);
Object bean = valueExpression.getValue(FacesContext.getCurrentInstance().getELContext());
Class<?> beanClass = bean.getClass();
这很好用,但是如果我从 facelet 使用 my:component
并通过 ui:param
作为参数传递 bean
这不起作用,因为 bean
不能已解决。
可能我应该使用 FaceletContext
作为 ELContext
而不是 FacesContext.getCurrentInstance().getELContext()
:
FaceletContext faceletElContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes()
.get("javax.faces.FACELET_CONTEXT");
但这不适用于 RENDER_RESPONSE
阶段(来自 encodeBegin
方法)。它 returns 最后使用 ELContext 而不是实际上下文(我并不感到惊讶 :))。
目标是从 my:component
中获得 #{bean.property1}
中的 class。我该怎么做?
这很容易 RichFaces
:
ValueExpressionAnalayser analyser = new ValueExpressionAnalayserImpl();
ValueDescriptor valueDescriptor = analyser.getPropertyDescriptor(context, valueExpression);
Class<?> beanClass = valueDescriptor.getBeanType();
这对我来说没问题。
javax.faces.validator
包中也有 ValueExpressionAnalayzer
,但它是包私有的,不能使用。
您可以将 bean 作为参数传递给组件。
1) 在组件接口文件中声明属性(如果使用复合组件):
<cc:interface componentType="myComponentClass">
<cc:attribute name="myBean" preferred="true"/>
..others attributes
<cc:interface>
2) 在组件 class(myComponentClass)
中为 "myBean" 属性实现各自的 getter 和 setter
protected enum PropertyKeys {
myBean;
String toString;
PropertyKeys(String toString) {
this.toString = toString;
}
PropertyKeys() {}
@Override
public String toString() {
return ((this.toString != null) ? this.toString : super.toString());
}
}
public YourBeanClass getMyBean() {
return (YourBeanClass) getStateHelper().eval(PropertyKeys.myBean, null);
}
public void setMyBean(YourBeanClass myBean) {
getStateHelper().put(PropertyKeys.myBean, myBean);
}
3) 在你的 jsf 页面上设置属性:
<my:component myBean="#{bean}"/>
4) 在组件的渲染中 class 将 UIComponent 转换为 myComponentClass。
@Override
public void encodeBegin(FacesContext pContext, UIComponent pComponent)
throws IOException {
myComponentClass myComponent = (myComponentClass) pComponent;
myComponent.getYourAttribute();
}
我有复合组件:
<my:component value="#{bean.property1.property2}/>
从复合组件中,我需要获取 class of bean.property1
才能读取其注释。
我通过以下代码完成:
ValueExpression valueExpression = expressionFactory.createValueExpression(FacesContext.getCurrentInstance().getELContext(),
"#{bean.property1}", Object.class);
Object bean = valueExpression.getValue(FacesContext.getCurrentInstance().getELContext());
Class<?> beanClass = bean.getClass();
这很好用,但是如果我从 facelet 使用 my:component
并通过 ui:param
作为参数传递 bean
这不起作用,因为 bean
不能已解决。
可能我应该使用 FaceletContext
作为 ELContext
而不是 FacesContext.getCurrentInstance().getELContext()
:
FaceletContext faceletElContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes()
.get("javax.faces.FACELET_CONTEXT");
但这不适用于 RENDER_RESPONSE
阶段(来自 encodeBegin
方法)。它 returns 最后使用 ELContext 而不是实际上下文(我并不感到惊讶 :))。
目标是从 my:component
中获得 #{bean.property1}
中的 class。我该怎么做?
这很容易 RichFaces
:
ValueExpressionAnalayser analyser = new ValueExpressionAnalayserImpl();
ValueDescriptor valueDescriptor = analyser.getPropertyDescriptor(context, valueExpression);
Class<?> beanClass = valueDescriptor.getBeanType();
这对我来说没问题。
javax.faces.validator
包中也有 ValueExpressionAnalayzer
,但它是包私有的,不能使用。
您可以将 bean 作为参数传递给组件。
1) 在组件接口文件中声明属性(如果使用复合组件):
<cc:interface componentType="myComponentClass">
<cc:attribute name="myBean" preferred="true"/>
..others attributes
<cc:interface>
2) 在组件 class(myComponentClass)
中为 "myBean" 属性实现各自的 getter 和 setterprotected enum PropertyKeys {
myBean;
String toString;
PropertyKeys(String toString) {
this.toString = toString;
}
PropertyKeys() {}
@Override
public String toString() {
return ((this.toString != null) ? this.toString : super.toString());
}
}
public YourBeanClass getMyBean() {
return (YourBeanClass) getStateHelper().eval(PropertyKeys.myBean, null);
}
public void setMyBean(YourBeanClass myBean) {
getStateHelper().put(PropertyKeys.myBean, myBean);
}
3) 在你的 jsf 页面上设置属性:
<my:component myBean="#{bean}"/>
4) 在组件的渲染中 class 将 UIComponent 转换为 myComponentClass。
@Override
public void encodeBegin(FacesContext pContext, UIComponent pComponent)
throws IOException {
myComponentClass myComponent = (myComponentClass) pComponent;
myComponent.getYourAttribute();
}