欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot整合websocket實(shí)現(xiàn)即時通信聊天

 更新時間:2022年05月10日 14:25:18   作者:BreezAm  
這篇文章主要介紹了SpringBoot整合websocket實(shí)現(xiàn)即時通信聊天,實(shí)時通信是一個實(shí)時通信系統(tǒng),允許兩人或多人使用網(wǎng)絡(luò)實(shí)時的傳遞文字消息、文件、語音與視頻交流,需要的朋友可以參考下

一、技術(shù)介紹

線上演示地址:http://chat.breez.work

實(shí)時通信(Instant Messaging,簡稱IM)是一個實(shí)時通信系統(tǒng),允許兩人或多人使用網(wǎng)絡(luò)實(shí)時的傳遞文字消息、文件、語音視頻交流。[4]

場景再現(xiàn):

  • 微信聊天
  • QQ聊天
  • 網(wǎng)站在線客服 

1.1 客戶端WebSocket

WebSocket 對象提供了用于創(chuàng)建和管理 WebSocket 連接,以及可以通過該連接發(fā)送接收數(shù)據(jù)的 API。使用 WebSocket() 構(gòu)造函數(shù)來構(gòu)造一個 WebSocket。[1]

構(gòu)造函數(shù)如下所示:

const webSocket = WebSocket(url[, protocols])

例子如下:

const webSocket = new WebSocket("ws://42.193.120.86:3688/ws/小明/翠花")

1.1.1 函數(shù)

1、 webSocket.send()
該函數(shù)用于向服務(wù)端發(fā)送一條消息,例子如下:

webSocket.send("Hello server!");

2、 webSocket.close()
該函數(shù)用于關(guān)閉客戶端與服務(wù)端的連接,例子如下:

webSocket.close();

1.1.2 事件

1、webSocket.onopen
該事件用于監(jiān)聽客戶端與服務(wù)端的連接狀態(tài),如果客戶端與服務(wù)端連接成功則該事件觸發(fā),例子如下:

webSocket.onopen = function(event) {
  console.log("連接已經(jīng)建立,可以進(jìn)行通信");
};

2、webSocket.onclose
如果服務(wù)端與客戶端連接斷開,那么此事件出發(fā),例子如下:

webSocket.onclose = function(event) {
  console.log("連接已經(jīng)關(guān)閉");
};

3、webSocket: message event
該事件用于監(jiān)聽服務(wù)端向客戶端發(fā)送的消息,例子如下:

webSocket.addEventListener('message', function (event) {
    console.log('來自服務(wù)端的消息:', event.data);
});

4、webSocket:error event
如果客戶端與服務(wù)端發(fā)生錯誤時,那么此事件將會觸發(fā),例子如下:

webSocket.addEventListener('error', function (event) {
  console.log('連接出現(xiàn)錯誤', event);
});

1.2 服務(wù)端WebSocket

@ServerEndpoint用于聲明一個socket服務(wù),例子如下:

@ServerEndpoint(value = "/ws/{userId}/{targetId}")

幾個重要的方法注解:

  • @OnOpen 打開連接
  • @OnClose 監(jiān)聽關(guān)閉
  • @OnMessage 發(fā)送消息
  • @OnError 監(jiān)聽錯誤 

二、實(shí)戰(zhàn) 

2.1、服務(wù)端

2.1.1引入maven依賴

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2.1.2 編寫配置類

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

2.1.3 編寫WebSocketService服務(wù)類

下面的userId代表發(fā)送者的ID號,target代表發(fā)送目標(biāo)ID號。

@Component
@ServerEndpoint(value = "/ws/{userId}/{target}")
public class WebSocketService {
    //用于保存連接的用戶信息
    private static ConcurrentHashMap<String, Session> SESSION = new ConcurrentHashMap<>();
    //原子遞增遞減,用于統(tǒng)計(jì)在線用戶數(shù)
    private static AtomicInteger count = new AtomicInteger();
    //消息隊(duì)列,用于保存待發(fā)送的信息
    private Queue<String> queue = new LinkedBlockingDeque<>();

   //onOpen()
   //onClose()
   //onMessage()
   //onError()
}

2.1.4 建立連接

建立連接之前,判斷用戶是否已經(jīng)連接,如果沒有連接,那么將用戶session信息保存到集合,然后計(jì)數(shù)器遞增。

@OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        if (!SESSION.containsKey(userId)) {
            SESSION.put(userId, session);
            count.incrementAndGet();
        }
    }

2.1.5 關(guān)閉連接

關(guān)閉連接的時候,將用戶session刪除和計(jì)數(shù)器遞減。

 @OnClose
    public void onClose(@PathParam("userId") String userId) {
        SESSION.remove(userId);
        count.decrementAndGet();
    }

2.1.6 發(fā)送消息

發(fā)送采用的方法是:session.getBasicRemote().sendText("你好");

	@OnMessage
    public void onMessage(String message, @PathParam("userId") String userId, @PathParam("target") String target) throws IOException {
        queue.add(message);
        Session s = SESSION.get(target);
        if (s == null) {
            Session b = SESSION.get(userId);
            b.getBasicRemote().sendText("對方不在線");
        } else {
            for (int i = 0; i < queue.size(); i++) {
                String msg = queue.poll();
                Message m = new Message();
                m.setUserId(userId);
                s.getBasicRemote().sendText(msg);
            }
        }
    }

2.1.7 監(jiān)聽錯誤

出現(xiàn)錯誤,刪除用戶session信息和計(jì)數(shù)器遞減

@OnError
    public void onError(Throwable error, @PathParam("userId") String userId) {
        SESSION.remove(userId);
        count.decrementAndGet();
        error.printStackTrace();
    }

2.2 客戶端

本案例中客戶端采用Nuxt編寫,相關(guān)代碼如下

2.2.1 主頁面

運(yùn)行截圖如圖所示:

<template>
  <div style="padding-left: 20%;">
    <div style="padding-left: 20%;padding-top: 30px;">
      <div style="font-size: 30px;">歡迎使用喵喵號聊天</div>
    </div>
    <div style="padding-top: 20%;">
      <el-form :rules="rules" ref="formInline" :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="我的喵喵號" prop="userId">
          <el-input v-model="formInline.userId" placeholder="喵喵號"></el-input>
        </el-form-item>
        <el-form-item label="對方喵喵號" prop="targetId">
          <el-input v-model="formInline.targetId" placeholder="喵喵號"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSubmit('formInline')">聊一下</el-button>
        </el-form-item>
      </el-form>
    </div>

  </div>
</template>

<script>
  export default {
    name: 'IndexPage',
    data() {
      return {

        formInline: {
          userId: '',
          targetId: ''
        },
        rules: {
          userId: [{
            required: true,
            message: '請輸入你的喵喵號',
            trigger: 'blur'
          }],
          targetId: [{
            required: true,
            message: '請輸入對方喵喵號',
            trigger: 'blur'
          }]
        }
      }

    },
    methods: {
      onSubmit(formName) {
        this.$refs[formName].validate((valid) => {
          if (valid) {
            this.$router.push({
              name: 'chat',
              params: this.formInline
            })
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      }
    },
    created() {

    }
  }
</script>
<style>
  body {
    background: url('../static/img/cat.jpg');
  }
</style>

2.2.1 聊天頁面

運(yùn)行截圖如下:
小明

翠花

<template>
  <div>
    <el-row :gutter="20" style="padding-top: 20px;">
      <div style="padding-left: 35%;">
        <div style="padding-bottom: 15px">
          <div style="float: left;padding-right: 30px;">
            我的喵喵號:<el-tag type="warning">{{user.userId}}</el-tag>
          </div>
          <div>
            對方喵喵號:<el-tag type="success">{{user.targetId}}</el-tag>
            <el-link @click="clearMsg()" :underline="false" style="padding-left: 30px;" type="danger">清空消息</el-link>
          </div>
        </div>
        <div style="border: 1px green solid;width: 400px;height: 400px;border-radius: 10px;">
          <div v-for="(m,index) in msgList" :key="index++">
            <el-row :gutter="20">
              <div v-if="m.type===1" style="padding-left: 10px;">
                <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
                {{m.msg}}
              </div>
              <div v-if="m.type===2" style="padding-right: 15px;float: right;">
                {{m.msg}}
                <el-avatar src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-avatar>

              </div>
              <div v-if="m.type===3" style="padding-left: 15px;padding-top: 15px;">系統(tǒng)消息:{{m.msg}}</div>
            </el-row>
          </div>
        </div>
      </div>
    </el-row>
    <el-row :gutter="5" style="padding-top: 20px;padding-left: 35%;">
      <el-col :span="9" :xs="9" :sm="9" :md="9" :lg="9" :xl="9">
        <el-input :disabled="msg_status" v-model="msg" placeholder="消息"></el-input>
      </el-col>
      <el-col :span="2">
        <el-button @click="sendMessage()" type="primary">發(fā)送</el-button>
      </el-col>
    </el-row>
  </div>

</template>

<script>
  export default {
    name: 'ChatPage',
    data() {
      return {
        url: 'localhost:3688/ws/1001/1002',
        msg: '',
        socket: {},
        msg_status: true,
        msgList: [],
        initList: [],
        count: 0,
        user: {
          userId: '',
          targetId: ''
        }

      }
    },
    created() {
      const userId = this.$route.params.userId
      const targetId = this.$route.params.targetId
      if (userId !== undefined && targetId !== undefined) {
        this.user.userId = userId
        this.user.targetId = targetId
        this.connect()
      } else {
        this.$router.push("/")
      }

    },
    methods: {
      //創(chuàng)建socket客戶端
      connect() {
        var that = this
        this.socket = new WebSocket("ws://42.193.120.86:3688/ws/" + this.user.userId + "/" + this.user.targetId);
        this.socket.onclose = function(event) {
          that.$message('連接關(guān)閉');
        };
        this.socket.addEventListener('error', function(event) {
          that.$message.error('出現(xiàn)錯誤');
        });
        // 監(jiān)聽消息
        this.socket.addEventListener('message', function(event) {
          that.msgList.push({
            type: 2,
            msg: event.data
          })
          console.log(event.data);
          console.log({
            type: 2,
            msg: event.data
          });
        });

        this.socket.onopen = function(event) {
          that.msg_status = false
          that.msgList.push({
            type: 3,
            msg: '連接成功'
          })
        };
      },
      clearMsg() {
        this.$confirm('確認(rèn)清空?', '提示', {
          confirmButtonText: '確定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {

          this.msgList = []
        })
      },
      //發(fā)送消息
      sendMessage() {
        this.socket.send(this.msg)
        this.msgList.push({
          type: 1,
          msg: this.msg
        })
        this.msg = ''
      }
    }
  }
</script>

<style>
</style>

三、開源地址

Gitee:https://gitee.com/BreezAm/websocket

演示地址:http://chat.breez.work

四、參考文獻(xiàn)

[1]MDN:WebSocket

[2]Nuxt:https://nuxtjs.org

[3]Vue:https://cn.vuejs.org

[4]百度百科:及時通信

到此這篇關(guān)于SpringBoot整合websocket實(shí)現(xiàn)即時通信聊天的文章就介紹到這了,更多相關(guān)SpringBoot websocket即時通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis 添加元數(shù)據(jù)自定義元素標(biāo)簽的實(shí)現(xiàn)代碼

    MyBatis 添加元數(shù)據(jù)自定義元素標(biāo)簽的實(shí)現(xiàn)代碼

    這篇文章主要介紹了MyBatis 添加元數(shù)據(jù)自定義元素標(biāo)簽的實(shí)現(xiàn)代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • springBoot 插件工具熱部署 Devtools的步驟詳解

    springBoot 插件工具熱部署 Devtools的步驟詳解

    這篇文章主要介紹了springBoot 插件工具 熱部署 Devtools,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • shiro 與 SpringMVC的整合完美示例

    shiro 與 SpringMVC的整合完美示例

    shiro可以直接和spring整合,但是這樣需要單獨(dú)配置spring用于整合shiro,在配置springmvc,接下來通過實(shí)例代碼給大家介紹shiro 整合 SpringMVC 的方法,感興趣的朋友一起看看吧
    2021-08-08
  • Java中的springboot監(jiān)聽事件和處理事件詳解

    Java中的springboot監(jiān)聽事件和處理事件詳解

    這篇文章主要介紹了Java中的springboot監(jiān)聽事件和處理事件,這個示例展示了如何在Spring Boot應(yīng)用中定義自定義事件、發(fā)布事件以及監(jiān)聽事件,需要的朋友可以參考下
    2024-07-07
  • Java并發(fā)中的ABA問題學(xué)習(xí)與解決方案

    Java并發(fā)中的ABA問題學(xué)習(xí)與解決方案

    這篇文章主要介紹了Java并發(fā)中的ABA問題學(xué)習(xí)與解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • java實(shí)現(xiàn)Excel轉(zhuǎn)換為圖片

    java實(shí)現(xiàn)Excel轉(zhuǎn)換為圖片

    在實(shí)際開發(fā)過程中,經(jīng)常會有這樣的需求,需要將Excel表格或特定區(qū)域轉(zhuǎn)換為圖片,所以小編今天就來為大家介紹一下如何使用Java將Excel轉(zhuǎn)化為圖片吧
    2023-10-10
  • Java編寫實(shí)現(xiàn)登陸窗口

    Java編寫實(shí)現(xiàn)登陸窗口

    這篇文章主要為大家詳細(xì)介紹了Java編寫實(shí)現(xiàn)登陸窗口,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Spring Cloud Alibaba配置多環(huán)境管理詳解與實(shí)戰(zhàn)代碼

    Spring Cloud Alibaba配置多環(huán)境管理詳解與實(shí)戰(zhàn)代碼

    本文通過實(shí)際案例詳細(xì)介紹了springboot配置多環(huán)境管理的使用,以及基于nacos的配置多環(huán)境管理的實(shí)踐,在實(shí)際開發(fā)中,配置多環(huán)境管理是一個很難避開的問題,同時也是微服務(wù)治理中一個很重要的內(nèi)容,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Spring實(shí)戰(zhàn)之SpEl語法實(shí)例詳解

    Spring實(shí)戰(zhàn)之SpEl語法實(shí)例詳解

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之SpEl語法,結(jié)合實(shí)例形式分析了SpEl創(chuàng)建數(shù)組、集合及解析變量等相關(guān)操作原理與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-12-12
  • java 多線程-線程通信實(shí)例講解

    java 多線程-線程通信實(shí)例講解

    本文主要介紹java 多線程-線程通信 這里整理了相關(guān)資料及示例代碼,有興趣的小伙伴可以參考下
    2016-09-09

最新評論