您现在的位置是:首页 > 经典句子

想在controller里面把实时调第三方模型的实时返回的流式数据,按每句话用String类型return给前端

作者:焦糖时间:2024-05-12 10:48:32分类:经典句子

简介  文章浏览阅读1.1k次,点赞24次,收藏16次。方法是异步的,并使用一个新线程或者异步任务来获取第三方模型的实时数据,并将数据逐行发送给客户端。对象,并在一个新的线程中启动了获取第三方模型实时数据的任务。每获取到一行数据,就使用。中将实时调用第三方模型的流式数

点击全文阅读

1、如果想在 Controller 中将实时调用第三方模型的流式数据逐行返回给前端,可以使用 Spring MVC 的 ResponseBodyEmitter。在这种情况下,需要确保 Controller 方法是异步的,并使用一个新线程或者异步任务来获取第三方模型的实时数据,并将数据逐行发送给客户端。
import org.springframework.http.MediaType;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;@RestController@RequestMapping("/api")public class YourController {    @PostMapping("/streamData")    public ResponseBodyEmitter streamData() {        ResponseBodyEmitter emitter = new ResponseBodyEmitter();        // 启动一个新的线程来处理数据流        new Thread(() -> {            String apiUrl = "your_api_url_here";            try {                URL url = new URL(apiUrl);                HttpURLConnection connection = (HttpURLConnection) url.openConnection();                // 设置请求方法为POST                connection.setRequestMethod("POST");                connection.setDoOutput(true);                // 获取输入流,这里是获取返回的数据流                InputStream inputStream = connection.getInputStream();                // 处理输入流,这里可以根据需要进行流式处理                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));                String line;                while ((line = reader.readLine()) != null) {                    // 发送每行数据给客户端                    try {                        emitter.send(line, MediaType.TEXT_PLAIN);                    } catch (IOException e) {                        e.printStackTrace();                        // 处理发送异常,比如客户端断开连接                        break;                    }                }                // 关闭资源                reader.close();                // 获取响应码,根据需要处理                int responseCode = connection.getResponseCode();                System.out.println("Response Code: " + responseCode);                // 断开连接                connection.disconnect();                // 发送完成信号                try {                    emitter.complete();                } catch (IOException e) {                    e.printStackTrace();                }            } catch (IOException e) {                e.printStackTrace();                // 发送错误信号                try {                    emitter.completeWithError(e);                } catch (IOException ex) {                    ex.printStackTrace();                }            }        }).start();        return emitter;    }}

        在这个例子中,streamData 方法返回了 ResponseBodyEmitter 对象,并在一个新的线程中启动了获取第三方模型实时数据的任务。每获取到一行数据,就使用 emitter.send(line, MediaType.TEXT_PLAIN) 将数据逐行发送给客户端。

2、执行逻辑

当使用 ResponseBodyEmitter 时,你实际上创建了一个可以异步写入响应体的对象。在这个具体的例子中,当请求到达 /api/streamData 接口时,streamData 方法会创建一个 ResponseBodyEmitter 对象,并返回给客户端。

在这个方法内,我们启动了一个新的线程,该线程负责调用第三方模型,并从模型那里获取流式数据。具体来说,我们使用 HttpURLConnection 打开一个连接到第三方 API(your_api_url_here),发送 POST 请求,并获取该 API 返回的输入流(InputStream)。

接下来,我们创建一个 BufferedReader 来逐行读取从第三方 API 返回的数据流。对于每一行数据,我们使用 emitter.send(line, MediaType.TEXT_PLAIN) 将数据发送到客户端。这实际上是将数据推送给客户端,而不是等待客户端拉取数据。

在发送数据的过程中,我们对异常进行了处理。如果客户端断开连接或者其他错误发生,我们捕获 IOException 并相应地处理。最终,在处理完数据流之后,我们发送 complete 信号,表示数据流传输完成。

这种方式允许你在异步的情况下,实时地将第三方模型返回的数据发送给客户端。客户端可以通过订阅这个接口来获取实时数据,而不需要等待整个流程执行完毕。

请注意,这里使用了一个简单的线程来执行异步任务,但在实际应用中,你可能会考虑使用 Spring 的异步特性,例如 @Async 注解结合 ThreadPoolTaskExecutor,以便更好地管理异步任务。

3、客户端如何订阅接收返回的ResponseBodyEmitter ?

在前端使用 WebSocket 订阅数据的步骤包括创建 WebSocket 连接、监听连接状态、发送和接收消息等。以下是一个简单的使用 WebSocket 的示例,假设你的后端已经支持 WebSocket:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>WebSocket Example</title></head><body><script>    // 创建 WebSocket 连接,指定连接的地址    const socket = new WebSocket('ws://your-server-address/api/streamData');    // 监听连接打开事件    socket.addEventListener('open', (event) => {        console.log('WebSocket连接已打开:', event);    });    // 监听连接关闭事件    socket.addEventListener('close', (event) => {        console.log('WebSocket连接已关闭:', event);    });    // 监听接收到消息事件    socket.addEventListener('message', (event) => {        // 处理从服务器收到的消息        const data = event.data;        console.log('收到消息:', data);        // 在这里,你可以将 data 渲染到页面上,或者进行其他业务逻辑的处理    });    // 监听发生错误事件    socket.addEventListener('error', (event) => {        console.error('WebSocket连接发生错误:', event);    });    // 当页面卸载时,关闭 WebSocket 连接    window.addEventListener('beforeunload', () => {        socket.close();    });</script></body></html>

这个示例中,我们创建了一个 WebSocket 连接到 ws://your-server-address/api/streamData,这个地址应该替换为你实际的后端 WebSocket 地址。然后,我们监听连接打开、关闭、接收消息和错误等事件。

message 事件中,我们处理从服务器端实时传输过来的数据。这个数据可能是由 ResponseBodyEmitter 在后端逐行发送的。你可以根据你的需求,将这些数据渲染到页面上或者进行其他业务逻辑的处理。

确保你的后端代码正确处理 WebSocket 连接,以及在适当的时候关闭连接。这样,前端就能够通过 WebSocket 实时接收到后端发送的数据。

请注意:

new WebSocket('ws://your-server-address/api/streamData') 中的 your-server-address 应该替换为你实际的后端服务器地址。如果你的后端支持 wss(WebSocket Secure),你应该使用 wss 而不是 ws。这个示例假设你的后端已经提供了 WebSocket 服务,并且在 /api/streamData 路径上提供了 WebSocket 端点。你需要确保后端正确处理 WebSocket 连接,并在数据准备好时通过 WebSocket 发送给客户端。在 message 事件中,你可以处理从服务器端收到的实时数据。你可以将这些数据渲染到页面上,或者进行其他业务逻辑的处理。

在实际应用中,你可能需要根据你的业务逻辑定制 WebSocket 的行为,并添加更多的错误处理和状态管理。

4、data 参数的含义

ResponseBodyEmitter 是用于在 Spring MVC 中异步发送响应数据的类。在这个场景下,data 参数中包含的数据是在后端逐行发送给前端的实时数据。

具体来说,data 包含的是每一行文本数据,这取决于后端代码如何使用 ResponseBodyEmitter 来发送数据。在先前的例子中,我们通过 emitter.send(line, MediaType.TEXT_PLAIN) 来发送每一行数据,而这个数据就是 line

举例来说,如果后端的逻辑是读取一个文本文件,逐行发送给前端,那么 data 就是文本文件中的每一行数据。如果后端的逻辑是调用某个 API 获取实时数据,那么 data 就是从该 API 获取到的每一行数据。

点击全文阅读

郑重声明:

本站所有活动均为互联网所得,如有侵权请联系本站删除处理

我来说两句