如何在 JSF 中执行验证,如何在 JSF 中创建自定义验证器
Posted
技术标签:
【中文标题】如何在 JSF 中执行验证,如何在 JSF 中创建自定义验证器【英文标题】:How to perform validation in JSF, how to create a custom validator in JSF 【发布时间】:2011-08-28 05:15:24 【问题描述】:我想使用一些 Java bean 方法在我的一些输入组件中执行验证,例如 <h:inputText>
。我应该为此使用<f:validator>
还是<f:validateBean>
?我在哪里可以了解更多信息?
【问题讨论】:
【参考方案1】:标准方式是实现Validator
接口。
@FacesValidator("fooValidator")
public class FooValidator implements Validator
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
// ...
if (valueIsInvalid)
throw new ValidatorException(new FacesMessage("Value is invalid!"));
@FacesValidator
会将其注册到具有验证器 ID myValidator
的 JSF,以便您可以在任何 <h:inputXxx>
/<h:selectXxx>
组件的 validator
属性中引用它,如下所示:
<h:inputText id="foo" value="#bean.foo" validator="fooValidator" />
<h:message for="foo" />
只要验证器抛出ValidatorException
,其消息就会显示在与输入字段关联的<h:message>
中。
您还可以在任何 <h:inputXxx>
/<h:selectXxx>
组件的 validator
属性中使用 EL,其中您引用的托管 bean 方法具有与 Validator#validate()
完全相同的方法签名(相同的方法参数)。 IE。按此顺序获取FacesContext
、UIComponent
和Object
参数。
<h:inputText id="foo" value="#bean.foo" validator="#bean.validateFoo" />
<h:message for="foo" />
public void validateFoo(FacesContext context, UIComponent component, Object value) throws ValidatorException
// ...
if (valueIsInvalid)
throw new ValidatorException(new FacesMessage("Value is invalid!"));
这仅在验证器需要访问同一托管 bean 中存在的另一个属性时才有用。如果不需要,那么这种方法被认为是紧耦合(因此是不好的做法),您应该将验证器拆分为实现Validator
接口的自己的类。
您也可以使用<f:validator>
taghandler,如果您打算在同一个组件上附加多个验证器,这是唯一的方法:
<h:inputText id="foo" value="#bean.foo">
<f:validator validatorId="fooValidator" />
</h:inputText>
<h:message for="foo" />
这将执行上面显示的@FacesValidator("fooValidator")
。
您还可以使用<f:validator binding>
来引用 EL 范围内某处的具体验证器实例,可以通过以下方式指定和提供该实例:
<h:inputText id="foo" value="#bean.foo">
<f:validator binding="#fooValidator" />
</h:inputText>
<h:message for="foo" />
@Named("fooValidator")
public class FooValidator implements Validator
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
// ...
if (valueIsInvalid)
throw new ValidatorException(new FacesMessage("Value is invalid!"));
请注意,因此使用的是@Named
而不是@FacesValidator
。这里也支持旧的@ManagedBean
,而不是@Named
。从历史上看,这是一个技巧,以便能够在验证器中使用 @EJB
和 @Inject
。另见How to inject in @FacesValidator with @EJB, @PersistenceContext, @Inject, @Autowired
或者这种方式,反过来可以很容易地作为 lambda 提供:
<h:inputText id="foo" value="#bean.foo">
<f:validator binding="#bean.fooValidator" />
</h:inputText>
<h:message for="foo" />
public Validator getFooValidator()
return (context, component, value) ->
// ...
if (valueIsInvalid)
throw new ValidatorException(new FacesMessage("Value is invalid!"));
;
当这个验证器不需要来自同一个 bean 的任何其他属性时,这里也会应用相同的紧耦合问题。
为了更进一步,您可以使用 JSR303 bean 验证。这会根据注释验证字段。所以你可以有一个
@Foo
private String foo;
无需在 Xhtml 端显式注册任何验证器。如果您使用 JPA 进行持久性,默认情况下,此验证器也将在数据库中插入/更新期间执行。由于这将是一个完整的故事,这里只是一些开始的链接:
Hibernate Validator - Getting started JSF 2.0 tutorial - Finetuning validation还有一个<f:validateBean>
标记,但这仅在您打算禁用 JSR303 bean 验证时有用。然后将输入组件(甚至整个表单)放入<f:validateBean disabled="true">
。
另见:
JSF doesn't support cross-field validation, is there a workaround? How to perform JSF validation in actionListener or action method?【讨论】:
以上是关于如何在 JSF 中执行验证,如何在 JSF 中创建自定义验证器的主要内容,如果未能解决你的问题,请参考以下文章