SpringBootラーニング-(14)SpringBootでWebSocket接続を確立する(STOMP実装指定されたユーザへのメッセージ送信)
19856 ワード
STOMPインプリメンテーションを使用して、指定されたユーザにメッセージを送信するには、次の手順に従います. pomファイル依存 を追加クライアントユーザエンティティクラス を書く.クライアントチャネルブロックアダプタ を書く websocket stomp の構成書き込み制御層 書き込みクライアント 1.pomファイル依存の追加
2.クライアントユーザーエンティティクラスを書く
クライアント・ユーザー・エンティティ・クラスをカスタマイズし、クライアントからの情報をカプセル化します.これは、クライアントごとに一意の識別を提供することに相当します.
3.書き込みクライアントチャネルブロックアダプタ
ブロック方式でstompに含まれるユーザ情報を取得し、認証されたユーザ情報を現在のアクセサに設定する
4.websocket stompの構成
5.書き込み制御層
コード解析:SimpUserRegistry接続されたクライアント情報を取得するために使用されるuserRegistry.getUsers()はユーザーリストを返します
指定したユーザーへのシミュレーション送信、ブラウザアクセス
接続ユーザー名としてtestを使用し、/user/queue/messageトピックを購読したクライアントは、サーバからアクティブにプッシュされたメッセージを受信します.
convertAndSendToUserのソースコードを表示するには、次の手順に従います.
メッセージを見つけることができますconvertAndSendToUser(「test」,「/queue/message」,new ServerMessage(「サーバアクティブプッシュデータ」)最終的に送信される宛先アドレスは次のとおりです.
ユーザー名に"/"が含まれている場合は"%2 F"に置き換えます.
6.書き込みクライアント
コード分析:クライアントが接続されている場合、ユーザー名を指定する必要があります.
ユーザーは、自分に送信されたメッセージを受信するには、/user/queue/messageトピックを購読する必要があります.
まとめ:
クライアントサブスクリプション:/user/queue/messageサーバプッシュ指定ユーザー:/user/クライアントユーザー名/queue/message
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-websocketartifactId>
dependency>
2.クライアントユーザーエンティティクラスを書く
クライアント・ユーザー・エンティティ・クラスをカスタマイズし、クライアントからの情報をカプセル化します.これは、クライアントごとに一意の識別を提供することに相当します.
package com.ahut.entity;
import java.security.Principal;
/**
*
* @ClassName: User
* @Description:
* @author cheng
* @date 2017 9 29 3:02:54
*/
public final class User implements Principal {
private final String name;
public User(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
3.書き込みクライアントチャネルブロックアダプタ
ブロック方式でstompに含まれるユーザ情報を取得し、認証されたユーザ情報を現在のアクセサに設定する
package com.ahut.websocket;
import java.util.LinkedList;
import java.util.Map;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
import org.springframework.messaging.support.MessageHeaderAccessor;
import com.ahut.entity.User;
/**
*
* @ClassName: UserInterceptor
* @Description:
* @author cheng
* @date 2017 9 29 2:40:12
*/
public class UserInterceptor extends ChannelInterceptorAdapter {
/**
* stomp
*/
@SuppressWarnings("rawtypes")
@Override
public Message> preSend(Message> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
Object raw = message.getHeaders().get(SimpMessageHeaderAccessor.NATIVE_HEADERS);
if (raw instanceof Map) {
Object name = ((Map) raw).get("name");
if (name instanceof LinkedList) {
//
accessor.setUser(new User(((LinkedList) name).get(0).toString()));
}
}
}
return message;
}
}
4.websocket stompの構成
package com.ahut.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
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.ahut.websocket.UserInterceptor;
/**
*
* @ClassName: WebSocketStompConfig
* @Description: springboot websocket stomp
* @author cheng
* @date 2017 9 27 3:45:36
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer {
/**
* stomp
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// socketJs , webSocketServer,
//
// http://localhost:8080/webSocketServer
// WebSocket
registry.addEndpoint("/webSocketServer").setAllowedOrigins("*").withSockJS();
}
/**
*
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// Broker
registry.enableSimpleBroker("/queue", "/topic");
// ( )
registry.setApplicationDestinationPrefixes("/app");
// ( ), , /user/
// registry.setUserDestinationPrefix("/user/");
}
/**
*
*/
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(createUserInterceptor());
}
/**
*
* @Title: createUserInterceptor
* @Description: spring ioc
* @return
*/
@Bean
public UserInterceptor createUserInterceptor() {
return new UserInterceptor();
}
}
5.書き込み制御層
package com.ahut.action;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.user.SimpUser;
import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.ahut.entity.ServerMessage;
/**
*
* @ClassName: WebSocketAction
* @Description: websocket
* @author cheng
* @date 2017 9 27 4:20:58
*/
@Controller
public class WebSocketAction {
private Logger logger = LoggerFactory.getLogger(this.getClass());
//spring
@Autowired
private SimpMessagingTemplate messagingTemplate;
@Autowired
private SimpUserRegistry userRegistry;
@RequestMapping(value = "/templateTest")
public void templateTest() {
logger.info(" :" + userRegistry.getUserCount());
int i = 1;
for (SimpUser user : userRegistry.getUsers()) {
logger.info(" " + i++ + "---" + user);
}
//
messagingTemplate.convertAndSendToUser("test", "/queue/message", new ServerMessage(" "));
}
}
コード解析:SimpUserRegistry接続されたクライアント情報を取得するために使用されるuserRegistry.getUsers()はユーザーリストを返します
指定したユーザーへのシミュレーション送信、ブラウザアクセス
localhost:8080/templateTest
接続ユーザー名としてtestを使用し、/user/queue/messageトピックを購読したクライアントは、サーバからアクティブにプッシュされたメッセージを受信します.
convertAndSendToUserのソースコードを表示するには、次の手順に従います.
@Override
public void convertAndSendToUser(String user, String destination, Object payload, Map headers,
MessagePostProcessor postProcessor) throws MessagingException {
Assert.notNull(user, "User must not be null");
user = StringUtils.replace(user, "/", "%2F");
super.convertAndSend(this.destinationPrefix + user + destination, payload, headers, postProcessor);
}
メッセージを見つけることができますconvertAndSendToUser(「test」,「/queue/message」,new ServerMessage(「サーバアクティブプッシュデータ」)最終的に送信される宛先アドレスは次のとおりです.
/user/test/queue/message
ユーザー名に"/"が含まれている場合は"%2 F"に置き換えます.
6.書き込みクライアント
<html>
<head>
<title>stomptitle>
head>
<body>
Welcome<br/><input id="text" type="text" />
<button onclick="send()"> button>
<button onclick="subscribe3()"> /user/queue/messagebutton>
<hr/>
<div id="message">div>
body>
<script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js">script>
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js">script>
<script type="text/javascript">
// ( )
var socket = new SockJS("http://localhost:8080/webSocketServer");
// STOMP
var stompClient = Stomp.over(socket);
// websocket CONNECT
stompClient.connect(
{
name: 'test' //
},
function connectCallback(frame) {
// ( CONNECTED )
setMessageInnerHTML(" ");
},
function errorCallBack(error) {
// ( ERROR )
setMessageInnerHTML(" ");
}
);
//
function subscribe3() {
stompClient.subscribe('/user/queue/message', function (response) {
var returnData = JSON.parse(response.body);
setMessageInnerHTML("/user/queue/message :" + returnData.responseMessage);
});
}
//
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '
';
}
script>
html>
コード分析:クライアントが接続されている場合、ユーザー名を指定する必要があります.
// websocket CONNECT
stompClient.connect(
{
name: 'test' //
},
function connectCallback(frame) {
// ( CONNECTED )
setMessageInnerHTML(" ");
},
function errorCallBack(error) {
// ( ERROR )
setMessageInnerHTML(" ");
}
);
ユーザーは、自分に送信されたメッセージを受信するには、/user/queue/messageトピックを購読する必要があります.
まとめ:
クライアントサブスクリプション:/user/queue/messageサーバプッシュ指定ユーザー:/user/クライアントユーザー名/queue/message