使用Java反射动态创建JSF表单

5

我正在尝试创建一个简单的CRUD表单,使用Hibernate将数据插入数据库,而不知道对象类型是什么。最终目标是只有一个插入表单,用于数据库中的每个表。到目前为止,我获取当前对象具有的方法,检查是否有任何设置方法,并为每个具有设置的字段创建文本输入。

UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
HtmlPanelGrid hpg = (HtmlPanelGrid) viewRoot.findComponent("panel");
    for (Method method : declaredFields) {
        String name = method.getName();

        if (name.contains("set")) {
            HtmlOutputText hot = new HtmlOutputText();
            HtmlInputText hit = new HtmlInputText();
            hot.setValue(name.substring(3));
            try {
                hit.setValue(newObject.getClass().getMethod(name, String.class));
            } catch (Exception ex) {
                Logger.getLogger(ReflectController.class.getName()).log(Level.SEVERE, null, ex);
            }
            hpg.getChildren().add(hot);
            hpg.getChildren().add(hit);
        }

    }

在这里,newObject 是稍后使用 Hibernate 要插入到数据库中的对象。我的问题是:

我应该如何将该对象的某个字段分配给当前创建的文本输入框。到目前为止,如果我像上面所做的那样将方法放在值中,它只会在该输入框的值属性中打印出该方法。我想要的是,在提交该表单时,将该文本框中的值分配给该名称的属性。

3个回答

2

我可以给你一个部分的答案 - 你需要动态地创建一个ValueExpression

    Application app = FacesContext.getCurrentInstance().getApplication();
    hit.setValueExpression("value", app.getExpressionFactory().createValueExpression(FacesContext.getCurrentInstance().getELContext(), "#{bean.item}", Item.class));

难点在于创建valueExpression,它需要实际映射到对象值中的字段。这需要更多的思考,但你肯定需要动态的valueExpression。按照当前的写法,这将导致执行bean的setItem()方法,参数类型为Item。你需要稍微复杂一些的内容。


2

在JSF中,将输入组件绑定到属性是通过EL表达式实现的。您可以像Steve所示一样以编程方式创建它,但这种语法真的很丑陋。另外,对组件树进行编程操作是使用JSF的一种非正统方法。解决您的需求的正统方法可能是:

<ui:repeat var="prop" value="#{genericEditorBean.propertyNames}">
    <h:outputLabel value="#{prop}" for="input"/>
    <h:inputText id="input" value="#{genericEditorBean.object[prop]}"/>
</ui:repeat>

在哪里

public List<String> getPropertyNames() {
    List<String> propertyNames = new ArrayList<>();
    BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
    for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
        propertyNames.add(pd.getName());
    }
    return propertyNames;
}

在Java API已经提供了一个专门用于扫描Java Bean属性的类时,重新实现这个功能是没有必要的。与您自己编写的版本不同,它还可以处理从超类继承的属性...


2

我曾经使用过一个名为MetaWidget的开源库来完成这个任务。

那是几年前的事情了,但它工作得很好,而且设置起来很容易。

看起来这个项目仍然活跃着:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接