在 h:selectManyCheckbox 中使用枚举
我想在
中使用枚举值。复选框已正确填充,但是,当选择某些值并提交它们时,它们的运行时类型是 String
,而不是枚举。我的代码:
<h:selectManyCheckbox value="#{userController.roles}" layout="pageDirection">
<f:selectItems value="#{userController.rolesSelectMany}" />
</h:selectManyCheckbox>
UserController 类(SecurityRole 是枚举类型):
public SelectItem[] getRolesSelectMany() {
SelectItem[] items = new SelectItem[SecurityRole.values().length];
int i = 0;
for (SecurityRole role : SecurityRole.values()) {
items[i++] = new SelectItem(role, role.toString());
}
return items;
}
public List<SecurityRole> getRoles() {
getCurrent().getRoles();
}
public void setRoles(List<SecurityRole> roles) {
getCurrent().setRoles(roles);
}
当 JSF 调用 setRoles 方法时,它包含 String 类型的列表,而不是枚举类型。有什么想法吗?谢谢!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这个问题与枚举没有具体关系。对于 JSF 具有内置转换器的其他
List
类型,例如List
、List
等,您也会遇到同样的问题。问题是 EL 在运行时运行,并且通用类型信息在运行时丢失。因此本质上,JSF/EL 对
List
的参数化类型一无所知,并且默认为String
,除非由显式Converter
另行指定>。理论上,在ParameterizedType#getActualTypeArguments()
,但 JSF/EL 开发人员可能有他们不这样做的原因。您确实需要为此明确定义一个转换器。由于 JSF 已经附带了内置的
EnumConverter
(在这种特殊情况下不能独立使用,因为您必须在运行时指定枚举类型),您可以按如下方式扩展它:
并按如下方式使用它:
或者
更通用一点(和hacky)解决方案是将枚举类型存储为组件属性。
它可用于使用转换器 ID
genericEnumConverter
的各种List
。对于List
、List
等,可以使用内置转换器javax.faces.Double
、javax .faces.Integer
等等。顺便说一句,内置枚举转换器不合适,因为无法从视图侧指定目标枚举类型(Class
)。 JSF 实用程序库 OmniFaces 正是提供了此转换器开箱即用。请注意,对于普通的
Enum
属性,内置的EnumConverter
已经足够了。 JSF 将使用正确的目标枚举类型自动实例化它。This problem is not specifically related to enums. You would have the same problem with other
List
types for which JSF has builtin converters, e.g.List<Integer>
,List<Double>
, etcetera.The problem is that EL operates runtime and that generic type information is lost during runtime. So in essence, JSF/EL doesn't know anything about the parameterized type of the
List
and defaults toString
unless otherwise specified by an explicitConverter
. In theory, it would have been possible using nasty reflection hacks with help ofParameterizedType#getActualTypeArguments()
, but the JSF/EL developers may have their reasons for not doing this.You really need to explicitly define a converter for this. Since JSF already ships with a builtin
EnumConverter
(which isn't useable standalone in this particular case because you have to specify the enum type during runtime), you could just extend it as follows:And use it as follows:
or
A bit more generic (and hacky) solution would be to storing the enum type as component attribute.
It's useable on all kinds of
List<Enum>
using converter IDgenericEnumConverter
. ForList<Double>
,List<Integer>
, etc one would have used the builtin convertersjavax.faces.Double
,javax.faces.Integer
and so on. The builtin Enum converter is by the way unsuitable due to the inability to specify the target enum type (aClass<Enum>
) from the view side on. The JSF utility library OmniFaces offers exactly this converter out the box.Note that for a normal
Enum
property, the builtinEnumConverter
already suffices. JSF will instantiate it automagically with the right target enum type.在某些情况下,List 也可以是数组 SomeType[],在这种情况下,不需要显式转换器。
泛型擦除是将泛型放入语言中而不破坏旧东西的聪明方法,但现在我们永远生活在这个决定的后果中......
In some cases the List could just as well be an array SomeType[], and in this case no explicit converter is needed.
Generic erasure was a clever way of putting generics into the language without breaking the old stuff, but now we live forever with the consequences of that decision...