您的位置:首页 > 编程语言 > Java开发

使用spring websocket 和stomp实现消息功能

2016-07-23 18:49 751 查看

实现一个消息驱动pojo

public class MarcHandler extends AbstractWebSocketHandler{
private Logger LOGGER = LoggerFactory.getLogger(MarcHandler.class);

@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
LOGGER.info("received Message :"+ message.getPayload());
Thread.sleep(2000);
session.sendMessage(new TextMessage("Polo!"));
}

@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
LOGGER.info("session closed!");
}

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
LOGGER.info("session established!");
}
}

配置websocket handler 和js demo

原生websocket配置

<websocket:handlers >
<websocket:mapping path="/marco" handler="marcHandler"/>
<!--<websocket:sockjs/>-->
</websocket:handlers>
js demo:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<title>Home</title>
<spring:url value="/webjars/jquery/2.0.3/jquery.min.js" var="jQueryCore"/>
<script src="${jQueryCore}"></script>
<spring:url value="/webjars/sockjs-client/0.3.4/sockjs.min.js" var="sockJs"/>
<script src="${sockJs}"></script>
</head>
<body>
<button id="stop">Stop</button>

<script style="text/javascript">
$(function () {
var wsUrl = "ws://"+window.location.host+"/japi-rest/marco"
var sock = new WebSocket(wsUrl);

//       var SockJSUrl = "http://"+window.location.host+"/japi-rest/marco"
//       var sock = new SockJS(SockJSUrl);

sock.onopen = function() {
console.log('Opening');
sayMarco();
}

sock.onmessage = function(e) {
console.log('Received message: ', e.data);
$('#output').append('Received "' + e.data + '"<br/>');
setTimeout(function(){sayMarco()}, 2000);
}

sock.onclose = function() {
console.log('Closing');
}

function sayMarco() {
console.log('Sending Marco!');
$('#output').append('Sending "Marco!"<br/>');
sock.send("Marco!");
}

$('#stop').click(function() {sock.close()});
})
</script>

<div id="output"></div>
</body>
</html>
PS: 1)如果打开 <websocket:sockjs/> 会报错:WebSocket connection to 'ws://localhost:8080/japi-rest/marco' failed: Error during WebSocket handshake: Unexpected response code: 200

利用SockJs解决部分浏览器不支持websocket

<websocket:handlers>
<websocket:mapping path="/marco" handler="marcHandler"/>
<websocket:sockjs/>
</websocket:handlers>
JS Demo:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %><html><head><title>Home</title><spring:url value="/webjars/jquery/2.0.3/jquery.min.js" var="jQueryCore"/><script src="${jQueryCore}"></script><spring:url value="/webjars/sockjs-client/0.3.4/sockjs.min.js" var="sockJs"/><script src="${sockJs}"></script></head><body><button id="stop">Stop</button><script style="text/javascript">$(function () {//       var wsUrl = "ws://"+window.location.host+"/japi-rest/marco"//       var sock = new WebSocket(wsUrl);var SockJSUrl = "http://"+window.location.host+"/japi-rest/marco"var sock = new SockJS(SockJSUrl);sock.onopen = function() {console.log('Opening');sayMarco();}sock.onmessage = function(e) {console.log('Received message: ', e.data);$('#output').append('Received "' + e.data + '"<br/>');setTimeout(function(){sayMarco()}, 2000);}sock.onclose = function() {console.log('Closing');}function sayMarco() {console.log('Sending Marco!');$('#output').append('Sending "Marco!"<br/>');sock.send("Marco!");}$('#stop').click(function() {sock.close()});})</script><div id="output"></div></body></html>

使用STOMP 消息

如果直接用websocket 编写web应用 类似与直接使用tcp套接字, stomp 相当于基于websocket之上的一个高层级的线路协议), xml配置:
<!--   stomp and message broker config  start --><websocket:message-broker application-destination-prefix="/app"><!--   websocket 底层连接地址 --><websocket:stomp-endpoint path="/marcopolo" ><websocket:sockjs/></websocket:stomp-endpoint><websocket:simple-broker prefix="/topic,/queue" /></websocket:message-broker><!--   stomp and message broker config  end-->
编写一个消息处理controller:
@Controllerpublic class MarcoController {private final static Logger logger = LoggerFactory.getLogger(MarcoController.class);@MessageMapping("/marco")public Shout handleShout(Shout incoming) {logger.info("Received message: " + incoming.getMessage());try { Thread.sleep(2000); } catch (InterruptedException e) {}Shout outgoing = new Shout();outgoing.setMessage("Polo!");return outgoing;}}
js 编写测试客户端:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %><html><head><title>Home</title><spring:url value="/webjars/jquery/2.0.3/jquery.min.js" var="jQueryCore"/><script src="${jQueryCore}"></script><spring:url value="/webjars/sockjs-client/0.3.4/sockjs.min.js" var="sockJs"/><script src="${sockJs}"></script><spring:url value="/webjars/stomp-websocket/2.3.4/lib/stomp.min.js" var="stomp"/><script src="${stomp}"></script><spring:url value="/" var="context"/></head><body><button id="stop">Stop</button><script th:inline="javascript">var sock = new SockJS("${context}"+"/marcopolo");var stomp = Stomp.over(sock);stomp.connect('guest', 'guest', function(frame) {console.log('*****  Connected  *****');stomp.subscribe("/topic/marco", handlePolo);sayMarco();});function handleOneTime(message) {console.log('Received: ', message);}function handlePolo(message) {console.log('Received: ', message);$('#output').append("<b>Received: " +JSON.parse(message.body).message + "</b><br/>")if (JSON.parse(message.body).message === 'Polo!') {setTimeout(function(){sayMarco()}, 2000);}}function handleErrors(message) {console.log('RECEIVED ERROR: ', message);$('#output').append("<b>GOT AN ERROR!!!: " +JSON.parse(message.body).message + "</b><br/>")}function sayMarco() {console.log('Sending Marco!');stomp.send("/app/marco", {},JSON.stringify({ 'message': 'Marco!' }));//        stomp.send("/topic/marco", {},//                JSON.stringify({ 'message': 'Marco!' }));$('#output').append("<b>Send: Marco!</b><br/>")}$('#stop').click(function() {sock.close()});</script><div id="output"></div></body></html>
PS:0) stomap 消息道理数据流程图:1)<websocket:stomp-endpoint path="/marcopolo" > 这个配置终端 表明底层的websocket url2)application-destination-prefix="/app" 是 controller处理的path 前缀3) <websocket:simple-broker prefix="/topic,/queue" /> 配置了两个代理的目的地4) @MessageMapping("/marco") 这个注解的方法返回的数据写到哪个代理目的地呢?因为没有配置@SendTo 所以默认写到/topic +"/marco" ,见下图调试:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring websocket