您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息

Spring Boot怎么使用SSE方式向前端推送数据

2024/4/24 23:39:40发布3次查看
前言sse简单的来说就是服务器主动向前端推送数据的一种技术,它是单向的,也就是说前端是不能向服务器发送数据的。sse适用于消息推送,监控等只需要服务器推送数据的场景中,下面是使用spring boot 来实现一个简单的模拟向前端推动进度数据,前端页面接受后展示进度条。
服务端在spring boot中使用时需要注意,最好使用spring web 提供的sseemitter这个类来进行操作,我在刚开始时使用网上说的将content-type设置为text-stream这种方式发现每次前端每次都会重新创建接。最后参考该文实现了最终想要的效果:
sse工具类sseserver.java
package vip.huhailong.catchat.sse;import lombok.extern.slf4j.slf4j;import org.springframework.http.mediatype;import org.springframework.web.servlet.mvc.method.annotation.sseemitter;import java.io.ioexception;import java.util.arraylist;import java.util.list;import java.util.map;import java.util.set;import java.util.concurrent.concurrenthashmap;import java.util.concurrent.atomic.atomicinteger;import java.util.function.consumer;/** * @author huhailong */@slf4jpublic class sseserver { /** * 当前连接数 */ private static atomicinteger count = new atomicinteger(0); private static map<string, sseemitter> sseemittermap = new concurrenthashmap<>(); public static sseemitter connect(string userid){ //设置超时时间,0表示不过期,默认是30秒,超过时间未完成会抛出异常 sseemitter sseemitter = new sseemitter(0l); //注册回调 sseemitter.oncompletion(completioncallback(userid)); sseemitter.onerror(errorcallback(userid)); sseemitter.ontimeout(timeoutcallback(userid)); sseemittermap.put(userid,sseemitter); //数量+1 count.getandincrement(); log.info("create new sse connect ,current user:{}",userid); return sseemitter; } /** * 给指定用户发消息 */ public static void sendmessage(string userid, string message){ if(sseemittermap.containskey(userid)){ try{ sseemittermap.get(userid).send(message); }catch (ioexception e){ log.error("user id:{}, send message error:{}",userid,e.getmessage()); e.printstacktrace(); } } } /** * 想多人发送消息,组播 */ public static void groupsendmessage(string groupid, string message){ if(sseemittermap!=null&&!sseemittermap.isempty()){ sseemittermap.foreach((k,v) -> { try{ if(k.startswith(groupid)){ v.send(message, mediatype.application_json); } }catch (ioexception e){ log.error("user id:{}, send message error:{}",groupid,message); removeuser(k); } }); } } public static void batchsendmessage(string message) { sseemittermap.foreach((k,v)->{ try{ v.send(message,mediatype.application_json); }catch (ioexception e){ log.error("user id:{}, send message error:{}",k,e.getmessage()); removeuser(k); } }); } /** * 群发消息 */ public static void batchsendmessage(string message, set<string> userids){ userids.foreach(userid->sendmessage(userid,message)); } public static void removeuser(string userid){ sseemittermap.remove(userid); //数量-1 count.getanddecrement(); log.info("remove user id:{}",userid); } public static list<string> getids(){ return new arraylist<>(sseemittermap.keyset()); } public static int getusercount(){ return count.intvalue(); } private static runnable completioncallback(string userid) { return () -> { log.info("结束连接,{}",userid); removeuser(userid); }; } private static runnable timeoutcallback(string userid){ return ()->{ log.info("连接超时,{}",userid); removeuser(userid); }; } private static consumer<throwable> errorcallback(string userid){ return throwable -> { log.error("连接异常,{}",userid); removeuser(userid); }; }}
上面这个类可以把它当作一个sse的工具类,下面我们使用一下它
在controller层创建 ssecontroller.javapackage vip.huhailong.catchat.controller;import lombok.extern.slf4j.slf4j;import org.springframework.web.bind.annotation.*;import org.springframework.web.servlet.mvc.method.annotation.sseemitter;import vip.huhailong.catchat.sse.sseserver;/** * @author huhailong */@slf4j@restcontroller@crossorigin@requestmapping("/sse")public class ssecontroller { @getmapping("/connect/{userid}") public sseemitter connect(@pathvariable string userid){ return sseserver.connect(userid); } @getmapping("/process") public void sendmessage() throws interruptedexception { for(int i=0; i<=100; i++){ if(i>50&&i<70){ thread.sleep(500l); }else{ thread.sleep(100l); } sseserver.batchsendmessage(string.valueof(i)); } }}
上面的connect是用来连接sse的,它返回一个sseemitter实例,这时候连接就已经创建了,然后下面的process接口是用来推送数据的,我这里是准备让前端实现一个进度条的效果,所以推送的是数字,为了效果明显,我在推送到50到70的时候速度放慢,其余都是100ms
前端代码<!doctype html><html lang="en"><head> <meta charset="utf-8"> <title>home</title> <script> let data = new eventsource("/cat-chat/sse/connect/huhailong") data.onmessage = function(event){ console.log("test=>",event) document.getelementbyid("result").innertext = event.data+'%'; document.getelementbyid("my-progress").value = event.data; } </script></head><body> <div id="result"></div> <progress id="my-progress" value="0" max="100"></progress></body></html>
最终效果:
以上就是spring boot怎么使用sse方式向前端推送数据的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录