我们最近将我们的系统从 JSF 1.2 升级到 JSF 2.0,并且正在使一切正常工作。但是,当在数据表或类似组件中使用验证器时,我们遇到了问题。基本上,问题是验证器无法使用数据表设置的变量。
这是一个例子:
验证器:
package test;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
@FacesValidator("test.TestValidator")
public class TestValidator implements Validator {
    private Integer length;
    public TestValidator() {
        super();
    }
    @Override
    public void validate(FacesContext context,
            UIComponent component, Object value) throws ValidatorException {
        String text = (String) value;
        if (text == null || text.trim().length() == 0) {
            return;
        }
        if (length != null && text != null && length.intValue() < text.length()) {
            String message = "The text is too long. It was " + text.length() +
                    ", but only " + length + " characters are allowed.";
            FacesMessage fm = new FacesMessage(
                    FacesMessage.SEVERITY_ERROR, message, null);
            throw new ValidatorException(fm);
        }
    }
    public Integer getLength() {
        return length;
    }
    public void setLength(Integer length) {
        this.length = length;
    }
}
标签:
<?xml version="1.0" encoding="UTF-8"?>
    <facelet-taglib
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
         version="2.0">
        <namespace>http://industry-supply.dk/test</namespace>
        <tag>
            <tag-name>testValidator</tag-name>
            <validator>
                <validator-id>test.TestValidator</validator-id>
            </validator>
            <attribute>
                <name>length</name>
                <required>true</required>
                <type>java.lang.Integer</type>
            </attribute>
        </tag>
    </facelet-taglib>
管理豆:
package test;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean(name = "testBean")
@RequestScoped
public class TestBean {
    public TestBean() {
    }
    public String[] getKey() {
        return new String[]{
                    "0",
                    "1",
                    "2",
                    "3"
                };
    }
    public String[] getValue() {
        return new String[]{
                    "This is a text and it's too long.",
                    "This is a text and it's too long.",
                    "This is a text and it's too long.",
                    "This is a text and it's too long."
                };
    }
}
JSF:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:test="http://industry-supply.dk/test">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:dataTable value="#{testBean.key}" var="k">
                <h:column>
                    <h:message for="val"/>
                    <h:inputText id="val" value="#{testBean.value[k]}">
                        <test:testValidator length="#{testBean.key[k]}"/>
                    </h:inputText>
                </h:column>
            </h:dataTable>
            <h:commandButton value="Submit"/>
        </h:form>
    </h:body>
</html>
运行项目时,会显示 4 个输入字段和一个命令按钮。每个输入字段包含一个 33 个字符长的文本。单击“提交”时,错误消息“文本太长。它是 33,但只允许 0 个字符。” 为每一行/字段显示。这是错误的,因为 "test:testValidator length="#{testBean.key[k]}"" 将第一行的长度指定为 0,第二行指定为 1,第三行指定为 2,第四行指定为 3。所以对于最后一行,错误信息应该是:“文本太长。它是 33,但只允许 3 个字符。”。
问题是验证器似乎无法从 JSF 文件中的 dataTable 组件访问 k 变量。这在 JSF 1.2 中有效,但我们无法让它在 JSF 2.0 中有效。我们已经花了几天时间解决这个问题,真的需要一些帮助。任何人的想法?