Spring MVC Streaming and SSE Request Processing SSE可以实现chatgpt一次请求分批次响应的效果

1. Introduction

This simple tutorial demonstrates the use of several asynchronous and streaming objects in Spring MVC 5.x.x.

Specifically, we’ll review three key classes:

  • ResponseBodyEmitter
  • SseEmitter
  • StreamingResponseBody

Also, we’ll discuss how to interact with them using a JavaScript client.

2. ResponseBodyEmitter

ResponseBodyEmitter handles async responses.

Also, it represents a parent for a number of subclasses – one of which we’ll take a closer look at below.

2.1. Server Side

It’s better to use a ResponseBodyEmitter along with its own dedicated asynchronous thread and wrapped with a ResponseEntity (which we can inject the emitter into directly):

@Controller
public class ResponseBodyEmitterController {private ExecutorService executor = Executors.newCachedThreadPool();@GetMapping("/rbe")public ResponseEntity<ResponseBodyEmitter> handleRbe() {ResponseBodyEmitter emitter = new ResponseBodyEmitter();executor.execute(() -> {try {emitter.send("/rbe" + " @ " + new Date(), MediaType.TEXT_PLAIN);emitter.complete();} catch (Exception ex) {emitter.completeWithError(ex);}});return new ResponseEntity(emitter, HttpStatus.OK);}
}

So, in the example above, we can sidestep needing to use CompleteableFutures, more complicated asynchronous promises, or use of the @Async annotation.

Instead, we simply declare our asynchronous entity and wrap it in a new Thread provided by the ExecutorService.

2.2. Client Side

For client-side use, we can use a simple XHR method and call our API endpoints just like in a usual AJAX operation:

var xhr = function(url) {return new Promise(function(resolve, reject) {var xmhr = new XMLHttpRequest();//...xmhr.open("GET", url, true);xmhr.send();//...});
};xhr('http://localhost:8080/javamvcasync/rbe').then(function(success){ //... });

3. SseEmitter

SseEmitter is actually a subclass of ResponseBodyEmitter and provides additional Server-Sent Event (SSE) support out-of-the-box.

3.1. Server Side

So, let’s take a quick look at an example controller leveraging this powerful entity:

@Controller
public class SseEmitterController {private ExecutorService nonBlockingService = Executors.newCachedThreadPool();@GetMapping("/sse")public SseEmitter handleSse() {SseEmitter emitter = new SseEmitter();nonBlockingService.execute(() -> {try {emitter.send("/sse" + " @ " + new Date());// we could send more eventsemitter.complete();} catch (Exception ex) {emitter.completeWithError(ex);}});return emitter;}   
}

Pretty standard fare, but we’ll notice a few differences between this and our usual REST controller:

  • First, we return a SseEmitter
  • Also, we wrap the core response information in its own Thread
  • Finally, we send response information using emitter.send()

3.2. Client Side

Our client works a little bit differently this time since we can leverage the continuously connected Server-Sent Event Library:

var sse = new EventSource('http://localhost:8080/javamvcasync/sse');
sse.onmessage = function (evt) {var el = document.getElementById('sse');el.appendChild(document.createTextNode(evt.data));el.appendChild(document.createElement('br'));
};

4. StreamingResponseBody

Lastly, we can use StreamingResponseBody to write directly to an OutputStream before passing that written information back to the client using a ResponseEntity.

4.1. Server Side

@Controller
public class StreamingResponseBodyController {@GetMapping("/srb")public ResponseEntity<StreamingResponseBody> handleRbe() {StreamingResponseBody stream = out -> {String msg = "/srb" + " @ " + new Date();out.write(msg.getBytes());};return new ResponseEntity(stream, HttpStatus.OK);}
}

4.2. Client Side

Just like before, we’ll use a regular XHR method to access the controller above:

var xhr = function(url) {return new Promise(function(resolve, reject) {var xmhr = new XMLHttpRequest();//...xmhr.open("GET", url, true);xmhr.send();//...});
};xhr('http://localhost:8080/javamvcasync/srb').then(function(success){ //... });
Copy

Next, let’s take a look at some successful uses of these examples.

5. Bringing It All Together

After we’ve successfully compiled our server and run our client above (accessing the supplied index.jsp), we should see the following in our browser:


And the following in our terminal:

We can also call the endpoints directly and see them streaming responses appear in our browser.

本文通过三类对象(ResponseBodyEmitterSseEmitterStreamingResponseBody)展示了 Spring MVC 处理异步与流式响应的不同方案,涵盖服务端实现、客户端交互及效果验证,适用于实时数据推送、大文件传输等场景。

类名特点
ResponseBodyEmitter基础异步响应,需手动管理线程与数据发送。
SseEmitter支持 SSE 协议,适合服务器主动推送多次事件(如实时通知)。
StreamingResponseBody直接操作输出流,适合大文件下载或低层级流式数据处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/18602.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

应对DeepSeek总是服务器繁忙的解决方法

最近由于访问量过大&#xff0c;DeepSeek服务器官网经常弹出&#xff1a;“服务器繁忙&#xff0c;请稍后再试”的提示&#xff0c;直接卡成PPT怎么办&#xff1f;服务器繁忙直接看到视觉疲劳&#xff1a; 解决DeepSeek卡顿问题 DeepSeek使用卡顿问题&#xff0c;是因为访问量…

GoC题解(21) 725.画迷宫(下册第4课)

题目描述 真观察下面迷宫图。发现它是一个边长逐渐变长的15边回旋图&#xff0c;边长依次为10、20、30....。 参考答案 int main(){int len0;for(int i1;i<15;i){ len10;pen.fd(len).rt(90); }return 0; } 解题思路 使用一个变量来记录每次循环时应该画多长的边&#…

STM32之SG90舵机控制

目录 前言&#xff1a; 一、硬件准备与接线 1.1 硬件清单 1.2 接线 二、 SG90舵机简介 1.1 外观 1.2 基本参数 1.3 引脚说明 1.4 控制原理 1.5 特点 1.6 常见问题 三、 单片机简介 四、 程序设计 4.1 定时器配置 4.2 角度控制函数 4.3 主函数调用 五、 总结 …

在vscode中拉取gitee里的项目并运行

拉取项目: 方法一:vscode点击查看--->终端(或者直接通过快捷键ctrol+ `打开) 在终端内通过cd命令定位到你想存放项目的文件夹 例如:cd h: 通过命令:git clone 地址 例如:git clone newbee-mall-vue-app: 前端代码 等待拉取完成即可在对应文件夹下看到项目啦 方…

机器学习实战(2):数据预处理——机器学习的第一步

第2集&#xff1a;数据预处理——机器学习的第一步 在机器学习的旅程中&#xff0c;数据预处理是至关重要的第一步。它决定了模型训练的质量和最终性能。没有经过良好预处理的数据就像未经打磨的钻石&#xff0c;虽然可能蕴含价值&#xff0c;但难以展现其光彩。今天我们将深入…

B站视频同步思维导图(全)

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z 文章目录 前言分段视频一张思维导图版本手写版本联系作者 分段视频 Java基础 并发编程 MySQL redis…

Spring中@Import原理和使用

Import注解是Spring框架中一个非常强大的工具&#xff0c;它允许你将普通类、组件类、ImportSelector实现类和ImportBeanDefinitionRegistrar实现类引入到容器中。通过Import&#xff0c;你可以实现配置的模块化&#xff0c;使得代码更加清晰和易于维护。 Spring集成很多框架时…

《pytorch》——优化器的解析和使用

优化器简介 在 PyTorch 中&#xff0c;优化器&#xff08;Optimizer&#xff09;是用于更新模型参数以最小化损失函数的关键组件。在机器学习和深度学习领域&#xff0c;优化器是一个至关重要的工具&#xff0c;主要用于在模型训练过程中更新模型的参数&#xff0c;其目标是最…

第J2周:ResNet50V2算法实战与解析

文章目录 一、准备工作1.设置GPU2.导入数据3.查看数据 二、数据预处理1.加载数据2.可视化数据 总结 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、准备工作 1.设置GPU import tensorflow as tf gpus …

CAS单点登录(第7版)18.日志和审计

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 日志和审计 Logging 概述 Logging CAS 提供了一个日志记录工具&#xff0c;用于记录重要信息事件&#xff0c;如身份验证成功和失败;可以对其进行自定义以生成用于故障排除的其他信息。…

Mybatisplus-IService

文章目录 简介IService如何继承基础业务完成复杂业务逻辑更简便的Lambda方法批处理 简介 IService类似于我们的BaseMapper吧 现在就是Service层的那些简单的CRUD也不用写了 下面是方法图 IService如何继承 不同于Mapper可以直接基础BaseMapper接口不用实现 我们的serviceIm…

一键安装教程

Maven 安装 右键 以管理员身份运行点击 下一步安装完成后会同步配置环境变量打开 cmd, 输入 mvn 查看mvn版本修改 maven 本地仓库地址 见图三, 本地新建文件夹&#xff0c;修改为你本地文件夹地址 Redis 安装 右键 以管理员身份运行点击 下一步会安装到选择的文件夹下 JAVA\R…

5分钟掌握LM Studio本地部署DeepSeek R1

文章目录 LM Studio安装与配置修改模型下载源下载DeepSeek R1模型模型选择配置模型部署API服务常见问题解决总结LM Studio安装与配置 下载地址:https://lmstudio.ai/ LM Studio 是一款专为开发者设计的轻量级集成开发环境(IDE),支持多种编程语言及框架,提供智能代码补全…

(前端基础)HTML(一)

前提 W3C:World Wide Web Consortium&#xff08;万维网联盟&#xff09; Web技术领域最权威和具有影响力的国际中立性技术标准机构 其中标准包括&#xff1a;机构化标准语言&#xff08;HTML、XML&#xff09; 表现标准语言&#xff08;CSS&#xff09; 行为标准&#xf…

Beszel监控Docker安装

一、Beszel Hub安装 #Beszel Hub安装 mkdir -p ./beszel_data && \ docker run -d \--name beszel \--restartunless-stopped \-v ./beszel_data:/beszel_data \-p 8090:8090 \henrygd/beszel#创建账号 账号/密码&#xff1a;adminadmin.com/adminadmin.com 二、Besz…

flutter image_cropper插件安装后 打包apk 报错命名空间问题

本篇文章主要讲解&#xff0c;Flutter安装完新依赖打包apk报错 A problem occurred configuring project ‘:image_cropper’. 命名空间问题的解决办法及原因说明。 日期&#xff1a;2025年2月15日 作者&#xff1a;任聪聪 一、报错现象&#xff1a; 报文信息&#xff1a; FAI…

unity学习41:动画里的曲线curve参数 和 事件 events

目录 1 曲线 curve 1.1 生成和修改曲线 1.2 曲线命名 animator参数命名&#xff0c;关联起来 1.3 可以修改animator的参数&#xff0c;也可以获取animator的参数 1.4 用脚本获得曲线的参数数值&#xff0c;并打印出来 1.4.1 获得曲线的test1参数 1.4.2 代码 1.4.3 测…

JVM学习

JVM 1、JVM是一个跨语言的平台&#xff0c;与语言无关 2、java虚拟机规范&#xff1a;一流企业做标准&#xff0c;二流企业做品牌&#xff0c;三流企业做产品 JVM种类 Hotspot&#xff1a;Oracle 公司&#xff0c;有商业版和免费版 open jdk 内部包含免费版本hotspot虚拟机 Jr…

DeepSeek 助力 Vue 开发:打造丝滑的开关切换(Switch)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

141,【1】buuctf web [SUCTF 2019]EasyWeb

进入靶场 代码审计 <?php // 定义函数get_the_flag&#xff0c;功能是处理文件上传相关操作 function get_the_flag() {// 注释说明&#xff1a;webadmin会每隔20分钟删除用户上传的文件$userdir "upload/tmp_" . md5($_SERVER[REMOTE_ADDR]);// 检查用户目录…