如何在Java springboot中从一个端点发送多个时间响应?

1hdlvixo  于 5个月前  发布在  Spring
关注(0)|答案(2)|浏览(42)

场景:
我有30个端到端流程流的测试用例,包括(调度器,生产者和消费者)。所以,我在java springmvc web应用程序中自动化了30个测试用例。我已经创建了一个端点,它将开始测试,然后它将依次运行30个测试用例,我为每个测试用例创建了30个方法,每个测试用例大约需要5分钟才能完成,因为(必须执行调度程序,生产者和消费者)。所以,在一个测试用例完成后,我想在UI中显示状态和消息,我不想等到所有30个测试用例完成后才显示所有测试用例的状态。如何使用rest endpoint实现这一点?

a11xaf1n

a11xaf1n1#

摘要

通过同一个端点发送多个消息,这不是REST API的情况。通常,我们经常使用长连接来处理这种情况,有很多技术可以选择,如WebSocket,tcp协议,socket,但它们都太重了,只是发送一个消息到指定的主机可能会配置这么多。

解决方案

简而言之,有Server-Sent Events可以很容易地解决你的问题,我会演示bacic demo为这项技术在 Spring ,也可以阅读官方 Spring sse文档

1.在spring中设置endpoint

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

import java.io.IOException;

@RestController
@RequestMapping("/sse")
public class SseController {

    @GetMapping("/events")
    public SseEmitter handleSse() {
        SseEmitter emitter = new SseEmitter();

        // Asynchronous processing to send events
        new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    // Send events every 1 second
                    emitter.send(SseEmitter.event().name("message").data("Event " + i));

                    Thread.sleep(1000);
                }
                // Signal the end of the event stream
                emitter.complete();
            } catch (IOException | InterruptedException e) {
                emitter.completeWithError(e);
            }
        }).start();

        return emitter;
    }
}

字符串

客户端连接端点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SSE Example</title>
</head>
<body>
    <h1>SSE Example</h1>
    <div id="sse-events"></div>

    <script>
        const eventSource = new EventSource('/sse/events');

        eventSource.onmessage = function (event) {
            const eventsDiv = document.getElementById('sse-events');
            eventsDiv.innerHTML += `<p>${event.data}</p>`;
        };

        eventSource.onerror = function (error) {
            console.error('EventSource failed:', error);
            eventSource.close();
        };
    </script>
</body>
</html>


在本例中,SseController中的/sse/events端点返回一个SseEEvent,并使用一个单独的线程异步发送事件。客户端的JavaScript代码使用EventSource API来侦听事件并更新HTML内容。
请记住使用适当的依赖项配置Sping Boot 应用程序,并且您可能需要在生产场景中适当地处理异常和清理。

附录

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.4.2</version> // replace appropriate  version , 3.0.0 or else later is ok
      </dependency>


你可以在下面的包路径中找到主类(可能与其他spring Boot 版本不同)

org.springframework.web.servlet.mvc.method.annotation.SseEmitter

uujelgoq

uujelgoq2#

为了在Sping Boot 应用程序中实现测试用例状态的实时更新,您需要使用异步通信方法。传统的REST端点是同步的,基于请求-响应,这意味着客户端发出请求并等待响应,这不适合您的需求。这里有一些您可以考虑的方法:

  1. WebSocket:这对于服务器和客户端之间的实时通信是一个很好的选择。Sping Boot 支持WebSocket,它允许双向通信。每次测试用例完成时,您可以向客户端发送消息。
    1.Server-Sent Events(SSE):SSE是WebSockets的一个更简单的替代方案。它允许服务器将数据推送到客户端。它是从服务器到客户端的单向通信。Spring通过SseEmitter类支持SSE。
    1.长轮询:这是另一种方法,客户端向服务器发出请求,服务器保持请求打开,直到有新数据发送回来。它比WebSockets或SSE效率低,但在某些情况下更容易实现。
    1.短信提示:使用像RabbitMQ或Apache Kafka这样的消息代理,您可以将消息(测试用例状态)发布到队列/主题,并且客户端可以订阅这些消息。这可能设置起来更复杂,但功能非常强大且可扩展。
    实现这些功能都需要在服务器端和客户端做一些修改。下面是如何进行的一般想法:
  • 修改端点以异步启动测试用例。您可以在Sping Boot 中使用@Async annotation轻松异步运行方法。
  • 选择实时通信方法(WebSocket、SSE等)。
  • 实现服务器端逻辑以在每个测试用例完成后发送更新。
  • 更新您的客户端应用程序以处理这些实时更新。

请记住,具体的实现将取决于应用程序的特定技术和体系结构。

相关问题