侧边栏壁纸
  • 累计撰写 57 篇文章
  • 累计创建 10 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Springboot 集成 socket.io

yilee
2023-04-04 / 0 评论 / 0 点赞 / 111 阅读 / 0 字
温馨提示:
本文最后更新于2024-05-31,若内容或图片失效,请留言反馈。 部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Springboot 集成 socket.io

配置依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>com.corundumstudio.socketio</groupId>
    <artifactId>netty-socketio</artifactId>
    <version>1.7.19</version>
</dependency>

后台参数

  • yml参数
socketio:
  port: 8081
  host: 0.0.0.0
  boss-count: 1
  work-count: 100
  max-frame-payload-length: 1048576
  max-http-content-length: 1048576
  allow-custom-requests: true
  upgrade-timeout: 10000
  ping-timeout: 60000
  ping-interval: 25000
  • properties类注入这些参数
@Component
@PropertySource("classpath:application.yml")
@ConfigurationProperties(prefix = "socketio")
@Data
public class SocketIO {
    /**
     * 请求主机
     */
    private String host;
    /**
     * 请求主机端口
     */
    private Integer port;
    /**
     * 设置最大每帧处理数据的长度,防止他人利用大数据来攻击服务器
     */
    private Integer maxFramePayloadLength;
    /**
     * 设置http交互最大内容长度
     */
    private Integer maxHttpContentLength;
    /**
     * socket连接数大小(如只监听一个端口boss线程组为1即可)
     */
    private Integer bossCount;
    /**
     * 工作线程
     */
    private Integer workCount;
    /**
     * 允许自定义请求
     */
    private Boolean allowCustomRequests;
    /**
     * 协议升级超时时间(毫秒),默认10秒。HTTP握手升级为ws协议超时时间
     */
    private Integer upgradeTimeout;
    /**
     * Ping消息超时时间(毫秒),默认60秒,这个时间间隔内没有接收到心跳消息就会发送超时事件
     */
    private Integer pingTimeout;
    /**
     * Ping消息间隔(毫秒),默认25秒。客户端向服务器发送一条心跳消息间隔
     */
    private Integer pingInterval;
}

  • Configuration 类,将socketIO注册为springboot 的容器
import com.corundumstudio.socketio.SocketConfig;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.liheji.component.SocketIOHandler;
import top.liheji.properties.SocketIO;

/**
 * @Time : 2021/11/25 23:46
 * @Author : Galaxy
 * @Create : IdeaJ
 * @Project : server
 * @Description :
 */
@Configuration
public class SocketIOConfig {
    @Autowired
    public SocketIO socketIO;

    /**
     * 配置装载
     *
     * @return SocketIOServer
     */
    @Bean
    public SocketIOServer socketIOServer() {
        SocketConfig socketConfig = new SocketConfig();
        socketConfig.setTcpNoDelay(true);
        socketConfig.setSoLinger(0);
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        config.setSocketConfig(socketConfig);
        config.setHostname(socketIO.getHost());
        config.setPort(socketIO.getPort());
        config.setBossThreads(socketIO.getBossCount());
        config.setWorkerThreads(socketIO.getWorkCount());
        config.setAllowCustomRequests(socketIO.getAllowCustomRequests());
        config.setUpgradeTimeout(socketIO.getUpgradeTimeout());
        config.setPingTimeout(socketIO.getPingTimeout());
        config.setPingInterval(socketIO.getPingInterval());
        //权限认证拦截器
        config.setAuthorizationListener(socketIOHandler());
        
        return new SocketIOServer(config);
    }

    /**
     * 用于扫描netty-socketio的注解,比如 @OnConnect、@OnEvent
     **/
    @Bean
    public SpringAnnotationScanner springAnnotationScanner() {
        return new SpringAnnotationScanner(socketIOServer());
    }

    /**
     * 注入socket处理拦截器
     *
     * @return 拦截器
     */
    @Bean
    public SocketIOHandler socketIOHandler() {
        return new SocketIOHandler();
    }
}
  • Configuration 用到了权限认证拦截器如下
import com.corundumstudio.socketio.AuthorizationListener;
import com.corundumstudio.socketio.HandshakeData;

public class SocketIOHandler implements AuthorizationListener {

    @Override
    public boolean isAuthorized(HandshakeData handshakeData) {
        String token = handshakeData.getSingleUrlParam("token");
        if ("e4038260a69e45159beaf7a282dd8e82".equals(token)) {
            return true;
        }

        return false;
    }
}

服务类

import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.liheji.service.SocketIOService;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

//注册为服务
@Service
public class SocketIOService {

    /**
     * 已连接的客户端
     */
    private static final Map<UUID, SocketIOClient> CLIENT_MAP = new ConcurrentHashMap<>();

    /**
     * 注入socketIOServer
     */
    @Autowired
    private SocketIOServer socketIOServer;


    /**
     * 客户端连上socket服务器时执行此事件
     *
     * @param client 客户端
     */
    @OnConnect
    public void onConnect(SocketIOClient client) {
        String server = client.getHandshakeData().getSingleUrlParam("server");
        String key = client.getHandshakeData().getSingleUrlParam("key");
        System.out.println("认证");
        System.out.println(server);
        System.out.println(key);

        System.out.println("连接成功: " + client.getSessionId());
        System.out.println("连接成功: " + client.getTransport());
        CLIENT_MAP.put(client.getSessionId(), client);
    }

    /**
     * 客户端断开socket服务器时执行此事件
     *
     * @param client 客户端
     */
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        CLIENT_MAP.remove(client.getSessionId());
        System.out.println("断开连接: " + client.getSessionId());
        client.disconnect();
    }
    
    //注册json事件
    @OnEvent("json")
    public void onEventJson(SocketIOClient client, AckRequest request, Object data) {
        System.out.println("收到来自客户端:" + data);
        Map<String, Object> map = new HashMap<>(2);
        map.put("code", 0);
        map.put("msg", "更新完成");
        map.put("count", 1);
        map.put("total", 1);
        client.sendEvent("push", map);
    }

    /**
     * 在加载当前Bean之后执行
     * 启动监听客户端连接
     */
    @PostConstruct
    private void autoStart() {
        socketIOServer.start();
    }

    /**
     * 销毁Bean之前执行
     * 停止监听客户端连接
     * 防止端口占用
     */
    @PreDestroy
    private void autoStop() {
        if (socketIOServer != null) {
            socketIOServer.stop();
            socketIOServer = null;
        }

        CLIENT_MAP.clear();
    }
}

前端配置

  • 依赖
<!--jquery依赖-->
<script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
<!--socket.io核心依赖-->
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
  • js代码
let socket;

function connect() {
    //token 用于权限验证
    //transports 传输类型,指定使用websocket
    socket = io.connect('http://127.0.0.1:8081', {
        query: `token=e4038260a69e45159beaf7a282dd8e82`,
        transports: ["websocket", "polling"]
    });

    //连接建立事件
    socket.on('connect', function () {
        console.log("连接成功");
        serverOutput('<span class="connect-msg">连接成功</span>');
    });
    
	//push事件
    socket.on('push', function (data) {
        output(`<span class="username-msg">${data}</span>`);
        console.log(data);
    });
    
	//连接释放事件
    socket.on('disconnect', function () {
        serverOutput('<span class="disconnect-msg">已下线! </span>');
    });
    
    //连接错误事件
    socket.on("connect_error", () => {
        // revert to classic upgrade
        socket.io.opts.transports = ["polling", "websocket"];
    });
}


//****自定义js内容,无需关心,这里引用了jquery,只做展示使用
function disconnect() {
    socket.disconnect();
}

function output(message) {
    const element = $("<div>" + message + "</div>");
    $('#console').append(element);
}

function serverOutput(message) {
    const element = $("<div>" + message + "</div>");
    $('#console').append(element);
}

function send() {
    socket.emit('json', {data: $("#msg").val()});
}
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区