JSF之AJAX

JSF框架在其规范中提供了对AJAX(Asynchronous JavaScript and XML)的内建支持,开发者可以通过AJAX技术实现动态和交互式的用户界面,而无需手动处理复杂的JavaScript代码,这使得使用JSF来开发富客户端应用程序变得更加容易和高效。这篇笔记我们学习如何基于JSF框架实现AJAX。

AJAX提交数据

JSF中使用AJAX涉及到<f:ajax>标签,下面例子代码中,我们点击按钮就会触发AJAX操作,对应字段的值会被更新到ManagedBean中。

package com.gacfox.demo.demojsf.controller;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named("noteBook")
@RequestScoped
public class NoteBookManagedBean {
    private String note;

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
        System.out.println("更新了数据: " + note);
    }
}

代码中NoteBookManagedBean我们维护了一个字段note,其中触发setNote()方法时我们除了将值设置到属性,还会额外打印新的值。

<?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:f="http://java.sun.com/jsf/core">
<h:head>
    <title>JSF Demo</title>
</h:head>
<h:body>
    <h:form>
        <h:inputText id="note" value="#{noteBook.note}"/>
        <h:commandButton value="btn">
            <f:ajax execute="note"/>
        </h:commandButton>
    </h:form>
</h:body>
</html>

在视图层,我们使用了<f:ajax execute="note"/>,该标签用于AJAX更新,其中execute属性表示要更新的字段名,它对应于<h:inputText>id属性,此时我们点击按钮时,对应ManagedBean的setNote()方法就会被触发,此时我们就实现了AJAX提交数据。

通过观察Firefox浏览器的调试工具,我们可以看到JSF框架AJAX请求的格式为表单,响应格式采用了XML。当然这些交互数据都是自动处理的,我们其实可以不必关心数据具体是怎样传输的。

此外,我们还可以发现实际上JSF会加载一个JavaScript文件jsf.js.faces,AJAX相关的功能其实都包含在这个页面脚本中。

AJAX局部更新

前面代码实现了AJAX提交数据,不过实际开发中数据提交后通常都要更新一些列表或是表格,这些页面的更新是局部的,它们并非页面刷新整个HTML文档重新加载而是通过页面上的JavaScript脚本的DOM操作实现的,JSF框架的AJAX局部更新功能可以实现这个需求而不必我们手写JavaScript。

下面例子中我们实现一个TodoList程序,用户提交的数据会以列表形式展示。

package com.gacfox.demo.demojsf.controller;

import com.gacfox.demo.demojsf.service.NoteService;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;

@Named("noteBook")
@RequestScoped
public class NoteBookManagedBean {
    @Inject
    private NoteService noteService;

    private String note;

    public List<String> getNoteList() {
        return noteService.getAllNotes();
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public void addNote() {
        noteService.addNote(note);
    }
}

上面代码中,我们的ManagedBean维护了一个noteList属性,它用于展示我们提交的内容列表;note属性则和之前相同,对应于表单的输入框。此外我们还添加了一个addNote()方法,它用于向noteList添加一个字符串内容。

<?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:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
    <title>JSF Demo</title>
</h:head>
<h:body>
    <h:panelGroup id="noteList">
        <ui:repeat value="#{noteBook.noteList}" var="note">
            <h:outputText value="#{note}"/><br/>
        </ui:repeat>
    </h:panelGroup>
    <h:form>
        <h:inputText id="note" value="#{noteBook.note}"/>
        <h:commandButton value="btn" actionListener="#{noteBook.addNote()}">
            <f:ajax execute="note" render="noteList"/>
        </h:commandButton>
    </h:form>
</h:body>
</html>

XHTML视图中,和之前相比我们添加了一个<h:panelGroup>,其中展示了一个列表对应于ManagedBean中的noteList,我们的按钮还添加了一个actionListener属性,它表示提交时ManagedBean的addNote()方法也会被触发。

<f:ajax>标签中,我们依然声明了更新ManagedBean的note字段,此外我们还使用了render属性,它对应于局部更新的组件ID,这里我们将其设置为noteList,对应于<h:panelGroup>,此时表单提交后,页面上的列表就会更新。

此时运行效果如下。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。