显示导航

使用Grails发送服务器发送事件

本指南将指导您如何使用Grails和RxJava发送服务器发送事件。

作者:Graeme Rocher

Grails版本 3.3.1

1 Grails培训

Grails培训 - 由创建并积极维护Grails框架的人们开发和提供的!

2入门

在本指南中,您将构建一个Grails应用程序,该应用程序通过服务器发送事件与JavaScript客户端通信。

2.1您将需要

要完成本指南,您将需要以下内容

  • 一些时间

  • 一个合适的文本编辑器或IDE

  • 已安装JDK 1.7或更高版本,并已正确配置JAVA_HOME

2.2如何完成指南

要开始,请执行以下操作

Grails指南存储库包含两个文件夹

  • initial初始项目。通常是一个简单的Grails应用程序,其中包含一些其他代码,让您领先一步。

  • complete一个完整的示例。这是完成指南中介绍的步骤并将这些更改应用到initial文件夹的结果。

要完成该指南,请转到initial文件夹

  • cd进入grails-guides/server-sent-events/initial

并按照下一部分中的说明进行操作。

cdgrails-guides/server-sent-events/complete 中,你可以直接转到完成的示例

3 编写应用程序

3.1 添加 RxJava 依赖项

第一步是配置必要的 Gradle 依赖项。这主要意味着在 build.gradle 文件中添加对用于 Grails 的RxJava 插件的依赖项

dependencies {
    ...
    compile "org.grails.plugins:rxjava"
}

RxJava 用于促进将事件发送到 JavaScript 客户端的响应式编程模型。

3.2 创建控制器

接下来创建一个名为 TickTock 的新控制器。如果安装了 Grails,可以通过运行 grails create-controller 命令来执行此操作,否则可以使用内置的 grailsw 包装器

$ ./grailsw create-controller TickTock
第一次运行 grails 命令时,应用程序依赖项将从互联网下载。后续调用会快得多。

该命令的输出将类似于

| Created grails-app/controllers/example/TickTockController.groovy
| Created src/test/groovy/example/TickTockControllerSpec.groovy

如你所见,一个新控制器在 grails-app/controllers/example 目录中创建。Grails 将使用定义在 grails-app/conf/application.ymlgrails.codegen.defaultPackage 值的值来决定使用哪个程序包。

3.3 实现控制器

现在你有一个控制器,你需要修改它以利用 RxJava 特性。为此,添加必要的导入并使控制器实现 grails.rx.web.RxController 性状

grails-app/controllers/example/TickTockController.groovy
import rx.Observer
import rx.Observable
import grails.rx.web.RxController
import java.util.concurrent.TimeUnit
import groovy.transform.CompileStatic

/**
 * Demo Server Sent Events Controller
 */
@CompileStatic
class TickTockController implements RxController {

下一步是实现 index 动作。如果没有指定显式动作,那么这将是控制器执行的默认动作。

RxController 性状添加了一个名为 rx 的帮助器,它允许你从控制器控制发送给客户端的响应。

为了开始发送服务器发送事件,我们将使用 rx.stream(..) 方法

grails-app/controllers/example/TickTockController.groovy
def index() {
    rx.stream { Observer observer ->
    }
}

stream 方法接受一个闭包,该闭包接收 rx.Observer 实例,当你准备通过 rx.Observer 接口发送数据时,可以使用该实例向客户端发送事件。

通过使用 rx 帮助器的各种方法,你可以向 Observer 的 onNext 方法传递值。例如

grails-app/controllers/example/TickTockController.groovy
for (i in (0 .. 5)) {
    if (i % 2 == 0) {
        observer.onNext(
            rx.render('Tick')
        )
    }
    else {
        observer.onNext(
            rx.render('Tock')
        )
    }
    sleep 1000
}

在此示例中,我们在 0 和 5 之间的值的循环并针对奇数和偶数值调用 rx.render(..),分别输出“Tick”或“Tock”。对 sleep(..) 的调用是为了模拟一个慢请求,例如,如果从外部 Web 服务获取值时。

一旦你完成发送事件,便可以使用 Observer 的 onCompleted 事件结束

grails-app/controllers/example/TickTockController.groovy
observer.onCompleted()

最终完成的逻辑如下所示

grails-app/controllers/example/TickTockController.groovy
def index() {
    rx.stream { Observer observer ->

        for (i in (0 .. 5)) {
            if (i % 2 == 0) {
                observer.onNext(
                    rx.render('Tick')
                )
            }
            else {
                observer.onNext(
                    rx.render('Tock')
                )
            }
            sleep 1000
        }
        observer.onCompleted()
    }
}

请注意,如果对 sleep(1000) 的调用实际上是应用程序的具体要求,那么用 interval 方法编写应用程序的习惯性方式将是更合适的

grails-app/controllers/example/TickTockController.groovy
@SuppressWarnings('DuplicateNumberLiteral')
def example() {
    int i = 0
    rx.stream(Observable
                .interval(1, TimeUnit.SECONDS)
                .map {
        i++
        if (i % 2 == 0) {
            rx.render('Tick')
        }
        else {
            rx.render('Tock')
        }
    })
}

3.4 实现客户端

要实现客户端,首先打开 grails-app/views/index.gsp 文件,并在“Welcome to Grails”<h1> 标记下面添加一个附加头

grails-app/views/index.gsp
<h1>Welcome to Grails</h1>
<h2 style="text-align:center;font-size:50px" id="message"></h2>

我们将使用此标头放置从服务器发送事件中收到的内容。

然后在页面底部添加以下 <script>

grails-app/views/index.gsp
<script type="text/javascript">
    (function() {
        var eventSource = new EventSource("tickTock");
        eventSource.onmessage = function(event) {
            console.log("data: "+event.data)
            document.getElementById('message').innerHTML = event.data;
        };
    })();
</script>

以上 JavaScript 代码使用服务器发送事件规范的 EventSource 对象开始接收来自控制器的事件

grails-app/views/index.gsp
var eventSource = new EventSource("tickTock");
您需要一个 现代浏览器 才能使用 EventSource 对象

然后,它注册一个侦听器,该侦听器将使用服务器的响应更新之前定义的 <h2> 标头

grails-app/views/index.gsp
eventSource.onmessage = function(event) {
    console.log("data: "+event.data)
    document.getElementById('message').innerHTML = event.data;
};

就是这样!您现在可以运行应用程序了!

4 运行应用程序

要运行应用程序,请使用 ./gradlew bootRun 命令,该命令将在端口 8080 上启动应用程序。

然后,您可以导航到 http://localhost:8080,您将看到“Welcome to Grails!” 消息下方消息“Tick”和“Tock”交替出现,因为浏览器从服务器接收到事件。

5 需要 Grails 帮助吗?

Object Computing, Inc. (OCI) 赞助了本指南的创建。提供各种咨询和支持服务。

OCI 是 Grails 的家

认识一下团队