0


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

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 实时接收到后端发送的数据。

请注意:

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

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

4、
data

参数的含义

ResponseBodyEmitter

是用于在 Spring MVC 中异步发送响应数据的类。在这个场景下,

data

参数中包含的数据是在后端逐行发送给前端的实时数据。

具体来说,

data

包含的是每一行文本数据,这取决于后端代码如何使用

ResponseBodyEmitter

来发送数据。在先前的例子中,我们通过

emitter.send(line, MediaType.TEXT_PLAIN)

来发送每一行数据,而这个数据就是

line

举例来说,如果后端的逻辑是读取一个文本文件,逐行发送给前端,那么

data

就是文本文件中的每一行数据。如果后端的逻辑是调用某个 API 获取实时数据,那么

data

就是从该 API 获取到的每一行数据。

标签: java

本文转载自: https://blog.csdn.net/suukii/article/details/134992724
版权归原作者 情敌贝多芳 所有, 如有侵权,请联系我们删除。

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

还没有评论