Websocketが単独チャットを実現

44434 ワード

1.Websocket紹介
インターネットの発展に伴い、従来のHTTPプロトコルはWebアプリケーションの複雑なニーズを満たすことが難しくなっている.近年、HTML 5の誕生に伴い、WebSocketプロトコルが提案され、ブラウザとサーバの全二重通信を実現し、ブラウザとサービス側の通信機能を拡張し、サービス側もクライアントにデータを積極的に送信できるようになった.従来のHTTPプロトコルは無状態であり、リクエスト(request)のたびにクライアント(ブラウザなど)がアクティブに開始し、サービス側が処理した後にresponse結果を返すが、サービス側がクライアントにデータをアクティブに送信することは難しいことを知っている.このようなクライアントはアクティブ側であり、サービス側がパッシブ側である従来のWebモードは、情報の変化が頻繁ではないWebアプリケーションにとって面倒が小さく、リアルタイム情報に関するWebアプリケーションにとっては、インスタント通信、リアルタイムデータ、サブスクリプションプッシュなどの機能を有するアプリケーションなど、大きな不便をもたらしている.WebSocket仕様が提案される前に、開発者はこれらのリアルタイム性の強い機能を実現するために、トレードオフの解決方法であるポーリング(polling)をよく使用していました.実は後者も本質的にポーリングであり、改善されたにすぎない.ポーリングは、リアルタイムWebアプリケーションを実装する最も原始的なソリューションです.ポーリング技術は、クライアントが設定された時間間隔で周期的にサービス側に要求を送信し、新しいデータ変更があるかどうかを頻繁に照会することを要求する.明らかに、この方法は、不要なリクエストが多すぎて、トラフィックとサーバリソースを浪費します. . この技術はすべて要求-応答モードに基づいており、本当の意味でのリアルタイム技術ではない.それらの要求,応答のたびに,一定のトラフィックが同じヘッダ情報に浪費され,開発の複雑さも大きい.HTML 5が発売したWebSocketに伴い、Webのリアルタイム通信を実現し、B/SモードにC/Sモードのリアルタイム通信能力を備えた.WebSocketのワークフローは、ブラウザがJavaScriptを介してWebSocket接続の確立をサービス側に要求し、WebSocket接続の確立に成功すると、クライアントとサービス側はTCP接続を通じてデータを転送することができる.WebSocket接続は本質的にTCP接続であり、伝送のたびに重複するヘッダデータを持つ必要がないため、ポーリングやComet技術よりもデータ伝送量が大幅に小さい.ここではWebSocket仕様について詳しく説明しないが,Java WebにおけるWebSocketの実装について主に紹介する.JavaEE 7にはJSR-356:Java API for WebSocket仕様が出ています.多くのWebコンテナ、例えばTomcat、Nginx、JettyなどはWebSocketをサポートしています.Tomcatは7.0.2からWebSocketをサポートし、7.0.47からJSR-356をサポートし、次のDemoコードもTomcat 7に配備する必要がある.0.47以上のバージョンでのみ実行できます.
チャットの実装:最初のステップ:
2.1.maven   
<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-messaging</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-websocket</artifactId>
			<version>${spring.version}</version>
		</dependency>

ステップ2:
2.2.    
  websocket    
<context:component-scan base-package="cn.itsource.websocket" />

ステップ3:
メッセージ処理クラスの作成
package cn.itsource.websocket;

import cn.itsource.Util.JsonUtil;
import cn.itsource.model.Chat;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

//     
public class MyHandler extends TextWebSocketHandler {

    //       
    public static final Map<String, WebSocketSession> userSocketSessionMap = new HashMap<String, WebSocketSession>();
    //            
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {System.err.println("      ");
        String str = session.getUri().toString();
        String str1=str.substring(0, str.indexOf("="));
        String str2=str.substring(str1.length()+1, str.length());
        System.err.println("  "+str2);//           id
        userSocketSessionMap.put(str2,session);//   map   
    }

 @Override
    public void handleTextMessage(WebSocketSession session,TextMessage message) {
        try {    
                sendMessagesToone(message);   
        } catch (Exception e) {
            e.printStackTrace();
        }      
    }
 
    //        ,    ,       websocket session remove ,            ,         
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus)  {
        try {
            if(session.isOpen()){
                session.close();
            }
            userSocketSessionMap.remove(session.getId());
            System.out.println("    ");
        }catch (Exception e){
            System.out.println("       ");
        }
    }    
}


構成クラスを作成するには、次の手順に従います.
package cn.itsource.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    //        
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

        registry.addHandler(myHandler(), "/myHandler").setAllowedOrigins("*");
    }
    //   
    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler();
    }

}

リンクできるかどうかをテストします.
  var url="ws://"+this.ip+"/myHandler?uid="+this.id;//      id
   websocket=new WebSocket(url);
      websocket.onopen=function () {
          //alert("    ")
        console.log("    ")
    }

フロントからバックグラウンドにメッセージを送信:
私たちが実現しなければならないのは単独チャットなので、誰があなたとチャットしているのかを区別しなければなりません.だから、私たちはメッセージを送信するときにあなたが選択したユーザーのidをバックグラウンドに持ち込んでthisを区別します.uid
//    
chatxx:function () {
                var json={"id":this.uid,"name":this.username,"message":this.text,"tid":this.tid,"groupchat":this.Groupchat}
                var jsonstr=JSON.stringify(json)
				console.log("  de  "+jsonstr)
				this.data.push(json)
                //alert("  ")
                this.websocket.send(jsonstr)
				this.text='';

            }

フロントからバックグラウンドに渡される値はjson文字列なので、逆シーケンス化して文字列をクラスに変換する必要があります.
まず、フロントから送信されたメッセージに対応するクラスを作成します.
package cn.itsource.model;

public class Chat {
    private Long id;
    private String name;
    private String message;
    private Long tid;
    private String groupchat;

    public String getGroupchat() {
        return groupchat;
    }

    public void setGroupchat(String groupchat) {
        this.groupchat = groupchat;
    }

    public Long getTid() {
        return tid;
    }

    public void setTid(Long tid) {
        this.tid = tid;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return "Chat{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", message='" + message + '\'' +
                ", tid=" + tid +
                ", groupchat='" + groupchat + '\'' +
                '}';
    }
}

変換を実現するための共通の方法を書きます.
package cn.itsource.Util;

import cn.itsource.model.Chat;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class JsonUtil {
    public static Chat jsontf(String jsonstr){
        ObjectMapper objectMapper = new ObjectMapper();
        Chat read=null;
        try {
            read= objectMapper.readValue(jsonstr, Chat.class);
            return read;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return read;
    }
}


メッセージ処理クラスにメッセージを受信する方法を書く
          //    
    public void sendMessagesToone(TextMessage message){
            //      
            Chat jsontf1 = JsonUtil.jsontf(message.getPayload());
            String id = jsontf1.getId().toString();//           id
            //   id  map    value
        WebSocketSession webSocketSession = userSocketSessionMap.get(id);
        try {
            System.err.println("   id"+id);
                //isOpen()     
            if(webSocketSession.isOpen()){
                    webSocketSession.sendMessage(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

    }

上のhandleTextMessageでsendMessagesTooneメソッドを呼び出し、バックグラウンドで配布されたメッセージを受信します.
 //    
            this.websocket.onmessage=(e)=> {
                console.log(e.data)
                let rep = JSON.parse(e.data);//        json
                this.cid=rep.id
                this.data.push(rep)//         

            }

            //     
            this.websocket.onclose = function (event) {
                console.log('Info: connection closed.');
            }

ページ面にdataの中のデータをループすればいいです.
<ul v-show="schat" class="content" id="chatbox2" v-for="item in data"  >
					<!--<li class="other" v-if="'{{item.id}}'==='{{uid}}'" >-->
				<li class="other" v-if="item.id===id&&uid===item.tid">
					<img src="/static/images/head/15.jpg" title="   " >
					<span>{{item.message}}</span>
				</li>

				<li class="me" v-else-if="item.id!=id&&uid===item.id"><img src="/static/images/head/15.jpg" title="   " >
					<span>{{item.message}}</span>	
				</li>
			</ul>