如何在 Spring MVC 中正确配置 Stomp 和 SockJS 端点?
How to properly configure Stomp and SockJS endpoint in Spring MVC?
此 is/may 与以下项重复:
。
我正在实施通知系统。并希望在用户登录时初始化套接字连接,并向他显示他的通知,以及是否发生某些事件。
我的代码片段如下。
websocket.js :
var stompClient = null;
function connect( temp ) {
alert(temp);
//var socket = new SockJS("/websock");
//var socket = new SockJS("/websock"+temp);
var socket = new SockJS(context_path+"/websock"+temp);
//context_path == "/SupportCenter"
stompClient = Stomp.over(socket);
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
}, function( error ) {
alert( error );
});
alert();
getNotifications();
}
function getNotifications() {
stompClient.send("/app/hello", {}, "Hiiiiii");
}
WebSocketConfig.java :
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
/* (non-Javadoc)
* @see org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer#registerStompEndpoints(org.springframework.web.socket.config.annotation.StompEndpointRegistry)
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/websock").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// TODO Auto-generated method stub
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
}
WebSocketController.java :
@Controller
public class WebSocketController {
@MessageMapping(value="/hello")
@SendTo("/topic/notifications")
public Notify hello() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Notify notify = new Notify();
notify.setMessage("Hello World !!!");
return notify;
}
}
一些代码 Hom.jsp :
<script type="text/javascript" src="<c:url value="/resources/js/sockjs.min.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/js/stomp.min.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/js/websocket.js"/>"></script>
<script type="text/javascript">
$(document).ready(function() {
//...
connect( '${nsec}');
});
为什么 Firefox 控制台 在 网络选项卡 中给出 XML Parsing Error: no root element found Location:
状态代码是 200 OK
。
控制台选项卡
网络选项卡
最初发布到 this question。
这是因为stompClient.connect()
方法是异步的。我不会暂停执行,直到建立连接。当您在 alert()
之后立即调用 getNotifications()
时,很可能尚未建立连接(如果 alert()
需要足够的时间进行连接,则可能会建立连接)。
您应该在 stompClient.connect()
回调中调用 getNotifications()
(就像您对 stompClient.subscribe()
所做的那样)以确保在它被调用时建立连接。
例如:
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
getNotifications();
}, function( error ) {
alert( error );
});
除此之外,您可以考虑在 java 代码中使用 @SubscribeMapping
注释来摆脱来自 JavaScript 的显式消息,从而从服务器获取初始消息。这样,服务器会在订阅建立后立即发送初始消息。
例如:
@MessageMapping(value="/hello")
@SubscribeMapping("/notifications")
@SendTo("/topic/notifications")
public Notify hello() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Notify notify = new Notify();
notify.setMessage("Hello World !!!");
return notify;
}
然后客户端代码如下所示:
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
}, function( error ) {
alert( error );
});
此 is/may 与以下项重复:
我正在实施通知系统。并希望在用户登录时初始化套接字连接,并向他显示他的通知,以及是否发生某些事件。
我的代码片段如下。
websocket.js :
var stompClient = null;
function connect( temp ) {
alert(temp);
//var socket = new SockJS("/websock");
//var socket = new SockJS("/websock"+temp);
var socket = new SockJS(context_path+"/websock"+temp);
//context_path == "/SupportCenter"
stompClient = Stomp.over(socket);
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
}, function( error ) {
alert( error );
});
alert();
getNotifications();
}
function getNotifications() {
stompClient.send("/app/hello", {}, "Hiiiiii");
}
WebSocketConfig.java :
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
/* (non-Javadoc)
* @see org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer#registerStompEndpoints(org.springframework.web.socket.config.annotation.StompEndpointRegistry)
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/websock").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// TODO Auto-generated method stub
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
}
WebSocketController.java :
@Controller
public class WebSocketController {
@MessageMapping(value="/hello")
@SendTo("/topic/notifications")
public Notify hello() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Notify notify = new Notify();
notify.setMessage("Hello World !!!");
return notify;
}
}
一些代码 Hom.jsp :
<script type="text/javascript" src="<c:url value="/resources/js/sockjs.min.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/js/stomp.min.js"/>"></script>
<script type="text/javascript" src="<c:url value="/resources/js/websocket.js"/>"></script>
<script type="text/javascript">
$(document).ready(function() {
//...
connect( '${nsec}');
});
为什么 Firefox 控制台 在 网络选项卡 中给出 XML Parsing Error: no root element found Location:
状态代码是 200 OK
。
控制台选项卡
网络选项卡
最初发布到 this question。
这是因为stompClient.connect()
方法是异步的。我不会暂停执行,直到建立连接。当您在 alert()
之后立即调用 getNotifications()
时,很可能尚未建立连接(如果 alert()
需要足够的时间进行连接,则可能会建立连接)。
您应该在 stompClient.connect()
回调中调用 getNotifications()
(就像您对 stompClient.subscribe()
所做的那样)以确保在它被调用时建立连接。
例如:
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
getNotifications();
}, function( error ) {
alert( error );
});
除此之外,您可以考虑在 java 代码中使用 @SubscribeMapping
注释来摆脱来自 JavaScript 的显式消息,从而从服务器获取初始消息。这样,服务器会在订阅建立后立即发送初始消息。
例如:
@MessageMapping(value="/hello")
@SubscribeMapping("/notifications")
@SendTo("/topic/notifications")
public Notify hello() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Notify notify = new Notify();
notify.setMessage("Hello World !!!");
return notify;
}
然后客户端代码如下所示:
stompClient.connect({}, function( frame ){
console.log( "Connected :- "+frame );
stompClient.subscribe("/topic/notifications", function( notifications ) {
alert( notifications );
});
}, function( error ) {
alert( error );
});