闲来无事,学习下WebSocket

闲来无事啃啃Websocket

前言

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。

小试牛刀

这次只是简单了解下websocket,先把项目搭建起来,让项目能够跑起来,万事开头难,项目能够跑起来就说明最难的问题已经解决了。

后端

导入依赖

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

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

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

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

配置类

@Configuration
public class WebSocketConfig {

    /**
     * 注入ServerEndpointExporter,自动注册使用@ServerEndpoint注解
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

端点

@Slf4j
@Component
@ServerEndpoint(value = "/chat/{username}")
public class ChatEndpoint {

    //存储每一个客户端对象对应的chatEndpoint对象
    private static Map<String, ChatEndpoint> onlineUsers = new ConcurrentHashMap<>();

    //和某个客户端连接对象,需要通过他来给客户端发送数据
    private Session session;

    private String username;

    /**
     * 建立成功时调用
     * 将当前会话建立成功的用户会话保存起来
     * @param session
     * @param username
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "username") String username) {

        this.session = session;

        //保存用户
        onlineUsers.put(username, this);
        this.username = username;

        log.info("用户连接成功 = [{}]", username);
    }

    /**
     * 接收到消息时调用
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        //解析用户发送来的数据
        log.info("用户消息 = [{}]", message);
        //将消息广播给其他用户
        Map<String, ChatEndpoint> onlineUsers = ChatEndpoint.onlineUsers;
        Set<String> keySet = onlineUsers.keySet();
        Iterator<String> it = keySet.iterator();
        while (it.hasNext()) {
            String username = it.next();
            if (this.username.equals(username)) {
                continue;
            }
            ChatEndpoint chatEndpoint = onlineUsers.get(username);
            chatEndpoint.session.getAsyncRemote().sendText(this.username + ":" + message);
        }

    }

    @OnClose
    public void onClose(Session session) {

        onlineUsers.remove(this.username);
        log.info("用户关闭成功 = [{}]", username);
    }

}

websocket实现有编程式和注解式,而我采用的是注解式,我并没有对连接的用户做身份验证,只是简单的先让项目能够跑起来,后续再慢慢优化。

至此,启动项目即可,接下来就是通过前端来连接。

前端

前端我采用的是Vue来实现,因为日常主要从事后端开发工作,所以以前学的Vue都丢掉了,现在要慢慢一点点重新捡起来了。

首先,如果没有安装node环境的童鞋需要先安装,安装过程也是很简单的,可以自行百度搜索一下,就几行命令。

先创建一个Vue项目,在前端的工作目录下进入cmd窗口执行 Vue create xxxx(项目名),然后选择Vue版本,我创建的是Vue3,选择好就等待创建完成即可。

创建vue项目
tips:执行vue create xxx命令可能需要等一会儿.
选择vue框架版本
选择vue的版本,此处我选择的是3,直接回车即可,然后等待项目创建完成。

项目创建完成后可以用开发工具打开,我用的开发工具是webstorm,因为作为一名后端开发习惯了idea的开发页面。

下载websocket依赖
下载websocket依赖

然后我们简单的在项目自带的HelloWorld组件上面进行代码编写

<template>
  <div>
    <span>用户名:</span>
    <input v-model="username">
    <button v-on:click="connectServer">连接服务器</button><br/>
    <input v-model="msg"/>
    <button v-on:click="sendMsg">发送消息</button><br/>

  </div>
</template>

<script>

export default{
  name: "HelloWorld",
  methods: {
    sendMsg() {
      this.socket.send(this.msg)
      console.log("向服务器发送消息" + this.msg);
    },
    connectServer () {
      console.log("开始连接...")
      const endpoint = 'ws://localhost:8082/chat/' + this.username; // WebSocket的地址
      this.socket = new WebSocket(endpoint);

      this.socket.addEventListener('message', (event) => {
        // 处理服务器发送的消息
        console.log("服务器:" + event.data);

      });

      this.socket.addEventListener('close', () => {
        // 连接关闭
        console.log('连接关闭')
      });
    }
  },
  data() {
    return {
      username: "",
      msg: ""
    }
  }
}
</script>

在这里我是将内容打印在控制台上面,所以需要F12进入开发者工具的控制台中看打印内容。

最后一步,启动前端项目,执行 npm run serve 即可。

项目启动完成
先输入用户名连接服务器,再用其它浏览器打开窗口访问 localhost:8080 同操作,发送消息即可广播给其它用户。

tips: websocket难点在于session对象无法序列化,分布式情况下需要解决找到上一次连接所在节点,所以后续我会一步步解决这个问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不爱敲代码_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值