SpringMVC流式返回数据

2025-04-06 00:28:51 5

    @GetMapping("/get")
    public ResponseBodyEmitter get(@RequestParam String question) {

        ResponseBodyEmitter emitter = new ResponseBodyEmitter();

        threadPool.submit(() -> {
            try {
                String prompt = "...";
                Flux<ChatResponse> responseFlux = chatclient.prompt(prompt)
                        .user(question)
                        .stream().chatResponse();

                responseFlux.subscribe(chatResponse -> {
                    try {
                        AssistantMessage output = chatResponse.getResult().getOutput();
                        emitter.send(output);
                    } catch (Exception e) {
                        emitter.completeWithError(e);
                        log.error(e.getMessage(), e);
                    }
                }, emitter::completeWithError, emitter::complete);
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        });

        return emitter;
    }


前端根据数据的格式处理即可


        const eventSource = new EventSource("/get?question=Hello");

        eventSource.onmessage = function(event) {
            const chatOutput = document.getElementById("chat-output");
            chatOutput.innerHTML += `<p>${event.data}</p>`;
        };

        eventSource.onerror = function(event) {
            console.error("EventSource failed:", event);
            eventSource.close();
        };


fetch api


export const postStream = async () => {
  const abortController = new AbortController(); // 创建 AbortController 实例
  const signal = abortController.signal; // 获取 signal 对象

  try {
    const postData = {
      key1: 'value1',
      key2: 'value2',

    };

    let response = await fetch("/api/admin/common/testStream", {
      method: 'POST', // 使用 POST 方法
      headers: {
        'Content-Type': 'application/json', // 设置请求头
        'Authorization': 'Bearer your_token_here', // 如果需要认证,可以添加 Authorization 头
        // 其他自定义请求头
      },
      body: JSON.stringify(postData), // 将 JSON 数据转换为字符串
      signal: signal, // 传递 signal 以支持取消
    });
    console.log(response);

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    const body = response.body as ReadableStream<Uint8Array<ArrayBufferLike>>;
    const reader = body.getReader();
    const textDecoder = new TextDecoder();
    let result = true;
    let output = "";

    while (result) {
      const { done, value } = await reader.read();

      if (done) {
        console.log("Stream ended");
        result = false;
        break;
      }

      const chunkText = textDecoder.decode(value);
      output += chunkText;
      console.log("Received chunk:", chunkText);
    }
  } catch (e) {
    if (e.name === 'AbortError') {
      console.log("请求已被取消"); // 捕获取消请求的错误
    } else {
      console.log(e); // 捕获其他错误
    }
  }

  // 暴露 abort 方法,供外部调用取消请求
  return () => abortController.abort();
};


如果经过了代理层, 比如nginx, 需要配置禁用缓冲

proxy_buffering off;


SpringMVC流式返回数据

@GetMapping("/get") public ResponseBodyEmitter get(@RequestParam String question) { ResponseBodyEmitter emitter = new ResponseBodyEmi
2025-04-06
基于Ollama本地部署deepseek-r1:8b

基于Ollama本地部署deepseek-r1:8b

下载ollama https://ollama.com/ 设置好环境变量, 更换模型的存储位置OLLAMA_MODELS下载大模型命令行中输入ollama run deepseek-r1:8b
2025-02-22

x-www-form-urlencoded 自动转小写

场景用户进行邮箱验证, 发送成功了, 验证码也收到了, 也提交对了. 但, 就是不通过.原因前端通过form表单提交的数据 application/x-www-form-urlencoded后端接收的时候, 大写被自动转成了小写.SpringBoot: 1.5.10.RELEASE
2024-11-17

Stable-Diffusion AI 绘画

git clone https://github.com/CompVis/stable-diffusion.git进入stable-diffusion目录在这里注册一个账号: https://huggingface.co/ 并生成个token安装CUDA https://blog.csdn.net/
2023-06-13
手写Spring、SpringMVC

手写Spring、SpringMVC

目前实现了以下注解@Autowired 从容器中自动注入@Bean 标记方法返回值加入容器管理@Component 标记此类加入容器管理@RestController 标记此类为Rest风格的控制器 结果默认转为json@RequestMapping 前置匹配路径@GetMapping 匹配一个Ge
2020-07-01

freemarker 时间显示不正常 设置时区

项目在本地开发的时候显示正常,部署上服务器就一直差8个小时,最后发现freemarker官方文档有这样的说明time_zone:时区的名称来显示并格式化时间。 默认情况下,使用JVM的时区。 也可以是 Java 时区 API 接受的值,或者 "JVM default" (从 FreeMarker 2
2020-03-28
IDEA 2019.1 xml 不高亮

IDEA 2019.1 xml 不高亮

前几天更新了idea后,发现xml里的代码都没有了高亮,变得跟记事本一个德性了打开setting ,搜索 File Types,找到xml项, 查看下方的匹配格式,果然没有xml,(idea真是厉害)点击右方的+,输入*.xml,点击ok,解决问题
2020-03-28

npm install 淘宝镜像

npm install --registry=https://registry.npm.taobao.org
2020-03-28
Java中方法的参数传递机制

Java中方法的参数传递机制

来看一段代码 public class Man { private String name; private Integer age; public String getName() { return name; } publi
2020-03-28
基于自定义注解手写权限控制

基于自定义注解手写权限控制

方法一: AOP 方法二: 拦截器项目结构项目依赖<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-w
2020-03-28

Docker 部署 详细全过程 附代码

Docker 部署本站 全过程环境:CentOS7.61. 安装Docker其他版本CentOS可以参考这个https://help.aliyun.com/document_detail/187598.html查看本机内核版本,内核版本需高于 3.10uname -r 确保 yum 包最新yum u
2020-03-28

SpringBoot 启动普通java工程

引入依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.0.9</version> </dependency>
2020-03-28

Vue.js DOM操作

<template> <input type="button" @click="reply($event)" value="回复"> </template> export default { methods: { replyFun(e) {
2020-03-29
CentOS7编译调试OpenJDK12

CentOS7编译调试OpenJDK12

1. 下载源码https://hg.openjdk.java.net/jdk/jdk12点击左侧的browse,再点击zip,就可以下载zip格式的源码压缩包。unzip xxx.zip 解压文件2. 安装jdkyum install java-11-openjdk-devel -y3. 运行con
2020-04-23
编写自己的Spring Boot Starter

编写自己的Spring Boot Starter

1.新建一个maven项目命名规则统一是xxx-spring-boot-starter完整pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"
2020-06-29