通过WebSocket连接的Spring SseEmitter

Zuberuber

我的目标是从前端向后端发送一个请求并接收多个响应。我使用WebSocket的原因是响应非常频繁,WebSocket似乎是执行此操作的最佳协议,并且SseEmitter从后端发送多个响应。

这是我的请求控制器:

@MessageMapping("/emitter")
@SendTo("/topic/response")
public SseEmitter output(RunData runData) throws Exception {
    SseEmitter emitter = new SseEmitter();
    new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                RemoteHostController rhc = new RemoteHostController(runData);
                rhc.execute();
                while (rhc.getActiveCount() > 0) {
                    emitter.send(rhc.getAllOutput());
                    Thread.sleep(2000);
                }

                 emitter.complete();
            } catch (Exception ee) {
                ee.printStackTrace();
                emitter.completeWithError(ee);
            }
        }
    }).start();

    return emitter;
}

RemoteHostController正在管理连接,并且getAllOutput返回主机的输出。

前端应用程序正在运行非常简单的index.html,它使用Stomp和SockJS连接到Websocket,将数据发送到服务器并生成

标记来自响应的数据:

function connect() {
        var socket = new SockJS('http://localhost:8080/emitter');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function(frame) {
            setConnected(true);
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/response', function(greeting){
                showOutput(greeting.body);
            });
        });
}

function sendData() {
        var hostname = document.getElementById('hostname').value;
        var username = document.getElementById('username').value;
        var password = document.getElementById('password').value;
        var command = document.getElementById('command').value;
        stompClient.send("/app/emitter", {}, JSON.stringify({ 'hostname': hostname,
                                                    'username': username,
                                                    'password': password,
                                                    'command': command}));
}

function showOutput(message) {
        var response = document.getElementById('response');
        var p = document.createElement('p');
        p.style.wordWrap = 'break-word';
        p.appendChild(document.createTextNode(message));
        response.appendChild(p);
}

当我将数据发送到后端时,只有响应:

{"timeout":null}

这是SseEmitter超时字段,当我更改超时时,它将返回{"timeout":<timeout_value>}

我在日志中看到RemoteHostController正在连接到主机并正确执行命令。

难道我做错了什么?还是WebSocket只支持一个请求一个响应通信?

罗伯·贝利

这是WebSocket和SSE的示例。如上所述,IE浏览器不支持SSE。为了达到完整性,请尽可能多地添加。确保在使用SeeEmitter时没有使用RestController,因为这将返回对象,这是我从上面的描述中得出的猜测。

pom.xml

<dependencies>
    <!-- Spring boot framework -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
</dependencies>

Web套接字配置:

@Configuration
@EnableWebSocketMessageBroker
public class ApplicationWebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        super.configureMessageBroker(registry);
        registry.enableSimpleBroker("/topic");
    }

    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        stompEndpointRegistry.addEndpoint("/socketrequest").withSockJS();
    }
}

索取资料:

public class RequestData {
    private String string1;
    private String string2;
    // excluding getters and setters
}

Web套接字控制器:

@Controller
public class WebSocketController {
   @Autowired
    SimpMessagingTemplate simpMessagingTemplate;

    @MessageMapping("/processrequest")
    void runWebSocket( RequestData requestData ) {
        new Thread(new RunProcess(requestData)).start();
    }

    private class RunProcess implements Runnable {
        private RequestData requestData;

        RunProcess(RequestData requestData) {
            this.requestData = requestData;
        }

        public void run() {
            simpMessagingTemplate.convertAndSend("/topic/response", requestData.getString1());
            simpMessagingTemplate.convertAndSend("/topic/response", requestData.getString2());
            simpMessagingTemplate.convertAndSend("/topic/response", "A third response via websocket");
        }
    }
}

该控制器:

@Controller
public class SseController {

    @RequestMapping("/emitter")
    public SseEmitter runEmitter(@RequestParam(value = "string1") String string1,
                                 @RequestParam(value = "string2") String string2)
    {
        SseEmitter sseEmitter = new SseEmitter();
        RequestData requestData = new RequestData();
        requestData.setString1(string1);
        requestData.setString2(string2);
        new Thread(new RunProcess(requestData,sseEmitter)).start();
        return sseEmitter;
    }

    private class RunProcess implements Runnable {
        private RequestData requestData;
        private SseEmitter sseEmitter;

        RunProcess(RequestData requestData, SseEmitter sseEmitter) {
            this.requestData = requestData;
            this.sseEmitter = sseEmitter;
        }

        public void run() {
            try {
                sseEmitter.send(requestData.getString1());
                sseEmitter.send(requestData.getString2());
                sseEmitter.send("A third response from SseEmitter");
                sseEmitter.complete();
            } catch (IOException e) {
                e.printStackTrace();
                sseEmitter.completeWithError(e);
            }
        }
    }

}

HTML代码:

    <script src="/javascript/sockjs-0.3.4.js"></script>
    <script src="/javascript/stomp.js"></script>

    <script type="text/javascript">
    var stompClient = null;

    function connect() {
        var socket = new SockJS('http://localhost:8085/socketrequest');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function(frame) {
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/response', function(message){
                showOutput(message.body);
            });
        });
    }

    function doWebsocket() {
        stompClient.send("/processrequest", {}, JSON.stringify({ 'string1': 'The first string', 'string2' : 'The second string' }));
    }


    function doSse() {
        console.log("doSse");
        var rtUrl= '/emitter?string1=first string sse&string2=second string sse';
        var source = new EventSource(rtUrl);
        source.onmessage=function(event){
            showOutput(event.data)
        };
    }

    function showOutput(message) {
        var response = document.getElementById('response');
        var p = document.createElement('p');
        p.style.wordWrap = 'break-word';
        p.appendChild(document.createTextNode(message));
        response.appendChild(p);
    }

    connect();

    </script>
    </head>

<div>
Starting page
</div>
<div>
    <button id="websocket" onclick="doWebsocket();">WebSocket</button>
    <button id="sse" onclick="doSse();">Server Side Events</button>
</div>
<div >
    Response:
    <p id="response"></p>
</div>

</html>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

通过WebSocket连接的Spring SseEmitter

来自分类Dev

Spring SseEmitter超时时如何避免HttpMediaTypeNotAcceptableException

来自分类Dev

Java Spring SseEmitter / ResponseBodyEmitter:检测浏览器重载

来自分类Dev

SseEmitter的春季休息服务

来自分类Dev

应春SseEmitter.complete()触发一个EventSource的重新连接 - 如何紧密连接服务器端

来自分类Dev

通过WebSocket连接同步集合

来自分类Dev

Websocket跟踪Spring中的连接

来自分类Dev

Spring WebFlux认证的WebSocket连接

来自分类Dev

SseEmitter和jackson没有适合于类java.lang.String的转换器

来自分类Dev

Websocket通过Amazon ELB的连接错误

来自分类Dev

strophe无法通过websocket连接openfire

来自分类Dev

客户端 websocket 通过代理连接

来自分类Dev

WebSocket 通过 ws 未连接但 wss 是

来自分类Dev

无法连接到Spring AbstractWebSocketMessageBrokerConfigurer上的WebSocket

来自分类Dev

Spring如何管理Websocket与RabbitMQ的连接?

来自分类Dev

无法连接到Spring AbstractWebSocketMessageBrokerConfigurer上的WebSocket

来自分类Dev

通过LAN IP地址连接WebSocket服务器

来自分类Dev

仅允许通过一个URL进行websocket连接

来自分类Dev

通过 Caddy 保护最重要的连接,但 websocket 不起作用

来自分类Dev

通过管道而不是 websocket 连接 Puppeteer 的优缺点是什么

来自分类Dev

Spring Websocket和404连接状态

来自分类Dev

在Spring Boot中编写客户端以连接到Websocket

来自分类Dev

Spring Boot WebSocket Rabbitmq Stomp Broker无法保持连接

来自分类Dev

Spring Websocket践踏客户端如何捕获丢失的连接?

来自分类Dev

Spring Websocket和404连接状态

来自分类Dev

连接后Spring WebSocket不发送队列后缀

来自分类Dev

Spring Websocket获取连接号和详细信息

来自分类Dev

Spring JPA PageRequest通过连接列排序

来自分类Dev

Spring TCP 通过传入连接发送数据

Related 相关文章

  1. 1

    通过WebSocket连接的Spring SseEmitter

  2. 2

    Spring SseEmitter超时时如何避免HttpMediaTypeNotAcceptableException

  3. 3

    Java Spring SseEmitter / ResponseBodyEmitter:检测浏览器重载

  4. 4

    SseEmitter的春季休息服务

  5. 5

    应春SseEmitter.complete()触发一个EventSource的重新连接 - 如何紧密连接服务器端

  6. 6

    通过WebSocket连接同步集合

  7. 7

    Websocket跟踪Spring中的连接

  8. 8

    Spring WebFlux认证的WebSocket连接

  9. 9

    SseEmitter和jackson没有适合于类java.lang.String的转换器

  10. 10

    Websocket通过Amazon ELB的连接错误

  11. 11

    strophe无法通过websocket连接openfire

  12. 12

    客户端 websocket 通过代理连接

  13. 13

    WebSocket 通过 ws 未连接但 wss 是

  14. 14

    无法连接到Spring AbstractWebSocketMessageBrokerConfigurer上的WebSocket

  15. 15

    Spring如何管理Websocket与RabbitMQ的连接?

  16. 16

    无法连接到Spring AbstractWebSocketMessageBrokerConfigurer上的WebSocket

  17. 17

    通过LAN IP地址连接WebSocket服务器

  18. 18

    仅允许通过一个URL进行websocket连接

  19. 19

    通过 Caddy 保护最重要的连接,但 websocket 不起作用

  20. 20

    通过管道而不是 websocket 连接 Puppeteer 的优缺点是什么

  21. 21

    Spring Websocket和404连接状态

  22. 22

    在Spring Boot中编写客户端以连接到Websocket

  23. 23

    Spring Boot WebSocket Rabbitmq Stomp Broker无法保持连接

  24. 24

    Spring Websocket践踏客户端如何捕获丢失的连接?

  25. 25

    Spring Websocket和404连接状态

  26. 26

    连接后Spring WebSocket不发送队列后缀

  27. 27

    Spring Websocket获取连接号和详细信息

  28. 28

    Spring JPA PageRequest通过连接列排序

  29. 29

    Spring TCP 通过传入连接发送数据

热门标签

归档