【问题标题】:h:selectOneMenu generic converter for all entities without calling DB again and againh:selectOneMenu 用于所有实体的通用转换器,无需一次又一次地调用 DB
【发布时间】:2013-04-15 11:21:04
【问题描述】:

我想从<h:selectOneMenu> 中获取选定对象,但问题是我找不到适用于所有类型实体的通用转换器。

我的第一个问题是,是否有适用于所有类型实体的通用转换器?我不想再次为每个其他实体编写另一个转换器。我的第二个问题是,有没有办法在没有任何转换器的情况下获得选定的对象?我不想一次又一次地调用数据库。

我有一个具有idname 属性的Car 实体。

【问题讨论】:

    标签: jsf jsf-2 javabeans converter selectonemenu


    【解决方案1】:

    我的第一个问题是,是否有适用于所有类型实体的通用转换器?

    这在标准 JSF 中确实不存在。 JSF 实用程序库OmniFaces 在其分类中具有这样的转换器omnifaces.SelectItemsConverter。您需要做的就是将其声明为UISelectOneUISelectMany 组件的转换器,如下所示:

    <h:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
    

    另见the SelectItemsConverter showcase。此转换器依赖于对象项的toString()。还有另一个,omnifaces.SelectItemsIndexConverter,它依赖于选项列表中对象项的索引,另见the SelectItemsIndexConverter showcase

    目前没有其他 JSF 组件/实用程序库提供相同的功能。


    第二个问题是,有没有办法在没有任何转换器的情况下获取选定的对象?

    没有。只需使用 OmniFaces 即可,这样您就无需创建自定义转换器来访问数据库。或者,如果您想做得过火,请为 &lt;h:selectOneMenu&gt; 创建一个自定义渲染器,它将项目索引渲染为选项值并能够将其设置为模型值,但这比简单的转换器要多得多,而且您仍然需要需要做一些额外的工作才能根据索引从列表中获取所需的对象——这没有任何意义。

    另见:

    【讨论】:

    • 我可以从 selectonemenu 中获取选定值的索引并从绑定到 selectonemenu 的 List 中获取选定值吗?
    • 为什么这些信息与 backing bean 相关?无论如何......只要做availableItems.indexOf(selectedItem)
    • 问题是如何获取 selectedItem 或 selectedItem 的索引?你所说的 availableItems.indexOf(selectedItem) 是什么意思!?
    • 抱歉,我希望变量名称能够自我记录,以便具有足够逻辑思维能力的人能够轻松地自行判断它们所代表的含义。 availableItems 就是你绑定到&lt;f:selectItems&gt; 的值,selectedItem 就是你绑定到&lt;h:selectOneMenu&gt; 的值。该行可以进入 action(listener) 方法。同样,我不确定如果您已经拥有选定的项目,那么需要计算索引是否有意义。
    【解决方案2】:

    似乎应该有一个通用转换器,以便您可以轻松地从下拉列表中选择对象,而无需为每种对象类型编写转换器,也无需调用数据库(如大多数示例所示)。但是我不知道,所以我编写了自己的转换器来做到这一点。请注意,转换器希望该对象有一个 getId() 方法,该方法返回某种唯一 ID。如果没有,它将失败。如果您需要以编程方式确定要用作键的方法的名称,您可以将逻辑添加到getMethodName()。请注意,我们在项目中使用 Seam。如果你不使用 Seam,NO_SELECTION_VALUE 部分以及类上的三个注解可能会被删除。

    此代码的灵感来自:http://arjan-tijms.omnifaces.org/2011/12/automatic-to-object-conversion-in-jsf.html

    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Collection;
    
    import javax.faces.component.UIComponent;
    import javax.faces.component.UISelectItem;
    import javax.faces.component.UISelectItems;
    import javax.faces.context.FacesContext;
    import javax.faces.convert.ConverterException;
    import javax.faces.model.SelectItem;
    
    import org.jboss.seam.annotations.Name;
    import org.jboss.seam.annotations.faces.Converter;
    import org.jboss.seam.annotations.intercept.BypassInterceptors;
    
    /**
     * @author: Jason Wheeler
     * @description Converter for lists (SelectOneMenu, SelectManyMenu, etc)
     * @created: 09/05/2013
     */
    
    @Name("listConverter")
    @BypassInterceptors
    @Converter
    public class ListConverter implements javax.faces.convert.Converter {
        private String NO_SELECTION_VALUE = "org.jboss.seam.ui.NoSelectionConverter.noSelectionValue";
    
        @Override
        public String getAsString(FacesContext facesContext, UIComponent component, Object obj) {
            if (obj == null) {
                return NO_SELECTION_VALUE;
            } else {
                try {
                    Method method = obj.getClass().getMethod(getMethodName(obj));
                    return String.valueOf(method.invoke(obj));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    
        public String getMethodName(Object obj) {
            return "getId";
        }
    
        @Override
        public Object getAsObject(FacesContext facesContext, UIComponent component, String val) throws ConverterException {
            if (val == null) {
                return null;
            } else if (val.equals(NO_SELECTION_VALUE)) {
                return null;
            } else {
                for (SelectItem item : getSelectItems(component)) {
                    if (val.equals(getAsString(facesContext, component, item.getValue()))) {
                        return item.getValue();
                    }
                }
                return null;
            }
        }
    
        protected Collection<SelectItem> getSelectItems(UIComponent component) {
            Collection<SelectItem> collection = new ArrayList<SelectItem>();
    
            for (UIComponent child : component.getChildren()) {
                if (child instanceof UISelectItem) {
                    UISelectItem ui = (UISelectItem) child;
                    SelectItem item = (SelectItem) ui.getValue();
                    collection.add(item);
                } else if (child instanceof UISelectItems) {
                    UISelectItems ui = (UISelectItems) child;
                    Object value = ui.getValue();
                    collection.addAll((Collection<SelectItem>) value);
                }
            }
    
            return collection;
        }
    }
    

    【讨论】:

      【解决方案3】:

      我刚刚使用了@Bigwheels 代码,对 JSF 2.0 进行了一些更改,它解决了我的问题:

      import java.lang.reflect.Field;
      import java.lang.reflect.Method;
      import java.util.ArrayList;
      import java.util.Collection;
      import java.util.List;
      import javax.faces.component.UIComponent;
      import javax.faces.component.UISelectItem;
      import javax.faces.component.UISelectItems;
      import javax.faces.context.FacesContext;
      import javax.faces.convert.ConverterException;
      import javax.faces.convert.FacesConverter;
      import javax.faces.model.SelectItem;
      import javax.persistence.Id;
      
      @FacesConverter("selectItemConverter")
      public class SelectItemConverter implements javax.faces.convert.Converter {
      
          private String NO_SELECTION_VALUE = "SELECIONE";
      
          @Override
          public String getAsString(FacesContext facesContext, UIComponent component, Object obj) {
              if (obj == null) {
                  return NO_SELECTION_VALUE;
              } else {
                  try {
                      Method method = obj.getClass().getMethod(getIdMethodName(obj));
                      return String.valueOf(method.invoke(obj));
                  } catch (Exception e) {
                      throw new ConverterException(e);
                  }
              }
          }
      
          public String getIdMethodName(Object obj) {
              try {
                  Field[] fieldList = obj.getClass().getDeclaredFields();
      
                  Field id = null;
                  for (Field field : fieldList) {
                      if(field.isAnnotationPresent(Id.class)) {
                          id = field;
                          break;
                      }
                  }
                  return "get" + capitalize(id.getName());
              } catch(Exception ex) {
                  throw new ConverterException(ex);
              }
          }
      
          private String capitalize(final String line) {
              return Character.toUpperCase(line.charAt(0)) + line.substring(1);
          }
      
          @Override
          public Object getAsObject(FacesContext facesContext, UIComponent component, String val) throws ConverterException {
              if (val == null) {
                  return null;
              } else if (val.equals(NO_SELECTION_VALUE)) {
                  return null;
              } else {
                  for (Object item : getSelectItems(component)) {
                      if (val.equals(getAsString(facesContext, component, item))) {
                          return item;
                      }
                  }
                  return null;
              }
          }
      
          protected List getSelectItems(UIComponent component) {
              List list = new ArrayList();
              for (UIComponent child : component.getChildren()) {
                  if (child instanceof UISelectItem) {
                      UISelectItem ui = (UISelectItem) child;
                      SelectItem item = (SelectItem) ui.getValue();
                      list.add(item);
                  } else if (child instanceof UISelectItems) {
                      UISelectItems ui = (UISelectItems) child;
                      Object value = ui.getValue();
                      list.addAll((Collection<SelectItem>) value);
                  }
              }
              return list;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-04
        • 1970-01-01
        • 1970-01-01
        • 2016-08-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多