【问题标题】:Get bean class from composite component从复合组件中获取 bean 类
【发布时间】:2016-02-11 00:28:10
【问题描述】:

我有复合组件:

<my:component value="#{bean.property1.property2}/>

我需要从复合组件中获取 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 方法)。它返回最后使用的 ELContext 而不是实际上下文(我并不感到惊讶 :))。

目标是从my:component 获得#{bean.property1} 的类。我该怎么做?

【问题讨论】:

    标签: jsf jsf-2 facelets composite-component


    【解决方案1】:

    您可以将 bean 作为参数传递给组件。

    1)在组件接口文件中声明属性(如果你使用的是复合组件):

    <cc:interface componentType="myComponentClass">
        <cc:attribute name="myBean" preferred="true"/>
        ..others attributes
    <cc:interface>
    

    2) 在组件类(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) 在组件的渲染类中,将 UIComponent 转换为 myComponentClass。

    @Override
    public void encodeBegin(FacesContext pContext, UIComponent pComponent)
        throws IOException {
        myComponentClass myComponent = (myComponentClass) pComponent;
        myComponent.getYourAttribute();
    }
    

    【讨论】:

    • 感谢您的回答。不幸的是,我无法向现有组件添加新属性。有很多页面使用了这个组件,我不应该改变。
    【解决方案2】:

    RichFaces 很容易:

        ValueExpressionAnalayser analyser = new ValueExpressionAnalayserImpl();
        ValueDescriptor valueDescriptor = analyser.getPropertyDescriptor(context, valueExpression);
        Class<?> beanClass = valueDescriptor.getBeanType();
    

    这对我来说没问题。

    javax.faces.validator 包中还有ValueExpressionAnalayzer,但它是包私有的,不能使用。

    【讨论】:

    • JSF 自己的ValueExpressionAnalayzer 是一个包私有类,因此很遗憾不能公开使用。 OmniFaces 也有一个 org.omnifaces.el.ExpressionInspector 用于此目的。它甚至支持从 EL 表达式中提取方法参数(用于 a.o. &lt;o:graphicImage&gt;)。
    • @BalusC 关于私有包你是对的。我已经编辑了我的答案。我应该看看 OmniFaces。与 RichFaces 兼容吗?
    • 几个 OmniFaces 工件已使用 RF 4.5 进行了测试。至少,它应该可以很好地并排运行,就像 PrimeFaces 一样。 OmniFaces 旨在与任何 JSF 组件库兼容。如果您发现与最新 RF 版本的任何兼容性问题,请务必报告issue。
    猜你喜欢
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 2017-11-20
    • 2021-09-22
    • 1970-01-01
    • 2012-10-15
    • 2015-01-13
    • 1970-01-01
    相关资源
    最近更新 更多