如何从服务器向客户端发送消息?

Posted

技术标签:

【中文标题】如何从服务器向客户端发送消息?【英文标题】:How to send messages from server to client? 【发布时间】:2013-06-24 13:55:08 【问题描述】:

我将实现类似于 Facebook 通知和此网站的功能(*** 的通知会通知我们是否有人为我们的问题写评论/答案等)。请注意,用户会将我的应用程序用作网站而非移动应用程序。

我遇到了以下answer 获取结果,但我需要推送结果而不是获取。

根据建议,我在我的实体类中创建了一个简单的方法并向其中添加了@PostPersist,但它没有工作,因此基于this answer 我添加了 persistence.xml 文件来定义侦听器,但在 session.save 之后(用户) aftersave 方法没有被触发。

User.java

@Entity
public class User
  .....
  @PostPersist
    public void aftersave()
        System.err.println("*****this is post persist method****");
    

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->

<property name="hibernate.ejb.event.pre-insert"  value="my.hibernate.events.listeners.Listener" />
<property name="hibernate.ejb.event.pre-update"  value="my.hibernate.events.listeners.Listener" />
<property name="hibernate.ejb.event.pre-delete"  value="my.hibernate.events.listeners.Listener" />
<property name="hibernate.ejb.event.post-insert" value="my.hibernate.events.listeners.Listener" />
<property name="hibernate.ejb.event.post-update" value="my.hibernate.events.listeners.Listener" />
<property name="hibernate.ejb.event.post-delete" value="my.hibernate.events.listeners.Listener" />

pom.xml

 <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.2.1.Final</version>
            <type>jar</type>
        </dependency>

【问题讨论】:

取决于您使用的数据库引擎;大多数不支持更改侦听器,这是来自Postgres docs 的示例。您可能可以使用hibernate listener,在您想要的实体上使用@PostPersist 应该可以做到这一点。 @BoristheSpider 问题已更新 【参考方案1】:

听起来像是WebSockets 的任务。它是 Java EE 7 的一部分,因此 Glassfish 应该是第一个支持它的 AS。

要拦截数据库访问,您可以使用@PostUpdate@PostPersist。这里是相关的question。

有很多方法可以执行所谓的服务器推送来通知连接的客户端:

投票(您在问题中提供的链接(“我们到了吗?我们到了吗?...”)) long polling(更智能的轮询方式 - 使用 keepalive 消息的长寿命 HTTP 技术) WebSockets (JSR 356) piggy-backing SPDY(wiki) Server-Sent Events (related answer, wiki)

编辑:在 Java 世界中,有几个框架可以开箱即用地实现服务器推送(反向 ajax)。如果您熟悉GWT,我建议您使用Errai。其他选择是Atmospere。 Atmospere 的缺点是它需要在您的常规应用程序服务器旁边与您的 Web 应用程序一起独立运行进程。一年前我在玩它,所以从那时起这可能已经改变了。

一般来说,很难为您提供一段具体的代码,因为这取决于您将选择的框架。我对 Errai 很熟悉,所以这里有一个例子:

服务器端:

@ApplicationScoped
public class TickerService 

  @Inject
  private Event<Tick> tickEvent;

  private void sendTick() 
    tickEvent.fire(new Tick());
  
 

客户端:

@EntryPoint
public class TickerClient 
  public void tickHappened(@Observes Tick tick) 

    // update the UI with the new data
  

使用 Errai 的其他好处是在服务器和客户端上都有开箱即用的 CDI,另一件很好的事情是使用幕后的网络套接字,如果它受支持,否则回退到其他解决方案。

无论您选择什么,它都应该适合您现有的基础架构和客户端 UI 框架。

【讨论】:

诀窍不在于 db...(因为 jpa/hibernate 在那里提供了明确的解决方案),而是如何实现 ajax。为此目的有一个称为大气的框架,可能值得一试:***.com/questions/4003102/… 尽管我希望在不久的将来 websockets 将成为这条路线的唯一明智选择,但它试图解决客户端限制。【参考方案2】:

每 30 秒或根据要求检查来自服务器的更新。

window.setInterval(function()
  /// call your function here
 //Make AJAX call
 //Update Respective html Contact i,e, DIV

, 30000);

【讨论】:

【参考方案3】:

Comet 也称为Reverse Ajax,是一种 Web 应用程序模型,其中长期持有的 HTTP 请求允许 Web 服务器将数据推送到浏览器,而无需浏览器显式请求。

Comet(又名长寿命 http,服务器推送) 允许服务器开始非常缓慢地响应浏览器的信息请求,并按照服务器规定的时间表继续响应。有关彗星的更多信息,请参阅以下内容:

Alex Russell 的original post coining the term

Wikipedia article on Comet

Comet Daily,定期发布有关该主题的博客

DWR 是一个 Java 库,它使服务器上的 Java 和浏览器中的 javascript 能够尽可能简单地交互和调用。 借助 Reverse Ajax,DWR 允许在服务器上运行的 Java 代码使用客户端 API 将更新发布到任意组浏览器。这允许交互两种方式 - 浏览器调用服务器和服务器调用浏览器。 DWR 支持 Comet、Polling 和 Piggyback(通过正常请求发送数据)作为发布到浏览器的方式。

DWR 提供与 Spring、Struts、Guice、Hibernate 等的集成。 你可以从here阅读更多内容。

其他 Comet 和 Reverse AJAX 框架:

Grizzly Comet API Atmosphere AJAX push with ICEfaces 使用 Servlet 3.0 的异步 Servlet

【讨论】:

【参考方案4】:

使用Node JS 和socket.io

该技术根据客户端使用的浏览器选择最佳的传输方式。

对于最新的浏览器,它使用 Web Sockets,而对于其他浏览器,它会优雅地降级为 Flash Socket 或 Long Pooling。 See more here

您需要做的是使用这些技术设置服务器。服务器将在特定端口上运行。所有客户端都将监听该端口,服务器将能够通过该端口将数据推送到客户端。

【讨论】:

它是一个网站,它也可以在网站上运行吗?还是仅仅在客户端服务器平台上? 这项技术仅适用于浏览器。您自己创建一个客户端-服务器平台。所有浏览器都将充当客户端,您将编写一些代码来构建服务器。示例代码见 socket.io 网站【参考方案5】:

mqtt可用于服务器推送和消息广播。

http://mqtt.org/有更多详细信息。

=======================================

更新日期:2013 年 7 月 11 日

Mqtt 是一个发布/订阅,极其简单和轻量级的消息传递协议。如果服务器是发布者,客户端浏览器订阅服务器发布的主题,那么服务器可以直接向客户端推送消息。

一些有用的资源:

Mosquitto 是一个开源的 mqtt 服务器。易于安装和配置。

mqtt-client 是经过验证的强大的 java mqtt 客户端。

【讨论】:

您能否提供更多详细信息。【参考方案6】:

但是在 session.save(user) 之后 aftersave 方法没有被触发。

@PostPersist 是一个 JPA 回调。 session.save() 是一种非 JPA 的休眠专有方法。 JPA 使用entityManager.persist()。 您正在使用不兼容的功能

【讨论】:

那么 hibernate 做同样的解决方案是什么? 首先,我总是选择可用的标准。在这种情况下,JPA - 使用 EntityManager 和 @PostPersist 并参考 docs.jboss.org/hibernate/devguide/en-US/html。其次,我查看了 Hibernate 专有文档,找不到“回调”或“发布”,但似乎您可以覆盖 Envers 侦听器以通知您事件。不完全干净,但应该可以工作,如果这是你想要的:docs.jboss.org/hibernate/devguide/en-US/html/ch15.html 结合JPA和hibernate效率高吗? 并非完全没有效率。更复杂。除非你有令人信服的理由,否则我肯定不会混合这两种模式。有些人尽可能使用 JPA,然后在需要额外功能时回退到“原始休眠”。但这是:(a)复杂的(b)相当罕见,因为 JPA 非常丰富。当然,有许多“遗留”用户只使用原始休眠,他们还没有切换到 JPA——但是,他们错过了 JPA 添加的新功能。 :)

以上是关于如何从服务器向客户端发送消息?的主要内容,如果未能解决你的问题,请参考以下文章

如何从主(winsock)向服务器发送消息?

如何使用 STOMP 从 Spring WebSocket 服务器向 WebSocket 客户端发送消息?

如何从服务器向客户端发送消息?

如何使用 ZeroMQ 从 C# 客户端向 C++ 服务器发送消息

如何从 Java REST servlet 向 Angular 客户端发送注销消息?

Socket Send(2) - 如何从服务器向客户端发送错误消息