技术探索

java+vue使用长链接的方式发送文本

QQ5736Lv.1 平民

2026-10-20 11:41 (北京时间)

使用模型生成问题答案时,由于是一个一个字或词生成的,前端等待后台所有答案生成后再返回体验极其不好,使用SseEmitter建立长链接

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
 
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
@RestController
public class StreamController {
 
    @GetMapping("/stream")
    public SseEmitter streamData() {
        SseEmitter emitter = new SseEmitter();
 
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(() -> {
            try {
                String data = "Hello word!!!!";  //文本
                for (int i = 0; i < data.length(); i++) {
                    emitter.send(String.valueOf(data.charAt(i)));
                    Thread.sleep(1000);  // 等待一秒
                }
                emitter.complete();
            } catch (IOException | InterruptedException e) {
                emitter.completeWithError(e);
            }
        });
        executor.shutdown();
 
        return emitter;
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Stream Data</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1>Received Data: {{ receivedMessage }}</h1>
    </div>
 
    <script>
        new Vue({
            el: '#app',
            data: {
                receivedMessage: ''
            },
            mounted() {
                this.connect();
            },
            methods: {
                connect() {
                    const eventSource = new EventSource('http://localhost:8080/stream');
                    eventSource.onmessage = event => {
                        this.receivedMessage += event.data;
                    };
                    eventSource.onerror = error => {
                        console.error('EventSource failed:', error);
                        eventSource.close();
                    };
                }
            }
        });
    </script>
</body>
</html>

在后端,我们使用SseEmitter来发送SSE 消息。我们创建一个线程来模拟发送数据,每隔一秒发送一个字符。在前端,我们使用Vue.js创建一个简单的应用程序来监听这些SSE消息。每当接收到一个字符时,它就会被添加到receivedMessage中,并立即显示在页面上。

这样,你就可以看到后端每秒发送一个字符,前端也会实时更新显示这些字符。

IMG_0755