【Java】SpringBoot模拟流式输出,前端使用流式接收数据并打印

现在AI的接口由于生成内容比较慢都是采用的流式输出的方式。这里将模拟一下流式输出。

后端接口

java 复制代码
import cn.hutool.json.JSONUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/test")
public class TestController {

    @PostMapping("/stream")
    public ResponseEntity<StreamingResponseBody> streamData() {
        Map<String, String> map = new HashMap<>();
        map.put("content", "内容");

        StreamingResponseBody responseBody = outputStream -> {
            try (PrintWriter writer = new PrintWriter(outputStream)) {
                for (int i = 0; i < 10; i++) {
                    map.put("content", "内容:" + i);
                    writer.println(JSONUtil.toJsonStr(map));
                    writer.flush();
                    // 模拟一些延迟
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.TEXT_PLAIN);
        // 指示这是一个流式响应
        headers.setContentLength(-1L);

        return new ResponseEntity<>(responseBody, headers, HttpStatus.OK);
    }
}

传统非流式-前端

js 复制代码
url = 'http://127.0.0.1:8080/test/stream'
async function getResp(){
	const startTime = performance.now();
	console.log("非流式输出")
	const resp = await fetch(url,{
		method: 'POST',
		headers: {
			'Content-Type': 'application/json'
		},
		body: JSON.stringify({
			content: '讲个笑话'
		})
	});
	const msg = await resp.text();
	console.log(msg)
	const endTime = performance.now();
	console.log(`执行耗时: ${endTime - startTime} ms`);
}
getResp()

测试结果如下,程序会等待所有内容都返回了,才输出内容

流式-前端

js 复制代码
async function getRespStream(){
	console.log("流式输出")
	const resp = await fetch(url,{
		method: 'POST',
		headers: {
			'Content-Type': 'application/json'
		},
		body: JSON.stringify({
			content: '讲个笑话'
		})
	});
	
  const reader = resp.body.getReader();
	while(1){
		// value 是类型化数组
		const textDecoder = new TextDecoder()
		const {done,value} = await reader.read();
		if(done){
			break
		}
		const str = textDecoder.decode(value)
		console.log(str)
	}
}
getRespStream()

可以看到后端只要输出一段内容前端就会打印一段内容。

相关推荐
短剑重铸之日43 分钟前
7天读懂MySQL|Day 5:执行引擎与SQL优化
java·数据库·sql·mysql·架构
Light601 小时前
CSS逻辑革命:原生if()函数如何重塑我们的样式编写思维
前端·css·响应式设计·组件化开发·css if函数·声明式ui·现代css
酒九鸠玖1 小时前
Java--多线程
java
Dreamboat-L1 小时前
云服务器上部署nginx
java·服务器·nginx
蜡笔小嘟1 小时前
宝塔安装dify,更新最新版本--代码版
前端·ai编程·dify
长安er1 小时前
LeetCode215/347/295 堆相关理论与题目
java·数据结构·算法·leetcode·
ModyQyW2 小时前
HBuilderX 4.87 无法正常读取 macOS 环境配置的解决方案
前端·uni-app
bitbitDown2 小时前
我的2025年终总结
前端
cici158742 小时前
C#实现三菱PLC通信
java·网络·c#
五颜六色的黑2 小时前
vue3+elementPlus实现循环列表内容超出时展开收起功能
前端·javascript·vue.js