最近在写ai返回的时候,使用到了这个工具类 在这里记录一下

在现代Web开发中,尤其是在处理长时间运行的请求时,如何有效地管理和返回响应成为了一个重要的话题。在此背景下,Spring框架提供了 ResponseBodyEmitter 类,以支持异步和基于事件的响应处理。

什么是 ResponseBodyEmitter?

ResponseBodyEmitter 是 Spring 提供的一个类,允许在处理请求时逐步发送数据。这种方式特别适合于实时数据传输或长时间运行的操作,如流式数据、服务器推送事件(Server-Sent Events, SSE)等。

主要特点

  • 异步支持:可以在处理请求时不阻塞服务器线程,从而提高应用的响应能力。

  • 逐步响应:允许在请求处理的过程中逐步发送数据,而不是等待所有数据准备好后再发送。

  • 事件触发:可以根据特定事件触发响应的发送。

如何使用 ResponseBodyEmitter

1. 创建 Emitter

首先,你需要在控制器中创建一个 ResponseBodyEmitter 实例。例如:

java复制代码

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;

@RestController
public class MyController {

    @GetMapping("/stream")
    public ResponseBodyEmitter handle() {
        ResponseBodyEmitter emitter = new ResponseBodyEmitter();
        // 这里可以添加数据处理逻辑
        return emitter;
    }
}

2. 发送数据

在处理请求的过程中,可以通过 ResponseBodyEmittersend() 方法逐步发送数据。例如:

java复制代码

import java.util.concurrent.Executors;

@GetMapping("/stream")
public ResponseBodyEmitter handle() {
    ResponseBodyEmitter emitter = new ResponseBodyEmitter();
    
    Executors.newSingleThreadExecutor().submit(() -> {
        try {
            emitter.send("数据片段1");
            Thread.sleep(1000); // 模拟延迟
            emitter.send("数据片段2");
            Thread.sleep(1000);
            emitter.send("数据片段3");
            emitter.complete(); // 完成响应
        } catch (Exception e) {
            emitter.completeWithError(e); // 处理异常
        }
    });

    return emitter;
}

3. 处理异常和完成

使用 complete() 方法来标记响应已完成,使用 completeWithError() 方法来处理异常情况。

实际使用示例

ResponseBodyEmitter emitter = new ResponseBodyEmitter();
        emitter.onCompletion(() -> {
            logger.info("开始使用gpt模型进行问答");
        });
        emitter.onError(throwable -> logger.error(throwable.getMessage()));
        Flux<ChatResponse> res = chatModel.stream(Prompt.builder().messages(UserMessage.builder().text("讲个笑话").build(),systemMessage)
                .build());
        res.subscribe(chatResponse -> {
                    if(Objects.nonNull(chatResponse.getResult().getOutput().getText())){
                        try {
                            emitter.send(chatResponse.getResult().getOutput().getText());
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }

                },
                error -> {
                    logger.info(error.getMessage());
                },
                emitter::complete


        );

        return emitter;

注意事项

  • 超时设置:可以设置 ResponseBodyEmitter 的超时时间,防止长时间未响应造成连接问题。

  • 资源管理:确保在完成响应后正确释放资源,以避免内存泄漏。

  • 线程安全:确保在多线程环境下对 ResponseBodyEmitter 的调用是线程安全的。

总结

ResponseBodyEmitter 是一个强大且灵活的工具,适用于需要实时数据传输的场景。通过合理的使用,可以显著提升应用的性能与用户体验。