/Registration.xhtml @19,81 validator="#{UsernameValidator}": Identity 'UsernameValidator' 为空,无法调用
/Registration.xhtml @19,81 validator="#{UsernameValidator}": Identity 'UsernameValidator' was null and was unable to invoke
这是我的项目结构:
这是在我的 XHTML 文件中:
<h:inputText id="username" value="#{user.username}" required="true"
validator="#{UsernameValidator}" />
<h:message for="username"/>
这里是 UsernameValidator
class:
@FacesValidator("UsernameValidator")
public class UsernameValidator implements Validator {
@Override
public void validate(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
但是当我在 username
字段中写东西时,会发生此错误:
/Registration.xhtml @19,81 validator="#{UsernameValidator}": Identity 'UsernameValidator' was null and was unable to invoke
您的 Registration.xhtml 文件似乎有问题。验证器需要在 标签内有一个单独的标签:
<h:inputText id="username" value="#{user.username}" required="true">
<f:validator validatorId="UsernameValidator" />
</h:inputText>
<h:message for="username" />
您遇到的错误似乎是由于 JSF 无法找到验证 bean 引起的。您的项目目录看起来不错,但请检查以确保 UsernameValidator 的 class 文件存在并且可以被您的应用服务器读取。
由于你的问题稍作修改,我在与你原问题相关的内容处添加了删除线:
首先,除了使用自定义组件之外,应用程序级别的验证还包括第 3 点和第 4 点(使用 Validator 接口和支持 bean 中的验证方法的自定义验证)。
您似乎混淆了使用 bean 方法的验证和实现自定义验证器 classes(最后两个),以您的代码为例快速回顾一下这两种方法:
使用 bean 方法验证:
这是最简单的一个,因为您只需要向您的 class 添加验证方法并使用 validator
属性通过方法表达式调用它,就像您的示例一样:
<h:inputText id="username" value="#{user.username}" required="true" validator="#{usernameValidator}" />
// I changed to usernameValidator to respect naming conventions
但是,在那种情况下,usernameValidator
是 user
@ManagedBean
中的一个方法,像这样:
@ManagedBean("user")
@SessionScoped
public class User implements Serializable{
// Please notice that this method should have the same signature as the validate method of the interface Validator
public void usernameValidator(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
自定义验证器 Classes:
Class 的实现与您所做的相同,即实现 Validator
接口,并通过给它和 ID
、 [=73 来注册验证器=]我会复制你的确切代码以使答案干净:
// I just changed the ID from UsernameValidator to usernameValidator
@FacesValidator("usernameValidator")
public class UsernameValidator implements Validator {
@Override
public void validate(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
您可以通过使用注释 @FacesValidator("usernameValidator")
(您已经这样做了)将 ID
和 ID
提供给您的验证器,或 在 faces-config.xml
通过添加以下内容:
<validator>
<validator-id>usernameValidator</validator-id>
<validator-class>yourpackage.UsernameValidator</validator-class>
</validator>
然后,您将在 f:validator
标签中使用相同的 ID
,如下所示:
<h:inputText id="username" value="#{user.username}" required="true">
<f:validator validatorId="usernameValidator" />
</h:inputText>
注意:这是不是JSF中的所有验证方法,但我认为这两个是自定义验证最简单的方法您可以在您的示例中使用 (它分别是您提供的 JSF 验证方式列表中的 4 和 3).
作为附加信息,我还将简要回顾一下 不适合 的内置验证组件代码示例:
内置验证组件:
JSF(我说的是 2.0,因为我不确定 JSF 2.2 中是否有一些新的)具有可用于验证的标准验证器:
String
的长度使用f:validateLength
- 一个
double
/long
值在可选范围内分别使用f:validateDoubleRange
/f:validateLongRange
。
- A
String
使用 f:validateRegex
对抗正则表达式
- 使用
f:validateRequired
或属性 required
的必需值
还有另一种方法可以使用 f:validator
使用这些标签,您可以找到 good example here。
另请参阅:
你的错误在这里:
<h:inputText ... validator="#{UsernameValidator}" />
您正在尝试将 @FacesValidator
引用为托管 bean。这行不通。 @FacesValidator
注释中的值代表应用程序范围的验证器 ID,它被指定为一个字符串,而不是托管 bean 名称。
所以,下面应该做:
<h:inputText ... validator="UsernameValidator" />
是的,您可能已经看到代码片段,其中通过 #{...}
将验证器(或转换器)引用为托管 bean。但在那些情况下,它们 实际上 也通过 @ManagedBean
或 @Named
而不是 @FacesValidator
(或 @FacesConverter
)注册为托管 bean .
@ManagedBean
@RequestScoped
public class UsernameValidator implements Validator {}
通常这样做是为了能够将 EJB 注入其中,以便可以执行任何必要的 business/DB 逻辑。
另请参阅:
- How to inject in @FacesValidator with @EJB, @PersistenceContext, @Inject, @Autowired
与具体问题无关:以下
JOptionPane.showMessageDialog(null, "in validator class");
在 web 应用程序中执行“日志记录”是一种非常、非常 糟糕的方法。请停止这样做。
这是我的项目结构:
这是在我的 XHTML 文件中:
<h:inputText id="username" value="#{user.username}" required="true"
validator="#{UsernameValidator}" />
<h:message for="username"/>
这里是 UsernameValidator
class:
@FacesValidator("UsernameValidator")
public class UsernameValidator implements Validator {
@Override
public void validate(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
但是当我在 username
字段中写东西时,会发生此错误:
/Registration.xhtml @19,81 validator="#{UsernameValidator}": Identity 'UsernameValidator' was null and was unable to invoke
您的 Registration.xhtml 文件似乎有问题。验证器需要在
<h:inputText id="username" value="#{user.username}" required="true">
<f:validator validatorId="UsernameValidator" />
</h:inputText>
<h:message for="username" />
您遇到的错误似乎是由于 JSF 无法找到验证 bean 引起的。您的项目目录看起来不错,但请检查以确保 UsernameValidator 的 class 文件存在并且可以被您的应用服务器读取。
由于你的问题稍作修改,我在与你原问题相关的内容处添加了删除线:
首先,除了使用自定义组件之外,应用程序级别的验证还包括第 3 点和第 4 点(使用 Validator 接口和支持 bean 中的验证方法的自定义验证)。
您似乎混淆了使用 bean 方法的验证和实现自定义验证器 classes(最后两个),以您的代码为例快速回顾一下这两种方法:
使用 bean 方法验证:
这是最简单的一个,因为您只需要向您的 class 添加验证方法并使用 validator
属性通过方法表达式调用它,就像您的示例一样:
<h:inputText id="username" value="#{user.username}" required="true" validator="#{usernameValidator}" />
// I changed to usernameValidator to respect naming conventions
但是,在那种情况下,usernameValidator
是 user
@ManagedBean
中的一个方法,像这样:
@ManagedBean("user")
@SessionScoped
public class User implements Serializable{
// Please notice that this method should have the same signature as the validate method of the interface Validator
public void usernameValidator(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
自定义验证器 Classes:
Class 的实现与您所做的相同,即实现 Validator
接口,并通过给它和 ID
、 [=73 来注册验证器=]我会复制你的确切代码以使答案干净:
// I just changed the ID from UsernameValidator to usernameValidator
@FacesValidator("usernameValidator")
public class UsernameValidator implements Validator {
@Override
public void validate(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
您可以通过使用注释 @FacesValidator("usernameValidator")
(您已经这样做了)将 ID
和 ID
提供给您的验证器,或 在 faces-config.xml
通过添加以下内容:
<validator>
<validator-id>usernameValidator</validator-id>
<validator-class>yourpackage.UsernameValidator</validator-class>
</validator>
然后,您将在 f:validator
标签中使用相同的 ID
,如下所示:
<h:inputText id="username" value="#{user.username}" required="true">
<f:validator validatorId="usernameValidator" />
</h:inputText>
注意:这是不是JSF中的所有验证方法,但我认为这两个是自定义验证最简单的方法您可以在您的示例中使用 (它分别是您提供的 JSF 验证方式列表中的 4 和 3).
作为附加信息,我还将简要回顾一下 不适合 的内置验证组件代码示例:
内置验证组件:
JSF(我说的是 2.0,因为我不确定 JSF 2.2 中是否有一些新的)具有可用于验证的标准验证器:
String
的长度使用f:validateLength
- 一个
double
/long
值在可选范围内分别使用f:validateDoubleRange
/f:validateLongRange
。 - A
String
使用f:validateRegex
对抗正则表达式
- 使用
f:validateRequired
或属性required
的必需值
还有另一种方法可以使用 f:validator
使用这些标签,您可以找到 good example here。
另请参阅:
你的错误在这里:
<h:inputText ... validator="#{UsernameValidator}" />
您正在尝试将 @FacesValidator
引用为托管 bean。这行不通。 @FacesValidator
注释中的值代表应用程序范围的验证器 ID,它被指定为一个字符串,而不是托管 bean 名称。
所以,下面应该做:
<h:inputText ... validator="UsernameValidator" />
是的,您可能已经看到代码片段,其中通过 #{...}
将验证器(或转换器)引用为托管 bean。但在那些情况下,它们 实际上 也通过 @ManagedBean
或 @Named
而不是 @FacesValidator
(或 @FacesConverter
)注册为托管 bean .
@ManagedBean
@RequestScoped
public class UsernameValidator implements Validator {}
通常这样做是为了能够将 EJB 注入其中,以便可以执行任何必要的 business/DB 逻辑。
另请参阅:
- How to inject in @FacesValidator with @EJB, @PersistenceContext, @Inject, @Autowired
与具体问题无关:以下
JOptionPane.showMessageDialog(null, "in validator class");
在 web 应用程序中执行“日志记录”是一种非常、非常 糟糕的方法。请停止这样做。