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

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

相关推荐
weixin_427771618 分钟前
前端调试隐藏元素
前端
Java小生不才20 分钟前
Spring AI文生音
java·人工智能·spring
凯尔萨厮24 分钟前
Springboot2.x+Thymeleaf项目创建
java
fish_xk36 分钟前
map和set
java·开发语言
李崧正1 小时前
Java技术分享:Lambda表达式与函数式编程
java·开发语言·python
老了,不知天命1 小时前
鳶尾花項目JAVA
java·开发语言·机器学习
二哈赛车手1 小时前
新人笔记---实现简易版的rag的bm25检索(利用ES),以及RAG上传时的ES与向量数据库双写
java·数据库·笔记·spring·elasticsearch·ai
winner88811 小时前
从零吃透C++命名空间、std、#include、string、vector
java·开发语言·c++
爱上好庆祝1 小时前
学习js的第五天
前端·css·学习·html·css3·js
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题】【Java基础篇】第26题:Java的抽象类和接口有哪些区别
java·开发语言·面试