介绍
JSF 生成 HTML。HTML 在 Java 术语中基本上是一大String
. 要在 HTML 中表示 Java 对象,必须将它们转换为String
. 此外,当提交 HTML 表单时,提交的值将被视为String
HTTP 请求参数中的值。在幕后,JSF 从HttpServletRequest#getParameter()
which return 中提取它们String
。
要在非标准 Java 对象之间进行转换(即不是String
,Number
或者Boolean
EL 具有内置转换,或者Date
/ LocalDate
/ ZonedDateTime
JSF 为其提供内置<f:convertDateTime>
标记),您确实必须提供自定义的Converter
. SelectItem
根本没有特殊用途。当无法List<Warehouse>
直接提供例如<f:selectItems>
. 它对标签和转换也没有特殊处理。
getAsString()
您需要以getAsString()
这样的方式实现方法,即所需的 Java 对象以唯一的 String
表示形式表示,该表示可以用作 HTTP 请求参数。通常,此处使用技术 ID(数据库主键)。
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
if (modelValue == null) {
return ""; // Never return null here!
}
if (modelValue instanceof Warehouse) {
return String.valueOf(((Warehouse) modelValue).getId());
} else {
throw new ConverterException(new FacesMessage(modelValue + " is not a valid Warehouse"));
}
}
请注意,在 null/空模型值的情况下返回空字符串很重要,并且javadoc需要:
返回:如果值为 null,则返回零长度字符串,否则为转换结果
否则生成的<option>
将没有value
属性,默认情况下将项目标签发送回getAsObject()
. 另请参阅在 ap:selectOneMenu 中使用具有空值/空值的“请选择” f:selectItem。
获取对象()
您需要以getAsObject()
这样的方式实现,即可以将由返回的表示完全转换回与中指定的完全相同的Java 对象。String
getAsString()
modelValue
getAsString()
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
if (submittedValue == null || submittedValue.isEmpty()) {
return null;
}
try {
return warehouseService.find(Long.valueOf(submittedValue));
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(submittedValue + " is not a valid Warehouse ID"), e);
}
}
换句话说,您必须在技术上能够将返回的对象作为modelValue
参数getAsString()
传回,然后在无限循环中将获得的字符串作为submittedValue
参数传回。getAsObject()
用法
最后只需注释Converter
with@FacesConverter
以挂钩有问题的对象类型,JSF 将在Warehouse
类型出现时自动处理转换:
@FacesConverter(forClass=Warehouse.class)
那是“规范的”JSF 方法。毕竟它不是很有效,因为它确实也可能只是从<f:selectItems>
. 但是a最重要的一点Converter
是它返回一个唯一的 String
表示,这样Java对象就可以被一个String
适合在HTTP和HTML中传递的简单标识。
基于 toString() 的通用转换器
JSF 实用程序库OmniFaces有一个SelectItemsConverter
基于toString()
实体结果的工作。这样您就不再需要摆弄getAsObject()
昂贵的业务/数据库操作了。有关一些具体的使用示例,另请参见展示。
要使用它,只需将其注册如下:
<h:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
并确保toString()
您的Warehouse
实体返回实体的唯一表示。例如,您可以直接返回 ID:
@Override
public String toString() {
return String.valueOf(id);
}
或者更具可读性/可重用性的东西:
@Override
public String toString() {
return "Warehouse[id=" + id + "]";
}
也可以看看:
与问题无关,因为 JSF 2.0 不再明确要求具有List<SelectItem>
as<f:selectItem>
值。一个List<Warehouse>
也足够了。
<h:selectOneMenu value="#{bean.selectedWarehouse}">
<f:selectItem itemLabel="Choose one .." itemValue="#{null}" />
<f:selectItems value="#{bean.availableWarehouses}" var="warehouse"
itemLabel="#{warehouse.name}" itemValue="#{warehouse}" />
</h:selectOneMenu>
private Warehouse selectedWarehouse;
private List<Warehouse> availableWarehouses;