JSF 2.3+
您可以使用@Push and <f:websocket>为了这。下面是一个带有应用程序范围套接字的启动示例,它在后端通过以下方式触发事件时更新数据表Event#fire()哪个托管 bean@Observes.
<h:dataTable id="notifications" value="#{bean.notifications}" var="notification">
<h:column>#{notification.message}</h:column>
</h:dataTable>
<h:form>
<f:websocket channel="push">
<f:ajax event="updateNotifications" render=":notifications" />
</f:websocket>
</h:form>
@Named @ApplicationScoped
public class Bean {
private List<Notification> notifications;
@Inject
private NotificationService service;
@Inject @Push
private PushContext push;
@PostConstruct
public void load() {
notifications = service.list();
}
public void onNewNotification(@Observes Notification newNotification) {
notifications.add(0, newNotification);
push.send("updateNotifications");
}
public List<Notification> getNotifications() {
return notifications;
}
}
@Stateless
public class NotificationService {
@Inject
private EntityManager entityManager;
@Inject
private BeanManager beanManager;
public void create(String message) {
Notification newNotification = new Notification();
newNotification.setMessage(message);
entityManager.persist(newNotification);
beanManager.getEvent().fire(newNotification);
}
public List<Notification> list() {
return entityManager
.createNamedQuery("Notification.list", Notification.class)
.getResultList();
}
}
JSF 2.2-
如果您还没有使用 JSF 2.3,则需要使用第 3 方 JSF 库。
-
OmniFaces has <o:socket>(JSR356 WebSocket + CDI)
-
PrimeFaces had
<p:socket>
(气氛)
-
ICEfaces有“ICEpush”(长轮询)
应当指出的是,<o:socket>
是 JSF 2.3 的基础<f:websocket>
。因此,如果您发现了很多相似之处,那就是正确的。
PrimeFaces 用途气氛在幕后(如果没有 Maven,设置起来很麻烦)。 Atmosphere 支持 Websocket,并可回退到 SSE 和长轮询。 ICEfaces 基于古代长轮询技术。所有这些都没有实现本机 JSR356 WebSocket API,该 API 后来才在 Java EE 7 中引入。
OmniFaces 使用原生JSR356 WebSocket API(所有 Java EE 7 服务器和 Tomcat 7.0.27+ 均受支持)。因此,它的设置和使用也是最简单的(一个 JAR、一个上下文参数、一个标签和一个注释)。它只需要CDI(不难安装在 Tomcat 上),但它甚至使您能够从非 JSF 工件(例如@WebServlet
)。出于安全性和 JSF 视图状态保持原因,它仅支持单向推送(服务器到客户端),而不支持相反的方式。为此,您可以继续以通常的方式使用 JSF ajax。 JSF 2.3<f:websocket>
很大程度上基于 OmniFaces<o:socket>
,因此您会发现它们的 API 有很多相似之处(JSF - OmniFaces).
或者,您也可以使用轮询而不是推送。几乎每个支持 ajax 的 JSF 组件库都有一个<xxx:poll>
组件,例如 PrimeFaces<p:poll>。这允许您每 X 秒向服务器发送一个 ajax 请求,并在必要时更新内容。只是效率比push低而已。
也可以看看:
- 如何在 JSF 组件中监视异步/后台线程状态并获取通知
- 使用 JSF/Java EE 从数据库实时更新
- 当数据库中的某些内容发生修改时,仅通过 WebSocket 通知特定用户