Spring Boot和Angular2使用WebSocket(通过SockJS上的STOMP)实现REST。

6

能否在没有MVC的情况下使用stomp over sockjs?因此,我想在tomcat中拥有spring rest接口,并由express运行的angular2应用程序。

WebSocketConfig.java

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // the endpoint for websocket connections
        registry.addEndpoint("/portfolio").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.setApplicationDestinationPrefixes("/app");
        config.enableSimpleBroker("/topic");
    }
}

SocketController.java

@Controller
public class SocketController {

    @Autowired
    private SimpMessagingTemplate template;

    public SocketController() {
        int a = 5;
    }

    @MessageMapping("/greeting")
    public String handle(String greeting) {
        return "[" + "greeting" + ": " + greeting;
    }
}

并且 TypeScript 代码:

. . .

constructor() {

        var socket = new SockJS('http://localhost:8080/portfolio');
        this.stompClient = Stomp.over(socket);
        this.stompClient.connect("guest", "guest", function(frame) {
            console.log('Connected: ' + frame);
            this.stompClient.subscribe('http://localhost:8080/topic/greeting', function(greeting) {
                console.log("from from", greeting);
            });
        }, function (err) {
            console.log('err', err);
        });
    }

. . .

send() {
    this.stompClient.send("http://localhost:8080/app/greeting", {}, JSON.stringify({ 'name': "kitica" }));
}

但是由于某些原因这并没有起作用。在控制台中我得到了输出:

Opening Web Socket...
stomp.js:134 Web Socket Opened...
stomp.js:134 >>> CONNECT
login:guest
passcode:guest
accept-version:1.1,1.0
heart-beat:10000,10000



stomp.js:134 <<< CONNECTED
version:1.1
heart-beat:0,0



stomp.js:134 connected to server undefined
activity-socket.ts:17 Connected: CONNECTED
heart-beat:0,0
version:1.1

当我发送时,我会得到以下结果。

>>> SEND
destination:http://localhost:8080/app/greeting
content-length:17

{"name":"kitica"}

(这是一段JSON数据)

但消息从未返回给订阅者。

Angular2运行在端口8001,Spring Rest运行在8080端口。


如果你可以在 JS 中使用它,那么你也可以在 Angular2 中使用它。 - Günter Zöchbauer
我已经更新了问题,并提供了我尝试过的代码示例,这是根据他们的文档进行的。 - Admir Sabanovic
你是如何在 Angular2 应用中添加 SockJS 的? - khalil _diouri
如果您的问题更具体,我可以给出更合适的答案。但是,这很简单,只需运行npm install命令,然后在您的TypeScript文件中声明变量SockJS和Stomp即可。希望这有所帮助。编辑:请参考https://dev59.com/1ZXfa4cB1Zd3GeqPfHTP#37094682。 - Admir Sabanovic
3个回答

7

有点让人困惑的是,我正在使用spring-boot-rest,而不是将angular2作为静态文件从tomcat容器中提供。 我在webpack下使用angular2,因此一直在尝试订阅和发送相对URL。

正确的做法是:

import {Component} from '@angular/core';
import {ActivityService} from '../common/services';
import {MaterializeDirective} from 'angular2-materialize';
import {LarsActionButtonComponent} from '../common/components';

var SockJS = require('sockjs-client');
var Stomp = require('stompjs');

@Component({
selector: 'activity',
providers: [ActivityService],
directives: [MaterializeDirective, LarsActionButtonComponent],
templateUrl: 'app/activity/activity.html'
})

export class Activity {
stompClient: any;

activityId: any;
text: any;
messages: Array<String> = new Array<String>();

constructor() {
}

send() {
    this.stompClient.send('/app/hello/' + this.activityId, {},      JSON.stringify({ 'name': this.text }));
}

connect() {
    var that = this;
    var socket = new SockJS('tst-rest.mypageexample/hello?activityId=' + this.activityId);
    this.stompClient = Stomp.over(socket);
    this.stompClient.connect({}, function (frame) {
        console.log('Connected: ' + frame);
        that.stompClient.subscribe('/topic/greetings/' + that.activityId, function (greeting) {
            that.messages.push(JSON.parse(greeting.body).content);
        });
    }, function (err) {
        console.log('err', err);
    });
}

}

在Spring控制器中:

@Controller
public class SocketController {


@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
    return new Greeting("Hello, " + message.getName() + "!");
}

}

配置类:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/hello").setAllowedOrigins("*").withSockJS();
    }

}

你使用哪个npm库?仅仅“npm install stomp”就足够了吗? - Johannes
请看一下我上面的回答,刚刚更新了。 - Admir Sabanovic
你是如何在Webpack中映射sockjs-client的? - Daniel Stradowski
我在package.json中只有以下内容:"sockjs": "0.3.4", "stompjs": "2.3.3",其它都已呈现。 - Admir Sabanovic
@critical 如果我失去了与套接字的连接,如何自动重新连接? - Pratap A.K

1
我有一些关于使用Stomp over SockJs的Angular2客户端与Java Spring-Boot后端工作的问题。以下是我为了使其正常工作所做的步骤:
在Angular方面:
this.stompClient.subscribe找不到,因此将“this”绑定到“that”。
constructor() {
    var that = this;
    var socket = new SockJS('http://localhost:8080/portfolio');
    this.stompClient = Stomp.over(socket);
    this.stompClient.connect("guest", "guest", function(frame) {
        console.log('Connected: ' + frame);
        that.stompClient.subscribe('http://localhost:8080/topic/greeting', function(greeting) {
            console.log("from from", greeting);
        });
    }, function (err) {
        console.log('err', err);
    });
}

在Java服务器端:
您的控制器需要一个注释,说明返回值的位置,如下所示:
@MessageMapping("/greeting")
@SendTo("/topic/greetings")
public String handle(String greeting) {
    return "[" + "greeting" + ": " + greeting;
}

根据您的消息代理。
希望这有点帮助。

如果我失去了与套接字的连接,如何自动重新连接? - Pratap A.K
@Lanou非常感谢,它解决了我的问题! - LINGS

0
你已经将 'handle()' 方法的值发送给订阅者,可以使用以下两种方式: 1. 使用 `simpMessagingTemplate.convertAndSend(, );` 方法进行发送, 例如: `simpMessagingTemplate.convertAndSend("/topic/chats", message.getMessage());` 2. 在处理程序方法上面添加 `@SendTo("destination url")` 注解, 例如: `@SendTo("/topic/message")`

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接