当我的h:inputText值绑定到从HashMap中收集的参数化类的某个实例的字段时,它不会被验证



我正在尝试做一些"自定义轻量级" JSF组件绑定。在我的bean(控制一些JSF页面)中,我声明了一个HahsMap,其中键范围超过我的h:inputText id(出现在页面中)将这些id映射到自定义HInputText<T>对象(T在下面的例子中是Long)。然后我使用HInputText<T>对象来保存相应的h: inputttext属性的子集:value应该是类型T, rendered, required等。在这个方向上,HInputText<T>对象的字段给h:inputText属性赋值。

我的问题是,当在h:form中使用这样的h:inputText时,JSF验证不会发生:我可以在h:inputText中键入字母数字字符(应该保存一个长值),并且我的表单提交而不会显示任何错误。请注意,requiredrendered属性被正确管理(因为required被设置为true,当我离开h:inputText字段为空时,我有一个错误),当我试图在使用一些h:outputText的页面中显示h:inputText的值时,显示字母数字字符。

是否有一些技巧可以使JSF验证工作,而不必为每个h:inputText显式地定义自定义Validator ?

HInputText.class:

public class HInputText<T>
{
    private String id;
    private boolean rendered;
    private boolean required;
    private T value;
    private Class<T> myClass;
    // getters and setters for all fields
    public HInputText(Class<T> myClass, String id)
    {
        this.myClass = myClass;
        this.id = id;
        this.rendered = true;
        this.required = true;
    }
}

管理Bean中的代码片段:

@ManagedBean(name="saisieController")
@SessionScoped
public class SaisieController
{
    ...
    private HashMap<String,HInputText<Long>> htagLongInputTexts;
    public HashMap<String, HInputText<Long>> getHtagLongInputTexts()
    {
        return htagLongInputTexts;
    }
    public void setHtagLongInputTexts(HashMap<String, HInputText<Long>> hLongInputTexts)
    {
        this.htagLongInputTexts = hLongInputTexts;
    }
    public void addHtagLongInputText(HInputText<Long> hLongInputText)
    {
        getHtagLongInputTexts().put(hLongInputText.getId(), hLongInputText);
    }
    public HInputText<Long> getHtagLongInputText(String hLongInputTextId)
    {
        return(getHtagLongInputTexts().get(hLongInputTextId));
    }

    @PostConstruct
    public void init()
    {
        setHtagLongInputTexts(new HashMap<String, HInputText<Long>>());
        addHtagLongInputText(new HInputText<Long>(Long.class, "HIT_LongTestHIT"));
    }
    public String doNothing()
    {
        return null;
    }
}

最后是JSF页面的一个片段:

<h:form>
    <h:inputText
        id = "HIT_LongTestHIT"
        value = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].value}"
        rendered = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].rendered}"
        required = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].required}"
    />
    <h:message for = "HIT_LongTestHIT" styleClass = "error-text" />
    <h:commandButton value = "submit" action = "#{saisieController.doNothing()}" />
    <h:outputText value = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].value}" />
</h:form>

是否有一些技巧可以使JSF验证工作而不必显式地为每个h:inputText定义自定义Validator ?

不,那不可能。由于类型擦除,泛型类型信息在运行时不可用。JSF/EL不知道T实际上是一个Long,更不用说实际上存在一些 T。您确实需要显式地指定一个转换器,在这个特定的示例中是LongConverter,转换器ID为javax.faces.Long

<h:inputText ... converter="javax.faces.Long">

或者动态的

<h:inputText ...>
    <f:converter converterId="#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].converterId}" />
</h:inputText>

您可以在javax.faces.convert包摘要中找到所有可用的标准JSF转换器的概述。您可以通过导航到公共常量CONVERTER_ID上的Constant字段值链接来查找它们的转换器id。

最新更新