Vue前端如何实时接收Quarkus+SmallRye Mutiny后端Multi推送的数据
Vue前端如何实时接收Quarkus+SmallRye Mutiny后端Multi推送的数据
嗨,我来帮你解决这个问题!你现在遇到的情况是因为默认的axios会等整个HTTP响应结束才返回所有数据,而Mutiny的Multi是用来做流式输出的,所以得换个思路来处理——用Server-Sent Events(SSE),这刚好是Quarkus和Mutiny原生支持的方案,前端用Vue配合EventSource就能实时接收每一条推送的数据啦。
第一步:调整后端Quarkus端点,支持SSE流式推送
你当前的端点返回Multi<Map>,但默认会被序列化成完整的JSON数组返回。我们需要把它改成SSE格式,让后端能逐个推送数据:
@GET @Path("/data") @APIResponse( responseCode = "200", description = "Stream data as Server-Sent Events", content = @Content( mediaType = MediaType.SERVER_SENT_EVENTS, schema = @Schema(type = SchemaType.OBJECT, implementation = HashMap.class) ) ) @Produces(MediaType.SERVER_SENT_EVENTS) // 关键:指定返回SSE类型 @Consumes(MediaType.APPLICATION_JSON) Multi<Map> data();
如果你的Multi是异步生成数据的(比如从数据库分批查询、监听消息队列等),Quarkus会自动把Multi里的每个元素包装成SSE事件推送给前端,不需要额外的包装逻辑。
第二步:Vue前端用EventSource实时接收数据
前端不能再用axios了(它不适合处理流式响应),我们用浏览器原生的EventSource来连接SSE端点,实时监听后端推送的数据:
<template> <div class="stream-data-container"> <h3>实时推送数据</h3> <ul> <li v-for="(item, index) in receivedData" :key="index"> {{ JSON.stringify(item) }} </li> </ul> </div> </template> <script> export default { data() { return { receivedData: [], eventSource: null }; }, mounted() { // 初始化EventSource,连接后端SSE端点 this.eventSource = new EventSource('/data'); // 监听后端推送的消息 this.eventSource.onmessage = (event) => { // 解析推送的JSON数据 const newData = JSON.parse(event.data); // 添加到页面列表中 this.receivedData.push(newData); }; // 监听连接错误,避免无限重试 this.eventSource.onerror = (error) => { console.error('SSE连接出错:', error); this.eventSource.close(); }; }, beforeUnmount() { // 组件销毁时关闭SSE连接,避免内存泄漏 if (this.eventSource) { this.eventSource.close(); } } }; </script>
额外注意事项
- 跨域配置:如果前端和后端不在同一个域名下,需要在Quarkus的
application.properties里配置CORS允许SSE请求:
quarkus.http.cors.enabled=true quarkus.http.cors.origins=https://your-frontend-domain.com # 生产环境不要用* quarkus.http.cors.methods=GET,OPTIONS quarkus.http.cors.headers=Content-Type,Accept
WebSocket vs SSE:你之前尝试的vue-socket.io是WebSocket方案,适合双向通信场景;而SSE是单向推送(服务器→客户端),更轻量,适合你现在的需求,不需要额外的端口或复杂配置。
Mutiny数据流的生命周期:确保后端的
Multi是持续产生数据的(比如用Multi.createFrom().ticks().every(Duration.ofSeconds(1))模拟定时推送),如果Multi很快就完成了,前端还是会一次性收到所有数据。
备注:内容来源于stack exchange,提问作者dockitu
相关产品推荐
相关产品推荐

