SpringBoot整合websocket

1.依赖

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

2.配置

/**
     * web_socket配置类
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

3.服务器部署:

package com.ciih.workshop.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Lenovo
 */
@Component
@Slf4j
@ServerEndpoint("/webSocket/{id}")
public class WebSocketServer {
    /**
     * 存储用户建立的连接Session
     */
    public static ConcurrentHashMap<String, Session> webSocketMap = new ConcurrentHashMap<>();


    /**
     * 建立连接调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") String id) throws IOException {

        if (webSocketMap.containsKey(id)) {
            webSocketMap.remove(id);
            webSocketMap.put(id, session);
        } else {
            webSocketMap.put(id, session);
        }
        log.info("连接成功:" + id);
        webSocketMap.get(id).getBasicRemote().sendText("连接成功");
    }


    /**
     * 连接关闭
     * 调用的方法
     */
    @OnClose
    public void onClose(@PathParam("id") String id) {
        webSocketMap.remove(id);
        log.info("连接关闭:" + id);
    }

    /**
     * 接收到客户端消
     **/
    @OnMessage
    public void onMessage(@PathParam("id") String id, String message) throws IOException {
        log.info("用户消息:" + id + ",报文:" + message);
        //可以群发消息
        //消息保存到数据库、redis
        if (StringUtils.isNotBlank(message)) {
            //解析发送的报文
            JSONObject jsonObject = JSON.parseObject(message);
            //追加发送人(防止串改)
            jsonObject.put("fromUserId", id);
            //解析收件人
            String toUserId = jsonObject.getString("toUserId");
            //传送给对应toUserId用户的websocket
            if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) {
                webSocketMap.get(toUserId).getBasicRemote().sendText(message);
            } else {
                //否则不在这个服务器上,发送到mysql或者redis
                log.error("请求的id:" + toUserId + "不在该服务器上");
            }
        }
    }

    @OnError
    public void onError(@PathParam("id") String id, Throwable error) {
        log.error("发生错误:" + id + ",原因:" + error.getMessage());
        error.printStackTrace();
    }
}

4.前端页面JSX

import { ref, reactive } from "vue";

let msg = ref("");

let socket;

// 主组件
const HelloWorld = () => {
  //发起websocket连接
  const openSocket = () => {
    const socketUrl = "ws://localhost:8080/webSocket/1";
    if (socket != null) {
      socket.close();
      socket = null;
    }
    socket = new WebSocket(socketUrl);
    //打开事件
    socket.onopen = function () {
      console.log("websocket已打开");
    };
    //监听服务器消息
    socket.onmessage = function (msg) {
      //存储服务器发来的消息
      messageList.set.add(msg.data);
    };
    //监听连接关闭事件
    socket.onclose = function () {
      console.log("websocket已关闭");
    };
    //监听连接错误事件
    socket.onerror = function () {
      console.log("websocket发生了错误");
    };
  };

  // 向Socket服务器发送消息
  const sendMessage = () => {
    socket.send(msg.value);
  };

  return (
    <>
      <el-button type={"primary"} size="default" onClick={openSocket}>
        连接websocket服务
      </el-button>
      <el-divider />
      <el-input style={{ width: "100px" }} v-model={msg.value}></el-input>
      <el-divider />
      <el-button type="primary" size="default" onClick={sendMessage}>
        发送消息
      </el-button>
      <el-divider />
      <h4>--------------收到消息-----------------</h4>
      <ReceivedMessage></ReceivedMessage>
    </>
  );
};

let messageList = reactive({
  set: new Set(),
});
// JSX组件 展示服务器发来的消息
const ReceivedMessage = () => {
  return (
    <>
      {Array.from(messageList.set).map((msg,index) => {
        return <div>{index}.{msg}</div>;
      })}
    </>
  );
};
export default HelloWorld;

获取IP工具类

package com.ciih.workshop.utils.sun;

import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;

public class WebSocketUtil {

    public static InetSocketAddress getRemoteAddress(Session session) {
        if (session == null) {
            return null;
        }
        RemoteEndpoint.Async async = session.getAsyncRemote();

        //在Tomcat 8.0.x版本有效
        InetSocketAddress addr0 = (InetSocketAddress) getFieldInstance(async,"base#sos#socketWrapper#socket#sc#remoteAddress");
        System.out.println("clientIP0" + addr0);
        //在Tomcat 8.5以上版本有效
        InetSocketAddress addr = (InetSocketAddress) getFieldInstance(async, "base#socketWrapper#socket#sc#remoteAddress");
        System.out.println("clientIP1" + addr);
        return addr;
    }


    private static Object getFieldInstance(Object obj, String fieldPath) {
        String fields[] = fieldPath.split("#");
        for (String field : fields) {
            obj = getField(obj, obj.getClass(), field);
            if (obj == null) {
                return null;
            }
        }

        return obj;
    }

    private static Object getField(Object obj, Class<?> clazz, String fieldName) {
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                Field field;
                field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (Exception e) {
            }
        }

        return null;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要实现Spring Boot整合WebSocket,你需要进行以下步骤: 1. 首先,在pom.xml文件中添加WebSocket的相关依赖。可以使用以下两个依赖之一: - 从中提到的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` - 从中提到的依赖: ```xml <!--webSocket--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建WebSocket配置类,这个类负责配置WebSocket的相关信息。你可以按照以下方式创建一个配置类[3]: ```java package com.loit.park.common.websocket; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } ``` 3. 至此,你已经完成了WebSocket整合配置。现在,你可以在你的应用中创建WebSocket的控制器并定义你的WebSocket端点。你可以根据你的需求来实现WebSocket端点的业务逻辑。 这就是Spring Boot整合WebSocket的基本步骤。通过这种方式,你可以在Spring Boot应用中轻松地使用WebSocket进行实时通信。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [springboot整合websocket](https://blog.csdn.net/weixin_45390688/article/details/120448778)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [springboot整合websocket(详解、教程、代码)](https://blog.csdn.net/hjq_ku/article/details/127503180)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

文子阳

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

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

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

打赏作者

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

抵扣说明:

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

余额充值