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

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

相关推荐
无巧不成书02182 小时前
30分钟入门Java:从历史到Hello World的小白指南
java·开发语言
anOnion3 小时前
构建无障碍组件之Carousel Pattern
前端·html·交互设计
ssshooter3 小时前
Tauri 2 iOS 开发避坑指南:文件保存、Dialog 和 Documents 目录的那些坑
前端·后端·ios
Можно4 小时前
深入理解 ES6 Proxy:与 Object.defineProperty 的全面对比
前端·javascript·vue.js
zs宝来了4 小时前
Playwright 自动发布 CSDN 的完整实践
java
Birdy_x4 小时前
接口自动化项目实战(1):requests请求封装
开发语言·前端·python
彭于晏Yan5 小时前
Redisson分布式锁
spring boot·redis·分布式
吴声子夜歌5 小时前
TypeScript——基础类型(三)
java·linux·typescript
天天向上10245 小时前
vue el-table实现拖拽排序
前端·javascript·vue.js