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:
ステップ3:
メッセージ処理クラスの作成
構成クラスを作成するには、次の手順に従います.
リンクできるかどうかをテストします.
フロントからバックグラウンドにメッセージを送信:
私たちが実現しなければならないのは単独チャットなので、誰があなたとチャットしているのかを区別しなければなりません.だから、私たちはメッセージを送信するときにあなたが選択したユーザーのidをバックグラウンドに持ち込んでthisを区別します.uid
フロントからバックグラウンドに渡される値はjson文字列なので、逆シーケンス化して文字列をクラスに変換する必要があります.
まず、フロントから送信されたメッセージに対応するクラスを作成します.
変換を実現するための共通の方法を書きます.
メッセージ処理クラスにメッセージを受信する方法を書く
上のhandleTextMessageでsendMessagesTooneメソッドを呼び出し、バックグラウンドで配布されたメッセージを受信します.
ページ面にdataの中のデータをループすればいいです.
インターネットの発展に伴い、従来の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>