【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()

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

相关推荐
花生Peadar9 分钟前
AI编程从入门到精通
前端·后端·代码规范
bug爱好者10 分钟前
vue3.x 使用vue3-tree-org实现组织架构图 + 自定义模版内容 - 附完整示例
前端·javascript·vue.js
百***355116 分钟前
Tomcat10下载安装教程
java
达达尼昂20 分钟前
🎯 Flutter 拖拽选择组件:flutter_drag_selector —— 像选文件一样选择列表项
前端·flutter
q***071425 分钟前
Spring Boot 从 2.7.x 升级到 3.3注意事项
数据库·hive·spring boot
Keely4028539 分钟前
Claude 配置使用墨刀MCP(modao-proto-mcp)
前端·aigc·claude
一心只读圣贤猪40 分钟前
Canal ES Adapter pkVal 为 null 问题解决方案
java·后端
少卿44 分钟前
从零构建 React Native 导航体系-React Navigation
前端·react native
Wect1 小时前
学习React-DnD:实现 TodoList 简单拖拽功能
前端·react.js
前端小书生1 小时前
Google Map、Solar Api
前端·react.js·google