JSF2.0:对selectOneMenu使用枚举值
我正在使用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
// 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>