JSF2.0:对selectOneMenu使用枚举值

JSF2.0:对selectOneMenu使用枚举值,jsf,jakarta-ee,jsf-2,jboss-weld,Jsf,Jakarta Ee,Jsf 2,Jboss Weld,我正在使用JSF2.0,希望用枚举的值填充selectOneMenu。 一个简单的例子: // Sample Enum public enum Gender { MALE("Male"), FEMALE("Female"); private final String label; private Gender(String label) { this.label = label; } public String getLabel() { return

我正在使用JSF2.0,希望用枚举的值填充selectOneMenu。 一个简单的例子:

// Sample Enum
public enum Gender {
  MALE("Male"),
  FEMALE("Female");

  private final String label;

  private Gender(String label) {
    this.label = label;
  }

  public String getLabel() {
    return this.label;
  }
}
不幸的是,我不能在我当前的项目中使用Seam,因为它有一个很好的
标记,完成了大部分工作。 在Seam中,为了使用枚举的值,我必须编写以下标记(并创建一个提供
{genderValues}
的工厂):

<!-- the Seam way -->
<h:selectOneMenu id="persongender" value="#{person.gender}">
  <s:selectItems var="_gender" value="#{genderValues}"" label="#{_gender.label}"/>
  <s:convertEnum/>
</h:selectOneMenu>


在看了我自己的Seam示例一分钟后,我在托管bean中创建了一个方法,如下所示:

@ManagedBean
public class MyManagedBean {
  public Gender[] getGenderValues() {
    return Gender.values;
  }
}   
在我的标记中

<h:selectOneMenu id="gender" value="#{person.gender}">
  <f:selectItems value="#{myManagedBean.genderValues}" var="g" 
    itemValue="#{g}" itemLabel="#{g.label}"/>
</h:selectOneMenu>

现在,我必须查看在发送表单时,
enum
是否正确保存在我的实体中。我将查看我是否可以自己完成此操作-无论如何,我将非常感谢这方面的提示或最佳做法!

好的,最后一种方法是: -在faces-config.xml中注册标准枚举转换器(可选):


java.lang.Enum
javax.faces.convert.EnumConverter
例如,向托管bean添加一个函数,该函数将枚举值转换为SelectItems数组:

@ManagedBean
公共阶级性别歧视{
public SelectItem[]getGenderValues(){
SelectItem[]items=新建SelectItem[Gender.values().length];
int i=0;
for(Gender g:Gender.values()){
items[i++]=newselectItem(g,g.getLabel());
}
退货项目;
}
}
然后将此函数绑定到JSF中的selectOneMenu:



就是这样!这不是网络上对这个问题的第一个解释。但我认为这是最简单和最短的一个;)

我不久前遇到这个问题,我和你一样解决了它,但后来我意识到,在某种程度上,我无法使用i18n,因为字符串是在enum类中硬编码的。因此,我修改了enumConverter,使用
消息
进行渲染

此外,有时您可能希望将枚举呈现为某种唯一标识符,而不是用户可读的文本(用于某些组件内部使用)

这是我的转换器:

import java.util.ResourceBundle;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */




import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

import com.eyeprevent.configuration.ConfigurationReader;


/**
 * converts an enum in a way that makes the conversion reversible (sometimes)
 * <ul>
 * <li>input: uses its classname and ordinal, reversible<li>
 * <li>else: uses its name, non reversible<li>
 * </ul>
 */
public class EnumConverter implements Converter
{
    @SuppressWarnings("unchecked")
    public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException
    {
        if (value == null || value.length() < 1)
        {
            return null;
        }

        int pos = value.indexOf('@');
        if (pos < 0)
        {
            throw new IllegalArgumentException(value + " do not point to an enum");
        }

        String className = value.substring(0, pos);
        Class clazz;
        int ordinal = Integer.parseInt(value.substring(pos+1), 10);

        try
        {
            clazz = Class.forName( className, true, Thread.currentThread().getContextClassLoader() );
            // if the clazz is not an enum it might be an enum which is inherited. In this case try to find the superclass.
            while (clazz != null && !clazz.isEnum())
            {
                clazz = clazz.getSuperclass();
            }
            if (clazz == null)
            {
                throw new IllegalArgumentException("class " + className + " couldn't be treated as enum");
            }

            Enum[] enums = (Enum[]) clazz.getEnumConstants();
            if (enums.length >= ordinal)
            {
                return enums[ordinal];
            }
        }
        catch (ClassNotFoundException e1)
        {
            throw new RuntimeException(e1);
        }

        throw new IllegalArgumentException("ordinal " + ordinal + " not found in enum " + clazz);
    }

    public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException
    {
        if (value == null)
        {
            return "";
        }

        Enum<?> e = (Enum<?>) value;

        if (component instanceof UIInput || UIInput.COMPONENT_FAMILY.equals(component.getFamily()))
        {
            return e.getClass().getName() + "@" + Integer.toString(e.ordinal(), 10);
        }
        ResourceBundle messages =ConfigurationReader.getMessages(context.getViewRoot().getLocale());
        return messages.getString(e.name());

    }
}
import java.util.ResourceBundle;
/*
*向Apache软件基金会(ASF)授权
*一个或多个参与者许可协议。见通知文件
*与此工作一起分发以获取更多信息
*关于版权所有权。ASF许可此文件
*根据Apache许可证,版本2.0(
*“许可证”);除非符合规定,否则您不得使用此文件
*带着执照。您可以通过以下方式获得许可证副本:
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
*除非适用法律要求或书面同意,
*根据许可证分发的软件在
*“按原样”的基础上,没有任何
*种类,无论是明示的还是暗示的。请参阅许可证以获取详细信息
*管理权限和限制的特定语言
*根据许可证。
*/
导入javax.faces.component.UIComponent;
导入javax.faces.component.UIInput;
导入javax.faces.context.FacesContext;
导入javax.faces.convert.Converter;
导入javax.faces.convert.ConverterException;
导入com.eyeprovent.configuration.ConfigurationReader;
/**
*以使转换可逆的方式转换枚举(有时)
*
    *
  • 输入:使用其类名和序号,可逆
  • *
  • else:使用其名称,不可逆
  • *
*/ 公共类EnumConverter实现转换器 { @抑制警告(“未选中”) 公共对象getAsObject(FacesContext上下文、UIComponent组件、字符串值)引发ConverterException { if(value==null | | value.length()<1) { 返回null; } int pos=value.indexOf('@'); 如果(位置<0) { 抛出新的IllegalArgumentException(值+“不指向枚举”); } String className=value.substring(0,pos); 课堂讨论; int-ordinal=Integer.parseInt(value.substring(pos+1),10); 尝试 { clazz=Class.forName(className,true,Thread.currentThread().getContextClassLoader()); //如果clazz不是枚举,它可能是继承的枚举。在这种情况下,请尝试查找超类。 while(clazz!=null&&!clazz.isEnum()) { clazz=clazz.getSuperclass(); } if(clazz==null) { 抛出新的IllegalArgumentException(“类”+className+“不能被视为枚举”); } 枚举[]枚举=(枚举[])clazz.getEnumConstants(); if(enums.length>=序号) { 返回枚举[序号]; } } 捕获(ClassNotFoundException e1) { 抛出新的运行时异常(e1); } 抛出新的IllegalArgumentException(“在enum”+clazz中找不到序号”+ordinal+); } 公共字符串getAsString(FacesContext上下文、UIComponent组件、对象值)引发ConverterException { 如果(值==null) { 返回“”; } 枚举e=(枚举)值; if(UIInput的组件实例| | UIInput.component_FAMILY.equals(component.getFamily())) { 返回e.getClass().getName()+“@”+Integer.toString(e.ordinal(),10); } ResourceBundle messages=ConfigurationReader.getMessages(context.getViewRoot().getLocale()); returnmessages.getString(例如name()); } }
这里有一个更简单的方法,它使用一个简单的getter和setter将字符串封送到枚举


我使用这种简单的方法,它非常乐观,您可以为自己的目的定制它。我将以下代码放在一个可重用bean中,可以随时从应用程序调用该bean,因此您可以使用包中声明的任何枚举

public List<String> fromEnum(String cname) {
        List<String> names = new ArrayList<>();
        try {
            Class c = Class.forName(cname);
            Object[] r = c.getEnumConstants();
            if (r != null) {
                for (Object o : r) {
                    names.add(o.toString());
                }
            }
        } catch (ClassNotFoundException ex) {
            FaceUtil.ShowError(ex);
        }
        return names;
    }
public static void ShowError(Exception ex) {
        FacesMessage msg=new FacesMessage(FacesMessage.SEVERITY_ERROR,ex.getMessage(),"Error Message");
        FacesContext.getCurrentInstance().addMessage(null, msg);
        }
来自枚举的公共列表(字符串cname){
列表名称=新的ArrayList();
试一试{
类别c=类别forName(cname);
奥布耶
<p:selectOneMenu value="#{jobapp.aplicant.marital}">
<f:selectItems value="#{rtutil.fromEnum('com.company.package.enMarital')}" var="m" itemLabel="#{m}" itemValue="#{m}"/>
</p:selectOneMenu>