您正在尝试将一个复杂的对象作为 HTTP 请求参数传递,该参数只能是String
。 JSF/EL 具有用于原语及其包装器的内置转换器(例如int
, Integer
)甚至枚举。但对于所有其他类型,您确实需要编写一个自定义转换器。在这种情况下,您需要编写一个转换器来在之间进行转换String
and Operation
. The String
然后用作选项值(在浏览器中打开页面,右键单击并查看源代码并注意<option value>
). The Operation
然后用作模型值。这String
应唯一标识Operation
目的。您可以为此使用操作 ID。
但在这种特殊情况下,有了这样一个硬编码的地图和一个相对简单的模型,我认为使用enum
反而。
public enum Operation {
DONATION("Donation"), EXCHANGE("Exchange");
private String label;
private Operation(String label) {
this.label = label;
}
public string getLabel() {
return label;
}
}
with
private Operation operation; // +getter +setter
public Operation[] getOperations() {
return Operation.values();
}
and
<h:selectOneMenu value="#{bean.operation}">
<f:selectItems value="#{bean.operations}" var="operation" itemValue="#{operation}" itemLabel="#{operation.label}" />
</h:selectOneMenu>
但如果这些值有actually要从数据库中检索并且其大小未定义,那么您仍然需要一个自定义转换器。你可以在getAsString()
返回 ID 并输入getAsObject()
使用操作 DAO/EJB 来获取Operation
通过身份证件。
@ManagedBean
@RequestScoped
public class OperationConverter implements Converter {
@EJB
private OperationService operationService;
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
// Convert here Operation object to String value for use in HTML.
if (!(value instanceof Operation) || ((Operation) value).getId() == null) {
return null;
}
return String.valueOf(((Operation) value).getId());
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// Convert here String submitted value to Operation object.
if (value == null || !value.matches("\\d+")) {
return null;
}
Operation operation = operationService.find(Long.valueOf(value));
if (operation == null) {
throw new ConverterException(new FacesMessage("Unknown operation ID: " + value));
}
return operation;
}
}
使用方法如下:
<h:selectOneMenu ... converter="#{operationConverter}">
至于为什么它是一个@ManagedBean
代替@FacesConverter
, 读这个:转换并验证 GET 请求参数 http://balusc.blogspot.com/2011/09/communication-in-jsf-20.html#ConvertingAndValidatingGETRequestParameters.
Update至于Validation Error: value not valid
错误,这意味着equals()
的方法Operation
类损坏或丢失。在验证期间,JSF 将提交的值与可用值列表进行比较Object#equals()
。如果列表中没有一个与提交的值匹配,那么您将看到此错误。所以,请确保equals()
得到正确实施。这是一个通过数据库技术特性进行比较的基本示例。
public boolean equals(Object other) {
return (other instanceof Operation) && (id != null)
? id.equals(((Operation) other).id)
: (other == this);
}
不要忘记实施hashCode()
还有:
public int hashCode() {
return (id != null)
? (getClass().hashCode() + id.hashCode())
: super.hashCode();
}