航海99 Weekly Iで学んだ<実戦プロジェクト編>


Springが提供するwebsocketにはstompというフレームワークがあります.
STOMP : Simple Text Oriented Messaging Protocol
stompはメッセージを効率的に伝送するためのプロトコルであり、基本的にはPUB/SUB構造である.従って、メッセージ送受信処理部の構成を明確に認識し、開発することができる.
  • STOMPプロトコルは、クライアント/サーバ間で送信されるメッセージのタイプ、フォーマット、およびコンテンツを定義するルールである.
  • は、TCPまたはWebSocketのような「双方向ネットワークプロトコルベース」として機能する.
  • ヘッダに値を設定し、ヘッダ値を元に通信時の認証処理を実現することができる.
  • PUB/SUB構造


    pub/subは、情報を提供する主体と消費する主体とを分けて提供する情報伝達方法である.代表的な例を挙げて説明する.
    ポストがあれば、郵便配達人は新聞をポストに送る行為をし、ポストが新聞を配達するのを待つサブスクライバは新聞を出して読む行為をする.この場合、サブスクライバは多数であってもよい.
    すなわち,チャットルームの作成はポスト画像の作成であり,チャットルームに入るとサブスクライバとしてSubscriberとなる.チャットルームで文章を書く行為は、メールボックスに新聞を入れるPublisherになります.

    Message Brocker


    このときMessage Brockerという概念があり、Publisherから送信されたメッセージをSubscriberに送信し、メッセージを受信させる中間ロールを指す.
    クライアントはSEND、SUBSCRIBEコマンド、および「destination」ヘッダーを使用してメールを転送または購読し、メールの内容とターゲットを説明できます.これにより、PUB/SUBメカニズムが可能になり、エージェントを介して接続された他のクライアントにメッセージを送信したり、サーバにメッセージを送信したりして、いくつかの操作を要求することができます.
    SpringがサポートするSTOMPでは、Spring WebソケットアプリケーションがクライアントにSTOMPエージェントとして機能します.この場合、メッセージは、@Controllerメッセージ処理方法またはSubscriberを追跡することによってサブスクリプションユーザにメッセージを伝播する簡単なメモリエージェントにルーティングされる.
    このようにspring環境でSTOMPプロトコルを使用すると、Message AgentはIn Memory Brokerを自動的に使用します.
    stompのフレーム構造
  • コマンド、タイトル、およびボディ構成
  • 命令:CONNECT、SEND、SUBSCRIBE、DISCONNECT...
  • ヘッダーとボディを空白行に分割し、ボディの末尾をNULL文字
  • に設定
    まず、私たちのプロジェクトで作成したリアルタイムの招待通知を書きます.
    まず、websocketのsockjsとstompを使用するにはspring-boot勾配を使用して依存項目を作成する必要があります.

    また,セッションを用いて握手を実現するWebSocketとは異なり,STOMPはbroker自身で握手を行うため,コード作成が非常に簡単である.もちろん自分で见てやってるので初めて接する人にはわかりづらいですが….
    stompを実施するbrokerはこうです.

    まず、EnableWebSocketMessageBroker注釈処理でBrokerを使用する注釈を処理し、WebSocketMessageBroker Configuratorを継承する必要があります.
    では、このインタフェースが持つ2つの方法を使用すれば、設定は終了します.まず、接続のためにフロントはstompが提供する始点(endpoint)に接続しなければならないので、endpointの設定方法が必要です.
    --> .addEndpoint("/カスタム")
    そしてその下のsetHandshackHandlerは、フロントにWebSocket接続がある場合、サーバログを印刷する役割を果たします.もちろん、newUserHandShakeHandler()は自分でカスタマイズする必要があります.
    そしてその下のsetAllowedOriginPatterns(「*」)は、フロントエンドアドレスまたはローカルアドレスを含むことができる.もちろん、星号はすべて含まれているという意味も知っています.妻の心だけど同じ意味のハーモニーでsetalowedOrigins("")もあります.使いやすいものを選べばいいです.
    そしてその下のwithSockjsは少し空っぽかもしれませんが、Sockjsを使いたいなら、この行は終わりです.

    Sockjsを使用する理由は、IE 8、9は依然として多くのインターネットユーザーが使用するブラウザであるが、このバージョンではWebSocketはサポートされていないからである。Springでは、sockjs-clientと併用し、既存の設定に大きな変更がない場合、WebSocket Polyfillの使用と同様の効果が得られます。


    さあ.以上がEndpointメソッドの内容です.
    では、これから下記の郵便配達員、郵便ポスト、購読者について説明します.
    まず、コードにpubと書いてあるところが郵便配達員のurl、subと書いてあるところが郵便ポストのurlです.これを理解するにはまず画像が必要です.

    どこに行ってもこんな絵がこの絵はspring公式サイトにあります.もちろん私はこの絵を見てもっとめまいがします.私の理解する絵は私が描きます.

    私の絵もおかしいかもしれませんが、理解してほしいです.そこまで理解すれば簡単ですが、そこまで理解すれば同じですこのように郵便配達人とポストを決めておけば、今すぐメールマッピングができます.
    @RequiredArgsConstructor
    @Controller
    public class AlarmController {
    
        private final ProjectMemberRepository projectMemberRepository;
        private final MemberRepository memberRepository;
        private final SimpMessageSendingOperations messagingTemplates;
    
        @MessageMapping("/invite")
        public InviteResponseDto inviteProject(@Payload InviteRequestDto requestDto) {
    
            InviteResponseDto inviteResponseDto = new InviteResponseDto();
            // 초대하려는 이메일이 존재하지 않을 때 !!
            System.out.println(requestDto.getReceiverEmail());
            if (!memberRepository.existsByEmail(requestDto.getReceiverEmail())) {
                inviteResponseDto.setMsg("초대하려는 이메일이 존재하지 않습니다.");
                System.out.println(memberRepository.existsByEmail(requestDto.getReceiverEmail()));
                return inviteResponseDto;
            }
            if (Objects.equals(requestDto.getSenderEmail(), requestDto.getReceiverEmail())) {
                inviteResponseDto.setMsg("자기자신은 초대할 수 없습니다.");
                return inviteResponseDto;
            }
            // 초대하려는 이메일이 존재할 때 !!
            Member receiver = memberRepository.findByEmail(requestDto.getReceiverEmail());
            if (projectMemberRepository.existsByMember_IdAndProject_Id(receiver.getId(), requestDto.getProjectId())) {
                inviteResponseDto.setMsg("이미 초대되어 있는 회원입니다.");
                return inviteResponseDto;
            }
            // 프론트에게 전해줄 보내는 자의 Id와 보내고 싶은 사용자 Id를 담아서 전해준다.
            inviteResponseDto.setMsg("초대완료");
            inviteResponseDto.setSenderEmail(requestDto.getSenderEmail());
            inviteResponseDto.setReceiverEmail(requestDto.getReceiverEmail());
            System.out.println(receiver.getId());
    
            messagingTemplates.convertAndSend("/sub/invite/" + receiver.getId(), inviteResponseDto);
    
            return inviteResponseDto;
        }
    }
    初めて@MassageMappingで使用したurlは、私が指定した/pubを隠していると考えられます.だから「/invite」としか書いていません.
    そして最後のSimpMessageSendingOpensのConvertAndSendに私が送りたいメールボックスと送りたいメッセージを書いて終わりました.これを適用すればいいです.そして、もちろん、フロントはこのメールボックスを購読しなければ情報を受け取ることができません.