1. 概述

Java Enterprise Edition (JEE) 7 提供了几个实用特性,比如用于验证用户输入、将值转换为适当 Java 数据类型的功能。

本教程将重点介绍转换器、监听器和验证器提供的这些特性。

2. 转换器

转换器允许我们将字符串输入值转换为 Java 数据类型。预定义的转换器位于 javax.faces.convert 包中,它们兼容任何 Java 数据类型,甚至像 Date 这样的标准类。

2.1 整数转换器

首先在托管 bean 中定义属性(作为 JSF 表单的后端):

private Integer age;
     
// getters and setters

然后在表单中使用 f:converter 标签创建组件:

<h:outputLabel value="Age:"/>
<h:inputText id="Age" value="#{convListVal.age}">
    <f:converter converterId="javax.faces.Integer" />
</h:inputText>
<h:message for="Age" />

2.2 双精度转换器

类似地创建其他数值转换器(如 Double 转换器):

private Double average;

在视图中创建对应的 JSF 组件(注意通过命名约定映射字段):

<h:outputLabel value="Average:"/>
<h:inputText id="Average" value="#{convListVal.average}">
    <f:converter converterId="javax.faces.Double" />
</h:inputText>
<h:message for="Average" />

⚠️ 重要提示:若要向用户提供反馈,必须包含 h:message 标签作为错误消息的占位符。

2.3 日期时间转换器

DateTime 转换器特别实用,因为它能验证日期/时间并格式化这些值。

首先在托管 bean 中声明字段:

private Date myDate;
// getters and setters

在视图中创建组件(必须使用模式输入日期,否则会报错):

<h:outputLabel value="Date:"/>
<h:inputText id="MyDate" value="#{convListVal.myDate}">
    <f:convertDateTime pattern="dd/MM/yyyy" />
</h:inputText>
<h:message for="MyDate" />
<h:outputText value="#{convListVal.myDate}">
    <f:convertDateTime dateStyle="full" locale="en"/>
</h:outputText>

✅ 这里我们将输入日期转换后,通过 h:outputText 以完整日期格式输出。

3. 监听器

监听器允许我们监控组件值的变化(例如文本框内容改变时)。

3.1 基本实现

在托管 bean 中定义属性:

private String name;

在视图中定义监听器:

<h:outputLabel value="Name:"/>
<h:inputText id="name" size="30" value="#{convListVal.name}">
    <f:valueChangeListener type="com.baeldung.convListVal.MyListener" />
</h:inputText>

通过 f:valueChangeListener 指定监听器类,当触发时执行任务:

public class MyListener implements ValueChangeListener {
    private static final Logger LOG = Logger.getLogger(MyListener.class.getName());    
        
    @Override
    public void processValueChange(ValueChangeEvent event)
      throws AbortProcessingException {
        if (event.getNewValue() != null) {
            LOG.log(Level.INFO, "\tNew Value:{0}", event.getNewValue());
        }
    }
}

踩坑提醒:监听器类必须实现 ValueChangeListener 接口并重写 processValueChange() 方法。

4. 验证器

验证器用于验证 JSF 组件数据,JSF 提供了标准验证类来检查用户输入。

4.1 长度验证器

以下示例验证文本框输入长度:

首先在托管 bean 中创建字段:

private String surname;

在视图中创建组件:

<h:outputLabel value="surname" for="surname"/>
<h:panelGroup>
    <h:inputText id="surname" value="#{convListVal.surname}">
        <f:validateLength minimum="5" maximum="10"/>
    </h:inputText>
    <h:message for="surname" errorStyle="color:red"  />
</h:panelGroup>

h:inputText 标签内嵌入验证器限制输入长度。JSF 预定义了多种标准验证器,用法类似。

5. 测试

我们将使用 Arquillian 结合 Drone、Graphene 和 Selenium WebDriver 进行功能测试。

5.1 部署配置

使用 ShrinkWrap 部署应用:

@Deployment(testable = false)
public static WebArchive createDeployment() {
    return (ShrinkWrap.create(
      WebArchive.class, "jee7.war").
      addClasses(ConvListVal.class, MyListener.class)).
      addAsWebResource(new File(WEBAPP_SRC, "ConvListVal.xhtml")).
      addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}

5.2 错误消息测试

验证各组件错误消息确保应用正常工作:

@Test
@RunAsClient
public void givenAge_whenAgeInvalid_thenErrorMessage() throws Exception {
    browser.get(deploymentUrl.toExternalForm() + "ConvListVal.jsf");
    ageInput.sendKeys("stringage");
    guardHttp(sendButton).click();
    assertTrue("Show Age error message",
      browser.findElements(By.id("myForm:ageError")).size() > 0);
}

类似测试需对每个组件执行。

6. 总结

本教程实现了 JEE7 提供的转换器、监听器和验证器功能。关键要点:

转换器:解决字符串到 Java 类型的转换问题
监听器:实时监控组件值变化
验证器:确保输入数据符合业务规则
常见陷阱:忘记添加 h:message 标签会导致错误信息不显示

完整代码可在 GitHub 获取。


原始标题:Converters, Listeners and Validators in Java EE 7