在Spring WebFlux Web服务中使用Server-Sent Events来实现Hello World
在Spring WebFlux Web服务中使用Server-Sent Events实现”Hello World”。

这个问题的目标是什么?
我将使用 Windows 11 上的 Linux 进行云开发。
您可以在这里查看文章的列表。
实现
在Ubuntu操作系统上,验证Spring WebFlux应用程序的Server-Sent Events功能。
技术主题
什么是Spring WebFlux?
这是Spring Framework的一个模块,用于开发异步和响应式的Web应用程序。
关键词
内容
异步和响应式的请求处理
Spring WebFlux可以使用称为响应式流的机制来异步处理请求。这样可以在资源较少的情况下实现高吞吐量。
WebFlux服务器
Spring WebFlux包含基于Netty的WebFlux服务器。该服务器可以实现高吞吐量和低延迟。
支持Reactive Streams API
Spring WebFlux符合Reactive Streams API规范,可以与其他使用Reactive Streams API的库进行集成。这样可以开发出更灵活和可扩展的应用程序。
服务器推送事件 (Server-Sent Events, SSE) 是什么?
服务器推送事件(SSE)是一种专门用于服务器向客户端进行单向实时通信的技术,服务器可以实时推送更新信息给客户端。通过维持长时间连接,客户端可以实时接收来自服务器的更新信息。
SSE适用于需要实时信息传递的Web应用程序。例如,下面是一些可能使用SSE的情况的关键词与内容。
关键词 内容
社交媒体的实时更新 像社交媒体这样的Web应用程序需要实时更新用户发布的新信息、关注人的活动情况等。通过使用SSE,服务器可以在收到新信息时推送给客户端。
股票信息的实时更新 在像股票市场这样的行业中,需要实时获取股票价格的变动等信息。通过使用SSE,可以实时推送股价和交易更新信息。
在线游戏的实时更新 在线游戏需要实时传递玩家的动作和其他玩家的行为等实时信息。通过使用SSE,可以向玩家实时传递信息。
这些只是一些例子,各种需要实时信息传递的Web应用程序中都可能会使用SSE。
开发环境
- Windows 11 Home 22H2 を使用しています。
> wsl –version
WSL版本:1.0.3.0
内核版本:5.15.79.1
WSLg版本:1.0.47Ubuntu ※您可以在相关文章中查找安装方法:
$ lsb_release -a
没有可用的LSB模块。
发行商ID:Ubuntu
描述:Ubuntu 22.04.1 LTS
发行版本:22.04
Java JDK ※您可以在相关文章中查找安装方法:
$ java -version
openjdk version “17.0.6” 2023-01-17
OpenJDK Runtime Environment GraalVM CE 22.3.1(build 17.0.6+10-jvmci-22.3-b13)
OpenJDK 64位服务器VM GraalVM CE 22.3.1(build 17.0.6+10-jvmci-22.3-b13,混合模式,共享)
Maven ※您可以在相关文章中查找安装方法:
$ mvn -version
Apache Maven 3.6.3
Maven主目录:/usr/share/maven
Java版本:11.0.18,供应商:Ubuntu,运行时:/usr/lib/jvm/java-11-openjdk-amd64
创建Web应用程序的规格
并行处理
创建Spring MVC Web服务
创建项目文件夹。
※将~/tmp/sync-spring-mvc设置为项目文件夹。
$ mkdir -p ~/tmp/sync-spring-mvc
$ cd ~/tmp/sync-spring-mvc
创建应用程序类
创建应用程序类。
为了简化项目结构,将所有元素都写入Application类。
$ mkdir -p src/main/java/com/example/springmvc
$ vim src/main/java/com/example/springmvc/Application.java
文件内容
Application.java
package com.example.springmvc;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@GetMapping(“/one”)
public Map<String, String> getOne() throws InterruptedException {
Map<String, String> map = Map.of(“message”, “Hello Object!”);
TimeUnit.SECONDS.sleep(2);
log.info(“Sending message: {}”, map);
return map;
}
@GetMapping(“/list”)
public List<Map<String, String>> getList() throws InterruptedException {
List<Map<String, String>> list = List.of(
Map.of(“message”, “Hello List 1!”),
Map.of(“message”, “Hello List 2!”),
Map.of(“message”, “Hello List 3!”),
Map.of(“message”, “Hello List 4!”),
Map.of(“message”, “Hello List 5!”));
list.forEach(map -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
log.error(e.getMessage());
throw new RuntimeException(e);
}
log.info(“Sending message: {}”, map);
});
return list;
}
}
每个处理都设置了2秒的延迟。
创建pom.xml
创建pom.xml文件。
$ vim pom.xml
文件内容
pom.xml
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.7.8
com.example
sync-spring-mvc
1.0
sync-spring-mvc
11
UTF-8
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
1.18.26
provided
app
org.springframework.boot
spring-boot-maven-plugin
配置输出日志文件
application.properties
logback-spring.xml
您可以在以下相关文章中查看详细步骤。
https://qiita.com/fsdg-adachi_h/items/ffbcb6ac9179852b2816
构建应用程序
构建Java应用程序。
※将创建target/app.jar。
$ mvn clean install
启动应用程序
启动应用程序。
※按Ctrl + C停止应用程序。
$ rm -rf log
$ mvn spring-boot:run
应用程序的功能验证
我們可以從另一個終端窗口使用curl命令來進行確認。
如果获取到一个对象(Map)的情况下。
$ curl -v http://localhost:8080/one -w '\n'
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /one HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Mon, 20 Mar 2023 03:53:45 GMT
<
* Connection #0 to host localhost left intact
{"message":"Hello Object!"}
我会从不同的终端查看日志文件。※ 这里只摘录了必要的部分。
$ cd ~/tmp/sync-spring-mvc/log
$ cat app.log
2023-03-20 13:05:32.679 [INFO ] [main] org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220 - Tomcat started on port(s): 8080 (http) with context path ''
2023-03-20 13:05:32.686 [INFO ] [main] org.springframework.boot.StartupInfoLogger.logStarted:61 - Started Application in 0.954 seconds (JVM running for 1.11)
2023-03-20 13:05:45.910 [INFO ] [http-nio-8080-exec-1] org.springframework.web.servlet.FrameworkServlet.initServletBean:525 - Initializing Servlet 'dispatcherServlet'
2023-03-20 13:05:45.913 [INFO ] [http-nio-8080-exec-1] org.springframework.web.servlet.FrameworkServlet.initServletBean:547 - Completed initialization in 1 ms
2023-03-20 13:05:47.930 [INFO ] [http-nio-8080-exec-1] com.example.springmvc.Application.getOne:26 - Sending message: {message=Hello Object!}
如果获取列表
我們將使用curl命令從另一個終端窗口進行驗證。
$ curl -v http://localhost:8080/list -w '\n'
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /list HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Mon, 20 Mar 2023 03:56:19 GMT
<
* Connection #0 to host localhost left intact
[{"message":"Hello List 1!"},{"message":"Hello List 2!"},{"message":"Hello List 3!"},{"message":"Hello List 4!"},{"message":"Hello List 5!"}]
我会从另一个终端检查日志文件。※仅提取必要的部分。
$ cd ~/tmp/sync-spring-mvc/log
$ cat app.log
2023-03-20 13:06:34.424 [INFO ] [main] org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220 - Tomcat started on port(s): 8080 (http) with context path ''
2023-03-20 13:06:34.430 [INFO ] [main] org.springframework.boot.StartupInfoLogger.logStarted:61 - Started Application in 0.947 seconds (JVM running for 1.102)
2023-03-20 13:06:38.337 [INFO ] [http-nio-8080-exec-1] org.springframework.web.servlet.FrameworkServlet.initServletBean:525 - Initializing Servlet 'dispatcherServlet'
2023-03-20 13:06:38.340 [INFO ] [http-nio-8080-exec-1] org.springframework.web.servlet.FrameworkServlet.initServletBean:547 - Completed initialization in 1 ms
2023-03-20 13:06:40.522 [INFO ] [http-nio-8080-exec-1] com.example.springmvc.Application.lambda$getList$0:45 - Sending message: {message=Hello List 1!}
2023-03-20 13:06:42.691 [INFO ] [http-nio-8080-exec-1] com.example.springmvc.Application.lambda$getList$0:45 - Sending message: {message=Hello List 2!}
2023-03-20 13:06:44.721 [INFO ] [http-nio-8080-exec-1] com.example.springmvc.Application.lambda$getList$0:45 - Sending message: {message=Hello List 3!}
2023-03-20 13:06:46.740 [INFO ] [http-nio-8080-exec-1] com.example.springmvc.Application.lambda$getList$0:45 - Sending message: {message=Hello List 4!}
2023-03-20 13:06:48.748 [INFO ] [http-nio-8080-exec-1] com.example.springmvc.Application.lambda$getList$0:45 - Sending message: {message=Hello List 5!}
总结到这里
异步处理
创建Spring WebFlux Web服务
创建项目文件夹
创建项目文件夹。
※ 将~/tmp/async-spring-webflux设为项目文件夹。
$ mkdir -p ~/tmp/async-spring-webflux
$ cd ~/tmp/async-spring-webflux
创建应用程序类
创建一个应用程序类。
$ mkdir -p src/main/java/com/example/springwebflux
$ vim src/main/java/com/example/springwebflux/Application.java
文件的内容 de
package com.example.springwebflux;
import java.time.Duration;
import java.util.Map;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@GetMapping("/mono")
public Mono<Map<String, String>> getMono() {
return Mono.just(
Map.of("message", "Hello Mono!"))
.delayElement(Duration.ofSeconds(2))
.doOnNext(map -> log.info("Sending message: {}", map));
}
@GetMapping("/flux")
public Flux<Map<String, String>> getFlux() {
return Flux.range(1, 5)
.map(idx -> Map.of("message", "Hello Flux " + idx + "!"))
.delayElements(Duration.ofSeconds(2))
.doOnNext(map -> log.info("Sending message: {}", map));
}
@GetMapping("/flux-sse")
public Flux<ServerSentEvent<Map<String, String>>> getFluxWithSSE() {
return Flux.range(1, 5)
.map(idx -> Map.of("message", "Hello Flux " + idx + "!"))
.delayElements(Duration.ofSeconds(2))
.doOnNext(map -> log.info("Sending message: {}", map))
.map(map -> ServerSentEvent.builder(map).build())
.concatWith(Mono.just(ServerSentEvent.<Map<String, String>>builder().event("end").build()));
}
}
@GetMapping(“/mono”)
public Mono<Map<String, String>> getMono() {
return Mono.just(
Map.of(“message”, “Hello Mono!”))
.delayElement(Duration.ofSeconds(2))
.doOnNext(map -> log.info(“Sending message: {}”, map));
}
內容
@GetMapping(“/mono”)註釋會將HTTP GET請求映射到”/mono”端點。
Mono<Map<String, String>> 是一個表示單一非同步值的Reactive Streams類型。在這種情況下,它表示單一個Map對象。
Mono.just(Map.of(“message”, “Hello Mono!”)) 創建一個包含”message”鍵和其值的Map對象,並將其包裝到Mono中返回。
.delayElement(Duration.ofSeconds(2)) 是轉換Mono以使回應延遲2秒的運算符。
.doOnNext(map -> log.info(“Sending message: {}”, map)) 是為了將每個值通知到log對象並輸出消息而添加的副作用運算符。
換句話說,這個端點將在等待2秒後返回包含”Hello Mono!”消息的Map對象。同時,日誌將輸出”Sending message: {message=Hello Mono!}”的消息當值被通知時。
返回給客戶端非同步的多個值回應的端點
@GetMapping(“/flux”)
public Flux<Map<String, String>> getFlux() {
return Flux.range(1, 5)
.map(idx -> Map.of(“message”, “Hello Flux ” + idx + “!”))
.delayElements(Duration.ofSeconds(2))
.doOnNext(map -> log.info(“Sending message: {}”, map));
}
內容
@GetMapping(“/flux”)註釋將HTTP GET請求映射到”/flux”端點。
Flux<Map<String, String>> 是一個使用Reactive Streams類型表示多個非同步值的端點。在這種情況下,它表示多個Map對象。
Flux.range(1, 5) 產生從1到5的整數的Flux。
.map(idx -> Map.of(“message”, “Hello Flux ” + idx + “!”)) 是用於創建每個元素的包含”message”鍵和其值的Map對象的運算符。
.delayElements(Duration.ofSeconds(2)) 是延遲每個元素2秒的運算符。
.doOnNext(map -> log.info(“Sending message: {}”, map)) 是為了將每個元素通知到log對象並輸出消息而添加的副作用運算符。
換句話說,這個端點將返回包含在2秒間隔通知的每個元素中的”Hello Flux {index}!”消息的Map對象。同時,日誌將在每個值被通知時輸出”Sending message: {message=Hello Flux {index}!}”的消息。
返回使用Server-Sent Events(SSE)協議非同步發送數據給客戶端的端點
@GetMapping(“/flux-sse”)
public Flux<ServerSentEvent<Map<String, String>>> getFluxWithSSE() {
return Flux.range(1, 5)
.map(idx -> Map.of(“message”, “Hello Flux ” + idx + “!”))
.delayElements(Duration.ofSeconds(2))
.doOnNext(map -> log.info(“Sending message: {}”, map))
.map(map -> ServerSentEvent.builder(map).build())
.concatWith(Mono.just(ServerSentEvent.<Map<String, String>>builder().event(“end”).build()));
}
內容
@GetMapping(“/flux-sse”) 註釋將HTTP GET請求映射到”/flux-sse”端點。
Flux<ServerSentEvent<Map<String, String>>> 是一個使用Server-Sent Events表示多個非同步值的Reactive Streams類型。在這種情況下,它表示多個Map對象。
Flux.range(1, 5) 產生從1到5的整數的Flux。
.map(idx -> Map.of(“message”, “Hello Flux ” + idx + “!”)) 是用於創建每個元素的包含”message”鍵和其值的Map對象的運算符。
.delayElements(Duration.ofSeconds(2)) 是延遲每個元素2秒的運算符。
.doOnNext(map -> log.info(“Sending message: {}”, map)) 是為了將每個元素通知到log對象並輸出消息而添加的副作用運算符。
.map(map -> ServerSentEvent.builder(map).build()) 是將每個Map對象轉換為ServerSentEvent對象的運算符。
.concatWith(Mono.just(ServerSentEvent.<Map<String, String>>builder().event(“end”).build())) 是用於在流的末尾添加ServerSentEvent對象的運算符。這樣可以發送表示SSE流結束的event: end標籤。
換句話說,這個端點將返回使用Server-Sent Events格式包含”Hello Flux {index}!”消息的Map對象的多個值,每個元素之間間隔2秒通知。同時,日誌將在每個值被通知時輸出”Sending message: {message=Hello Flux {index}!}”的消息。
创建 pom.xml 文件
创建 pom.xml 文件。
$ vim pom.xml
文件的内容 de
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>sync-spring-webflux</artifactId>
<version>1.0</version>
<name>sync-spring-webflux</name>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
输出日志文件的设置
-
- application.properties
- logback-spring.xml
您可以在这篇相关文章中确认步骤。
应用程序的构建
构建Java应用程序。
※ 将创建目标/app.jar。
$ mvn clean package
打开应用
启动应用程序。
※ 停止应用程序时按下 ctrl + C。
$ rm -rf log
$ mvn spring-boot:run
确认应用的运行情况
我們可以從另一個終端窗口使用curl命令進行確認。
如果以常规方式使用 HTTP 请求 Mono 的情况
$ curl -v http://localhost:8080/mono -w '\n'
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /mono HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Content-Type: application/json
< Content-Length: 25
<
* Connection #0 to host localhost left intact
{"message":"Hello Mono!"}
我会从另一个终端查看日志文件。※ 只摘录了必要的部分。
$ cd ~/tmp/async-spring-webflux/log
$ cat app.log
2023-03-20 12:11:59.869 [DEBUG] [main] org.springframework.boot.StartupInfoLogger.logStarting:56 - Running with Spring Boot v2.7.8, Spring v5.3.25
2023-03-20 12:11:59.870 [INFO ] [main] org.springframework.boot.SpringApplication.logStartupProfileInfo:637 - The following 1 profile is active: "develop"
2023-03-20 12:12:00.556 [INFO ] [main] org.springframework.boot.web.embedded.netty.NettyWebServer.start:111 - Netty started on port 8080
2023-03-20 12:12:00.562 [INFO ] [main] org.springframework.boot.StartupInfoLogger.logStarted:61 - Started Application in 0.987 seconds (JVM running for 1.221)
2023-03-20 12:15:32.844 [INFO ] [parallel-1] com.example.springwebflux.Application.lambda$getMono$0:32 - Sending message: {message=Hello Mono!}
如果使用普通的HTTP请求Flux的情况下
我会从另一个终端使用curl命令进行确认。
$ curl -v http://localhost:8080/flux -w '\n'
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /flux HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Content-Type: application/json
<
* Connection #0 to host localhost left intact
[{"message":"Hello Flux 1!"},{"message":"Hello Flux 2!"},{"message":"Hello Flux 3!"},{"message":"Hello Flux 4!"},{"message":"Hello Flux 5!"}]
我会从另一个终端检查日志文件。※ 我提取了必要的内容。
$ cd ~/tmp/async-spring-webflux/log
$ cat app.log
2023-03-20 12:19:28.477 [INFO ] [main] org.springframework.boot.web.embedded.netty.NettyWebServer.start:111 - Netty started on port 8080
2023-03-20 12:19:28.482 [INFO ] [main] org.springframework.boot.StartupInfoLogger.logStarted:61 - Started Application in 0.95 seconds (JVM running for 1.124)
2023-03-20 12:19:42.389 [INFO ] [parallel-1] com.example.springwebflux.Application.lambda$getFlux$2:40 - Sending message: {message=Hello Flux 1!}
2023-03-20 12:19:44.392 [INFO ] [parallel-2] com.example.springwebflux.Application.lambda$getFlux$2:40 - Sending message: {message=Hello Flux 2!}
2023-03-20 12:19:46.394 [INFO ] [parallel-3] com.example.springwebflux.Application.lambda$getFlux$2:40 - Sending message: {message=Hello Flux 3!}
2023-03-20 12:19:48.396 [INFO ] [parallel-4] com.example.springwebflux.Application.lambda$getFlux$2:40 - Sending message: {message=Hello Flux 4!}
2023-03-20 12:19:50.399 [INFO ] [parallel-5] com.example.springwebflux.Application.lambda$getFlux$2:40 - Sending message: {message=Hello Flux 5!}
如果使用Server-Sent Events指定的HTTP请求Flux的情况下。
从另一个终端使用curl命令进行确认。
$ curl -v http://localhost:8080/flux-sse -H 'Accept: text/event-stream' -w '\n'
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /flux-sse HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: text/event-stream
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Content-Type: text/event-stream;charset=UTF-8
<
data:{"message":"Hello Flux 1!"}
data:{"message":"Hello Flux 2!"}
data:{"message":"Hello Flux 3!"}
data:{"message":"Hello Flux 4!"}
data:{"message":"Hello Flux 5!"}
event:end
* Connection #0 to host localhost left intact
我要从另一个终端确认日志文件。※仅摘录了必要的部分。
$ cd ~/tmp/async-spring-webflux/log
$ cat app.log
cat app.log
2023-03-20 12:22:02.249 [INFO ] [main] org.springframework.boot.web.embedded.netty.NettyWebServer.start:111 - Netty started on port 8080
2023-03-20 12:22:02.256 [INFO ] [main] org.springframework.boot.StartupInfoLogger.logStarted:61 - Started Application in 1.035 seconds (JVM running for 1.224)
2023-03-20 12:22:17.814 [INFO ] [parallel-1] com.example.springwebflux.Application.lambda$getFluxWithSSE$4:48 - Sending message: {message=Hello Flux 1!}
2023-03-20 12:22:19.827 [INFO ] [parallel-2] com.example.springwebflux.Application.lambda$getFluxWithSSE$4:48 - Sending message: {message=Hello Flux 2!}
2023-03-20 12:22:21.831 [INFO ] [parallel-3] com.example.springwebflux.Application.lambda$getFluxWithSSE$4:48 - Sending message: {message=Hello Flux 3!}
2023-03-20 12:22:23.842 [INFO ] [parallel-4] com.example.springwebflux.Application.lambda$getFluxWithSSE$4:48 - Sending message: {message=Hello Flux 4!}
2023-03-20 12:22:25.854 [INFO ] [parallel-5] com.example.springwebflux.Application.lambda$getFluxWithSSE$4:48 - Sending message: {message=Hello Flux 5!}
这是目前为止的总结。
仅提供一种选项:
总结
我能够在使用Ubuntu搭建的简单Java开发环境下,运行实现了Server-Sent Events的Spring WebFlux Web服务。
请问感觉怎么样?在 WSL Ubuntu 上,您可以轻松运行实现 Server-Sent Events 的 Spring Boot Web 应用程序。请务必尝试一下。我们将继续介绍Java开发环境等内容,请敬请期待。
请提供相关参考资料。
W3C服务器推送事件
HTML 9.2服务器推送事件活动标准
MDN 服务器发送事件