服务器如何将异步更改推送到由 JSF 创建的 HTML 页面? [英] How can server push asynchronous changes to a HTML page created by JSF?

查看:23
本文介绍了服务器如何将异步更改推送到由 JSF 创建的 HTML 页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我们创建 JSF 页面时,客户端请求允许使用 Java 代码和 HTML 的组合动态生成 HTML.我们是否可以使用 JSF 框架在 HTML 页面中引入钩子,允许服务器根据稍后在服务器上发生的异步事件更新 HTML 页面,通常是通过不同的线程?

When we create a JSF page, a client request allows generation of HTML dynamically using a combination of Java code and HTML. Can we introduce hooks in the HTML page using JSF framework, that allow server to update the HTML page based on asynchronous events occurring later at the server, usually via different threads?

推荐答案

JSF 2.3+

您可以使用@Push 为此.下面是一个启动示例,它根据后端触发的应用程序范围的事件更新数据表.

JSF 2.3+

You can use @Push and <f:websocket> for this. Below is a kickoff example which updates a data table upon an application scoped event fired by the backend.

<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.fireEvent(newNotification);
    }

    public List<Notification> list() {
        return entityManager
            .createNamedQuery("Notification.list", Notification.class)
            .getResultList();
    }

}

JSF 2.2-

如果您还没有使用 JSF 2.3,则需要前往 3rd 方 JSF 库.

JSF 2.2-

If you're not on JSF 2.3 yet, you need to head to 3rd party JSF libraries.

  • OmniFaces has <o:socket> (JSR356 WebSocket + CDI)
  • PrimeFaces has <p:socket> (Atmosphere)
  • ICEfaces has ICEpush (long polling)

应该注意的是, 是 JSF 2.3 的基础.所以如果你发现了很多相似之处,那就对了.

Noted should be that the <o:socket> was the basis for the JSF 2.3 <f:websocket>. So if you have found a lot of similarities, then that's correct.

PrimeFaces 在幕后使用 Atmosphere(在没有 Maven 的情况下设置起来很麻烦).Atmosphere 支持具有回退到 SSE 和长轮询的 websocket.ICEfaces 基于古老的长轮询技术.所有这些都没有实现本机 JSR356 WebSocket API,后者后来才在 Java EE 7 中引入.

PrimeFaces uses Atmosphere under the hoods (which is troublesome to setup without Maven). Atmosphere supports websockets with fallback to SSE and long polling. ICEfaces is based on ancient long polling technique. All of those do not implement native JSR356 WebSocket API which was only later introduced in 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 主要基于 OmniFaces ,因此您会在它们的 API(JSF - OmniFaces).

OmniFaces uses native JSR356 WebSocket API (supported in all Java EE 7 servers and Tomcat 7.0.27+). It is therefore also most simple to setup and use (one JAR, one context param, one tag and one annotation). It only requires CDI (not hard to install on Tomcat), but it enables you to even push from a non-JSF artifact on (e.g. a @WebServlet). For security and JSF view state keeping reasons, it only supports one-way push (server to client), not the other way round. For that you can keep using JSF ajax the usual way. The JSF 2.3 <f:websocket> is largely based on OmniFaces <o:socket>, hence you'll find a lot of similarities in their APIs (JSF - OmniFaces).

或者,您也可以使用轮询代替推送.几乎每个支持 ajax 的 JSF 组件库都有一个 <xxx:poll> 组件,例如 PrimeFaces 和 .这允许您每 X 秒向服务器发送一个 ajax 请求,并在必要时更新内容.它只比推送效率低.

Alternatively, you can also use polling instead of pushing. Pretty much every ajax aware JSF component library has a <xxx:poll> component, such as PrimeFaces with <p:poll>. This allows you to send every X seconds an ajax request to the server and update the content whenever necessary. It's only less efficient than push.

这篇关于服务器如何将异步更改推送到由 JSF 创建的 HTML 页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆