. « Spring Framework» . , , : « Spring», .
でビルスケーラブルなサーバに送信され、イベントを使用して通知のようなFacebookの-とRedisの、私たちは、サーバからクライアントにメッセージを送信するサーバ送信されたイベントを使用していました。また、サーバーとクライアント間の双方向通信テクノロジーであるWebSocketについても言及しました。
この記事では、WebSocketの一般的な使用例の1つを見ていきます。プライベートメッセージングアプリケーションを作成します。
以下のビデオは、私たちがやろうとしていることを示しています。
WebSocketsとSTOMPの概要
WebSocketは、サーバーとクライアント間の双方向通信用のプロトコルです。
WebSocketは、HTTPとは異なり、アプリケーション層プロトコルはトランスポート層プロトコル(TCP)です。最初の接続にはHTTPが使用されますが、接続はWebSocketで使用されるTCP接続に「アップグレード」されます。
WebSocketは、メッセージ形式を定義しない低レベルのプロトコルです。したがって、WebSocket RFCは、メッセージの構造と標準を記述するサブプロトコルを定義します。STOMP over WebSockets(STOMP over WebSockets)を使用します。
プロトコルSTOMP(シンプル/テキスト指向のメッセージプロトコルのストリーミング)は、サーバーとクライアント間のメッセージ交換のルールを定義します。
STOMPはHTTPに似ており、次のコマンドを使用してTCP上で実行されます。
- 接続する
- 申し込む
- 購読解除
- 送信
- ベギン
- コミット
- ACK
STOMPコマンドの仕様と完全なリストはここにあります。
建築
- 認証サービスは、ユーザーを認証し、管理を担当。ここでは車輪を作り直さず、JWTの認証サービスとSpringBootを使用したソーシャル認証を使用します。
- チャットサービスがある、のWebSocketを設定STOMPメッセージを処理し、ユーザーメッセージを格納し、処理するための責任を負います。
- チャットクライアントが接続して、チャットを購読するSTOMPクライアントを使用していますReactJSアプリケーションです。また、ここにユーザーインターフェイスがあります。
メッセージモデル
最初に考えるのはメッセージモデルです。ChatMessageは次のようになります。
public class ChatMessage {
@Id
private String id;
private String chatId;
private String senderId;
private String recipientId;
private String senderName;
private String recipientName;
private String content;
private Date timestamp;
private MessageStatus status;
}
クラスは
ChatMessage非常に単純で、送信者と受信者を識別するために必要なフィールドがあります。
また、メッセージがクライアントに配信されたかどうかを示すステータスフィールドもあります。
public enum MessageStatus {
RECEIVED, DELIVERED
}
サーバーがチャットからメッセージを受信すると、メッセージを受信者に直接送信するのではなく、新しいメッセージが受信されたことをクライアントに通知する通知(ChatNotification)を送信します。その後、クライアント自身が新しいメッセージを受信できます。クライアントがメッセージを受信するとすぐに、メッセージはDELIVEREDとしてマークされます。
通知は次のようになります。
public class ChatNotification {
private String id;
private String senderId;
private String senderName;
}
通知には、以下に示すように、クライアントが新しいメッセージまたは新しいメッセージの数に関する情報を表示できるように、新しいメッセージのIDと送信者に関する情報が含まれています。
SpringでのWebSocketとSTOMPの構成
最初のステップは、STOMPエンドポイントとメッセージブローカーを構成することです。
これを行うには、注釈とを使用してWebSocketConfigクラスを作成
@Configurationし@EnableWebSocketMessageBrokerます。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker( "/user");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/ws")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setObjectMapper(new ObjectMapper());
converter.setContentTypeResolver(resolver);
messageConverters.add(converter);
return false;
}
}
最初の方法は、メッセージ
/userを送受信するために、単一のプレフィックス付きアドレスを持つ単純なメモリ内メッセージブローカーを構成します。プレフィックス付きアドレス/appは、注釈付きの方法@MessageMappingで処理されるメッセージ用です。これについては、次のセクションで説明します。
2番目の方法は、STOMPエンドポイントを登録します
/ws。このエンドポイントは、クライアントがSTOMPサーバーに接続するために使用されます。これには、WebSocketが使用できない場合に使用されるフォールバックSockJSも含まれます。
最後のメソッドは、SpringがメッセージをJSONとの間で変換するために使用するJSONコンバーターを構成します。
メッセージを処理するためのコントローラー
このセクションでは、リクエストを処理するコントローラーを作成します。ユーザーからメッセージを受信し、受信者に送信します。
@Controller
public class ChatController {
@Autowired private SimpMessagingTemplate messagingTemplate;
@Autowired private ChatMessageService chatMessageService;
@Autowired private ChatRoomService chatRoomService;
@MessageMapping("/chat")
public void processMessage(@Payload ChatMessage chatMessage) {
var chatId = chatRoomService
.getChatId(chatMessage.getSenderId(), chatMessage.getRecipientId(), true);
chatMessage.setChatId(chatId.get());
ChatMessage saved = chatMessageService.save(chatMessage);
messagingTemplate.convertAndSendToUser(
chatMessage.getRecipientId(),"/queue/messages",
new ChatNotification(
saved.getId(),
saved.getSenderId(),
saved.getSenderName()));
}
}
注釈
@MessageMappingを使用して、メッセージがに送信される/app/chatときにメソッドが呼び出されるように構成しますprocessMessage。以前に構成されたアプリケーションプレフィックスがマッピングに追加されることに注意してください/app。
このメソッドは、メッセージをMongoDBに格納して
convertAndSendToUserから、メソッドを呼び出して通知をターゲットに送信します。プレフィックスとアドレス
を
convertAndSendToUser追加する方法。最終的なアドレスは次のようになります。/userrecipientId/queue/messages
/user/{recipientId}/queue/messages
このアドレスのすべてのサブスクライバー(この場合は1つ)がメッセージを受信します。
chatIdの生成
2人のユーザー間の会話ごとに、チャットルームを作成し、それを識別するための一意のチャットルームを生成し
chatIdます。ChatRoom
クラスは次のようになります。
public class ChatRoom {
private String id;
private String chatId;
private String senderId;
private String recipientId;
}
値
chatIdは連結と同じsenderId_recipientIdです。会話ごとに、同じ2つのエンティティを保持しchatIdます。1つは送信者と受信者の間、もう1つは受信者と送信者の間で、両方のユーザーが同じを受信するようにしchatIdます。
JavaScriptクライアント
このセクションでは、WebSocket / STOMPサーバーとの間でメッセージを送受信するJavaScriptクライアントを作成します。
SockJSとStomp.jsを使用して、STOMP overWebSocketを使用してサーバーと通信します。
const connect = () => {
const Stomp = require("stompjs");
var SockJS = require("sockjs-client");
SockJS = new SockJS("http://localhost:8080/ws");
stompClient = Stomp.over(SockJS);
stompClient.connect({}, onConnected, onError);
};
このメソッドは、サーバーが接続を待機している
connect()への接続を確立し、接続が成功したときに呼び出され、サーバーへの接続中にエラーが発生した場合に呼び出される/wsコールバック関数も定義します。onConnectedonError
const onConnected = () => {
console.log("connected");
stompClient.subscribe(
"/user/" + currentUser.id + "/queue/messages",
onMessageReceived
);
};
このメソッド
onConnected()は特定のアドレスにサブスクライブし、そこで送信されたすべてのメッセージを受信します。
const sendMessage = (msg) => {
if (msg.trim() !== "") {
const message = {
senderId: currentUser.id,
recipientId: activeContact.id,
senderName: currentUser.name,
recipientName: activeContact.name,
content: msg,
timestamp: new Date(),
};
stompClient.send("/app/chat", {}, JSON.stringify(message));
}
};
メソッドの最後に、コントローラーで指定され
sendMessage()たアドレスにメッセージが送信/app/chatされます。
結論
この記事では、SpringBootとSTOMPoverWebSocketを使用してチャットを作成するためのすべての重要なポイントについて説明しました。
また、SockJsおよびStomp.jsライブラリを使用してJavaScriptクライアントを構築しました。
サンプルのソースコードはここにあります。
コースの詳細をご覧ください。