自定义验证程序类不起作用

Him*_*waj 4 java cdi jsf-2

我在这里有一个问题:

场景: 我有一个JSF-2,Spring(Beans wiring)应用程序.我写了一个自定义验证器,我想执行它.

@FacesValidator("com.test.vali")
@Named("com.test.vali")
public class TestValidator implements Validator {

    @Override
    public void validate(FacesContext arg0, UIComponent arg1, Object arg2) throws ValidatorException {
        System.out.println("dhkdfkbhdfbkdfksdfdfk");

    }

}
Run Code Online (Sandbox Code Playgroud)

我试图使用以下方式注入验证器:

方法1:

  <h:inputText value="#{helloWorld.name}">
      <f:validator binding="#{com.test.vali}" />
  </h:inputText>
Run Code Online (Sandbox Code Playgroud)

产量

当试图渲染页面时,它抛出异常.

javax.servlet.ServletException: /testRichFaces.xhtml @17,48 <f:validator> A validator id was not specified. Typically the validator id is set in the constructor ValidateHandler(ValidatorConfig)
Run Code Online (Sandbox Code Playgroud)

在此搜索了很多,并验证了几种方式:

  1. Java文件在一个包中.

路#2

 <f:validator validatorId="com.test.vali" />
Run Code Online (Sandbox Code Playgroud)

产量

javax.servlet.ServletException: Expression Error: Named Object: com.test.vali not found.
Run Code Online (Sandbox Code Playgroud)

所以从方式#1和方式#2,我可以解释没有任何注释对我有用.

然后,我试图转到最后一种方法:

方式#3:在faces-config.xml中添加验证器,只是为了表明我使用2.0兼容性:

<faces-config 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-facesconfig_2_0.xsd"
version="2.0">
Run Code Online (Sandbox Code Playgroud)

验证器配置是:

 <validator>
       <validator-id>com.test.vali</validator-id>
       <validator-class>teet.TestValidator</validator-class>
 </validator>
Run Code Online (Sandbox Code Playgroud)

产量

作品

现在问题出现了,即使使用JSF-2.0,我也不得不求助于faces-config.xml.

我在做什么可能是个错误?

让我们知道是否需要更多配置.

Bal*_*usC 10

首先,您基本上混合了两种注册验证器实例的方法,它们完全独立地工作:通过注册为面验证器@FacesValidator,或者注册为CDI管理bean @Named.这些注释彼此不了解,也没有考虑到彼此.您基本上最终会得到两个完全不同的实例,这些实例不会彼此共享数据.为避免将来出现混淆,因此强烈建议删除其中一个注释,以便保证始终使用同一个实例.

至于为什么方式1失败:

@Named("com.test.vali")
public class TestValidator implements Validator {
    // ...
}
Run Code Online (Sandbox Code Playgroud)
<f:validator binding="#{com.test.vali}" />
Run Code Online (Sandbox Code Playgroud)

这是因为句点.是EL中的一个特殊运算符,表示bean属性访问或bean方法调用.使用#{com.test.vali}只会查找一个bean #{com},然后查找其test属性,然后查找其vali属性.换句话说,它基本上试图获得通过验证com.getTest().getVali()哪里com是CDI托管bean像这样 @Named("com").

这不是你想要的.摆脱名称中的那些时期.更好,只需坚持默认实例名称,testValidator.这是最明智的选择,当然,如果你给你的班级合理的名字.

@Named
public class TestValidator implements Validator {
    // ...
}
Run Code Online (Sandbox Code Playgroud)
<f:validator binding="#{testValidator}" />
Run Code Online (Sandbox Code Playgroud)

至于为什么方式2失败:

@FacesValidator("com.test.vali")
public class TestValidator implements Validator {
    // ...
}
Run Code Online (Sandbox Code Playgroud)
<f:validator validatorId="com.test.vali" />
Run Code Online (Sandbox Code Playgroud)

@FacesValidator在启动期间未正确拾取时可能会发生这种情况.当有问题的类不在WAR内部,而是在例如EAR或EJB内部时,这可能反过来发生.在这种情况下,您需要在中明确注册验证器faces-config.xml.但更好的方法是将类放在WAR中,您应该在项目的EAR或EJB部分中绝对没有任何JSF工件.它会将模型/服务逻辑(JPA,EJB等)紧密耦合到视图(JSF),并使其不再可用于其他视图(前端),如JAX-RS,Spring MVC,Struts2等.