Spring+stomp+webSocket+SockJS簡単なブロードキャストメッセージと個人メッセージの購読を実現
個人初のCSDNブログでは、自分のIT成長過程を記録しています.
WebSocketに触れるのは、プロジェクトに画像レポートクラスのモニタリングページがあるため、データはページロード後ajaxバックグラウンドで取得してページに表示され、モニタリングデータはリアルタイムで変化し、データの時効性を体現する必要があるため、webSocketを採用してクライアントとサービス側の長接続通信を実現し、クライアントがデータの取得を繰り返し要求することを避ける.実装の構想は,タイミングタスクによって定期的に最新データを取得し,webSocketを介してサービス側からブロードキャストし,クライアントがこのブロードキャストメッセージを傍受し,最新データを展示することである.余計なことを言わない.1.まずこれはssmプロジェクトです.スプリング入りのwebSocketパッケージは、4.0以上のパッケージでなければなりませんが、ここでは4.1を使いました.1: spring-messaging-4.1.1.RELEASE.jar spring-websocket-4.1.1.RELEASE.jar 2. web.xmlのfilterとservletには注釈で定義されたwebSocketの構成クラス
ここで、StompMessageHandshakeHandlerクラスコードは次のとおりです.
WebSocketHandshakeInterceptorクラス:
WebSocketHandshakeHandlerクラス:
メッセージエンティティクラスをカスタマイズし、メッセージをカプセル化します.
WebSocketメッセージ送信のツールクラス
それからspringタイミングタスクを構成して、タイミング実行の方法の中でメッセージの追加を行って、参照コード
フロントインタフェースは、まず2つのjsファイルsockjsを導入する.min.jsとstomp.min.js
具体的なページは以下の通りです.
jsメソッドのsendNameは、サービス側のメッセージに対応するクラスに送信されます.
これで終わりです.
WebSocketに触れるのは、プロジェクトに画像レポートクラスのモニタリングページがあるため、データはページロード後ajaxバックグラウンドで取得してページに表示され、モニタリングデータはリアルタイムで変化し、データの時効性を体現する必要があるため、webSocketを採用してクライアントとサービス側の長接続通信を実現し、クライアントがデータの取得を繰り返し要求することを避ける.実装の構想は,タイミングタスクによって定期的に最新データを取得し,webSocketを介してサービス側からブロードキャストし,クライアントがこのブロードキャストメッセージを傍受し,最新データを展示することである.余計なことを言わない.1.まずこれはssmプロジェクトです.スプリング入りのwebSocketパッケージは、4.0以上のパッケージでなければなりませんが、ここでは4.1を使いました.1: spring-messaging-4.1.1.RELEASE.jar spring-websocket-4.1.1.RELEASE.jar 2. web.xmlのfilterとservletには
true
の構成が必要です.3.springmvcのプロファイルに導入されたwebSocketプロファイルを構成します.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd">
<bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean">
<property name="maxTextMessageBufferSize" value="8192"/>
<property name="maxBinaryMessageBufferSize" value="8192"/>
<property name="maxSessionIdleTimeout" value="900000"/>
<property name="asyncSendTimeout" value="5000"/>
bean>
<bean id="webSocketMessageUtil" class="com.lancy.webSocket.common.WebSocketMessageUtil"/>
beans>
package com.lancy.webSocket.action;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import com.lancy.webSocket.handler.StompMessageHandshakeHandler;
import com.lancy.webSocket.handler.WebSocketHandshakeInterceptor;
@EnableWebSocketMessageBroker
@Controller
public class WebSocketMessageAction extends AbstractWebSocketMessageBrokerConfigurer{
/**
* "/webSocket" STOMP , ,
* , , ,
* url="/applicationName/webSocket" STOMP server 。 url;
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// websocket, ws://host:port/ /webSocket
registry.addEndpoint("/webSocket")
.setHandshakeHandler(new StompMessageHandshakeHandler())
.addInterceptors(new WebSocketHandshakeInterceptor())
.withSockJS();// SockJS
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic","/user");// topic user
registry.setApplicationDestinationPrefixes("/ws");// "/ws"
registry.setUserDestinationPrefix("/user");// , "/user"
}
}
ここで、StompMessageHandshakeHandlerクラスコードは次のとおりです.
package com.lancy.webSocket.handler;
import java.security.Principal;
import java.util.Map;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
/**
* session、cookie , ?
* 。
*
*/
public class StompMessageHandshakeHandler extends DefaultHandshakeHandler{
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
Map attributes) {
return super.determineUser(request, wsHandler, attributes);
}
}
WebSocketHandshakeInterceptorクラス:
package com.lancy.webSocket.handler;
import java.util.Map;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
/**
* , ,
*
*/
public class WebSocketHandshakeInterceptor extends HttpSessionHandshakeInterceptor{
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
super.afterHandshake(request, response, wsHandler, ex);
}
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map attributes) throws Exception {
return super.beforeHandshake(request, response, wsHandler, attributes);
}
}
WebSocketHandshakeHandlerクラス:
package com.lancy.webSocket.handler;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
/**
* WebSocket
* @ClassName: WebSocketHandshakeHandler.java
* @Description: WebSocket
*/
public class WebSocketHandshakeHandler extends TextWebSocketHandler {
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
super.afterConnectionClosed(session, status);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
super.afterConnectionEstablished(session);
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage> message) throws Exception {
super.handleMessage(session, message);
}
}
メッセージエンティティクラスをカスタマイズし、メッセージをカプセル化します.
package com.lancy.webSocket.common;
/**
*
*
*/
public class WebSocketMessage {
/**
* , :/topic/* ,* , monitor, :/topic/monitor
* , :/*,* , message, :/user/{ ID}/message
*/
//
private String distination;
private Object data;//
private String userId;// ,
public String getDistination() {
return distination;
}
public void setDistination(String distination) {
this.distination = distination;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
WebSocketメッセージ送信のツールクラス
package com.lancy.webSocket.common;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import com.lancy.myBatis.common.StringUtils;
/**
* , 。
*
*/
public class WebSocketMessageUtil implements Runnable{
static Logger log = Logger.getLogger(WebSocketMessageUtil.class);
private static SimpMessagingTemplate messageingTemplate;
private static BlockingQueue wsQueue = new LinkedBlockingDeque<>();
public WebSocketMessageUtil() {
new Thread(this).start();
}
@Autowired
public void setTemplate(SimpMessagingTemplate t){
WebSocketMessageUtil.messageingTemplate = t;
}
public static void addMessage(WebSocketMessage msg){
try{
wsQueue.put(msg);
}catch(InterruptedException e){
log.error(" ");
}
}
public static void sendMessage(WebSocketMessage msg){
if(StringUtils.isBlank(msg.getUserId())){
messageingTemplate.convertAndSend(msg.getDistination(),msg);
}else{
messageingTemplate.convertAndSendToUser(msg.getUserId(), msg.getDistination(), msg);
}
}
@Override
public void run() {
log.info(">>>>>>> , 。");
while (true) {
try {
WebSocketMessage msg = wsQueue.take();
if(msg!=null){
WebSocketMessageUtil.sendMessage(msg);
}
} catch (Exception ex) {}
}
}
}
それからspringタイミングタスクを構成して、タイミング実行の方法の中でメッセージの追加を行って、参照コード
public void testWebSocket() {
WebSocketMessage msg = new WebSocketMessage();
msg.setDistination("/topic/lancy/testWebSocket/new");
msg.setData("test....");
WebSocketMessageUtil.addMessage(msg);
}
フロントインタフェースは、まず2つのjsファイルsockjsを導入する.min.jsとstomp.min.js
<script type="text/javascript" src="${ctx}/js/socket/sockjs.min.js">script>
<script type="text/javascript" src="${ctx}/js/socket/stomp.min.js">script>
具体的なページは以下の通りです.
"java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
"c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="ctx" value="${pageContext.request.contextPath}" />
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
<link rel="stylesheet" type="text/css" href="${ctx}/css/default.css" />
<link rel="stylesheet" type="text/css" href="${ctx}/js/easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="${ctx}/js/easyui/themes/icon.css">
<link rel="stylesheet" type="text/css" href="${ctx}/js/easyui/demo/demo.css">
<script type="text/javascript" src="${ctx}/js/jquery.min.js">script>
<script type="text/javascript" src="${ctx}/js/socket/sockjs.min.js">script>
<script type="text/javascript" src="${ctx}/js/socket/stomp.min.js">script>
<script type="text/javascript" src="${ctx}/js/app_common.js">script>
<script type="text/javascript" src="${ctx}/js/easyui/jquery.easyui.min.js">script>
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
document.getElementById('response').innerHTML = '';
}
function connect() {
var socket = new SockJS('/myBookstore/webSocket');// ,
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
//
stompClient.subscribe('/topic/lancy/testWebSocket/new', function(greeting){
showGreeting(greeting.body);
});
//
stompClient.subscribe('/user/1/testUser', function(greeting){
showGreeting(greeting.body);
});
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
setConnected(false);
console.log("Disconnected");
}
}
//
function sendName() {
var name = document.getElementById('name').value;
stompClient.send("/ws/webSocket/testWithServer", {'name': 'xiao','syn':'wang'}, JSON.stringify({'message': name }));
}
function showGreeting(message) {
var response = document.getElementById('response');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
response.appendChild(p);
}
script>
head>
<body class="easyui-layout">
<div>
<div>
<button id="connect" onclick="connect();">Connectbutton>
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnectbutton>
div>
<div id="conversationDiv">
<label>What is your name?label><input type="text" id="name" />
<button id="sendName" onclick="sendName();">Send allbutton>
<p id="response">p>
div>
div>
body>
html>
jsメソッドのsendNameは、サービス側のメッセージに対応するクラスに送信されます.
package com.lancy.webSocket.action;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
@Controller
public class WebSocketTestAction {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/webSocket/testWithServer")
// stompClient.send("/ws/webSocket/testWithServer",
//{'name': 'xiao','syn':'wang'}, JSON.stringify({'message': name }));
public String send(String message,@Header("name")String name,
@Headers Map headers){
System.out.println(message);
System.out.println(name);
System.out.println(headers);
simpMessagingTemplate.convertAndSend("/user/1/testUser"," ");
return "";
}
}
これで終わりです.