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>,此时表单提交后,页面上的列表就会更新。
此时运行效果如下。
