以下是一个完整的基于 spring boot 的 server-sent events (sse) 示例,包括服务端和客户端的实现。
一、服务端实现
1. 创建 spring boot 项目
首先,创建一个基本的 spring boot 项目,并添加 spring-boot-starter-web 依赖。在 pom.xml 中添加以下内容:
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
</dependencies>2. 创建 sse 控制器
创建一个控制器来处理 sse 连接并推送实时消息。
ssecontroller.java
package com.example.sse;
import org.springframework.http.mediatype;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.restcontroller;
import org.springframework.web.servlet.mvc.method.annotation.sseemitter;
import java.io.ioexception;
import java.util.concurrent.executorservice;
import java.util.concurrent.executors;
import java.util.concurrent.timeunit;
@restcontroller
public class ssecontroller {
private final executorservice executorservice = executors.newcachedthreadpool();
@getmapping("/sse")
public sseemitter handlesse() {
sseemitter emitter = new sseemitter();
executorservice.execute(() -> {
try {
for (int i = 0; i < 10; i++) {
emitter.send("message " + i, mediatype.text_plain);
timeunit.seconds.sleep(1);
}
emitter.complete();
} catch (ioexception | interruptedexception e) {
emitter.completewitherror(e);
}
});
return emitter;
}
}3. 配置跨域(可选)
如果前端和后端运行在不同端口上,需要配置跨域。
corsconfig.java
package com.example.sse;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.web.servlet.config.annotation.corsregistry;
import org.springframework.web.servlet.config.annotation.webmvcconfigurer;
@configuration
public class corsconfig implements webmvcconfigurer {
@override
public void addcorsmappings(corsregistry registry) {
registry.addmapping("/**")
.allowedoriginpatterns("*")
.allowedmethods("get", "post", "put", "delete")
.allowedheaders("*")
.allowcredentials(true);
}
}二、客户端实现
在前端页面中,使用 eventsource 来订阅 sse。
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>sse example</title>
</head>
<body>
<h1>server-sent events example</h1>
<div id="events"></div>
<script>
const eventsource = new eventsource('/sse');
eventsource.onmessage = function(event) {
const newelement = document.createelement("div");
newelement.innerhtml = "message: " + event.data;
document.getelementbyid("events").appendchild(newelement);
};
eventsource.onerror = function(event) {
eventsource.close();
alert("eventsource failed: " + event);
};
</script>
</body>
</html>三、运行和测试
- 启动 spring boot 应用。
- 在浏览器中访问
http://localhost:8080,即可看到服务端每秒推送的消息。
四、扩展功能
1. 动态推送消息
可以通过维护一个 sseemitter 的映射来动态推送消息。
ssecontroller.java(动态推送版本)
package com.example.sse;
import org.springframework.http.mediatype;
import org.springframework.web.bind.annotation.*;
import java.io.ioexception;
import java.util.map;
import java.util.concurrent.concurrenthashmap;
@restcontroller
public class ssecontroller {
private final map<string, sseemitter> emittermap = new concurrenthashmap<>();
@getmapping("/sse/{userid}")
public sseemitter connect(@pathvariable string userid) {
sseemitter emitter = new sseemitter();
emittermap.put(userid, emitter);
emitter.oncompletion(() -> emittermap.remove(userid));
emitter.ontimeout(() -> emittermap.remove(userid));
emitter.onerror(e -> emittermap.remove(userid));
return emitter;
}
@getmapping("/push/{userid}")
public void push(@pathvariable string userid, @requestparam string message) {
sseemitter emitter = emittermap.get(userid);
if (emitter != null) {
try {
emitter.send(message);
} catch (ioexception e) {
emitter.completewitherror(e);
emittermap.remove(userid);
}
}
}
}2. 使用 webflux 实现 sse
如果需要更高效的响应式编程支持,可以使用 spring webflux。
ssecontroller.java(webflux 版本)
package com.example.sse;
import org.springframework.http.mediatype;
import org.springframework.http.codec.serversentevent;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.restcontroller;
import reactor.core.publisher.flux;
import java.time.duration;
@restcontroller
public class ssecontroller {
@getmapping("/sse/stream")
public flux<serversentevent<string>> streamsse() {
return flux.interval(duration.ofseconds(1))
.map(sequence -> serversentevent.<string>builder()
.id(string.valueof(sequence))
.event("periodic-event")
.data("current time: " + java.time.localtime.now())
.build());
}
}通过以上步骤,你可以实现一个完整的基于 spring boot 的 sse 应用。
到此这篇关于spring boot实现sse实时推送实战示例的文章就介绍到这了,更多相关springboot sse实时推送内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论