WevSocket(java基于spring框架实现)

news2024/11/28 6:34:49

一、概述

本文基于spring-boot-starter-websocket简单的完成收发信息功能,使用spring框架进行实现。

二、相关配置

spring:2.0.2,jdk:1.8.202,maven:3.3.9

因为spring和maven有版本匹配的要求,请大家注意自己的版本是否匹配

三、项目结构

四、代码

1.启动类

SocketDemoApplication
package com.lp.socketdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@EnableScheduling
@SpringBootApplication
public class SocketDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SocketDemoApplication.class, args);
    }

    //处理定时任务报错问题
    @Bean
    public ThreadPoolTaskScheduler taskScheduler(){
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        taskScheduler.initialize();
        return taskScheduler;
    }
}

2.握手拦截器

package com.lp.socketdemo.spring;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.util.Map;

/**
 * 握手拦截器
 */
@Component
public class MyInterceptor extends HttpSessionHandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        System.out.println(request.getRemoteAddress().toString()+"开始握手");
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        System.out.println(request.getRemoteAddress().toString()+"完成握手");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

3.websocket主程序

package com.lp.socketdemo.spring;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * websocket 主程序
 */
@Component
public class MyWsHandler extends AbstractWebSocketHandler {

    private static Map<String,SessionBean> map;
    private static AtomicInteger clientIdMaker;
    static {
        map = new ConcurrentHashMap<>();
        clientIdMaker = new AtomicInteger(0);
    }

    /**
     * 连接建立
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        SessionBean sb = new SessionBean(session,clientIdMaker.getAndIncrement());
        map.put(session.getId(),sb);
        System.out.println(map.get(session.getId()).getClientId() +":建立连接");
        super.afterConnectionEstablished(session);
    }

    /**
     * 接收信息
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        System.out.println(map.get(session.getId()).getClientId() +":"+message.getPayload());
    }

    /**
     * 传输异常
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
        if(session.isOpen()) {
            session.close();
        }
        map.remove(session.getId());
    }

    /**
     * 连接关闭
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        System.out.println(map.get(session.getId()).getClientId() +":关闭连接");
        map.remove(session.getId());
    }

    @Scheduled(fixedRate = 10000)
    public void sendMsg() throws IOException{
        for (String key: map.keySet()) {

                map.get(key).getWebSocketSession().sendMessage(new TextMessage("ws2心跳"));

        }
    }
}

4.配置类

package com.lp.socketdemo.spring;

import com.lp.socketdemo.java.WebSocketConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import javax.annotation.Resource;

@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {

    @Resource
    MyWsHandler MyWsHandler;

    @Resource
    MyInterceptor myInterceptor;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(MyWsHandler,"/myWs2").addInterceptors(myInterceptor).setAllowedOrigins("*");
    }
}

5.封装实体类

package com.lp.socketdemo.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

@Component
public class SessionBean {
    private WebSocketSession webSocketSession;
    private int clientId;

    public SessionBean() {
    }

    public SessionBean(WebSocketSession webSocketSession, int clientId) {
        this.webSocketSession = webSocketSession;
        this.clientId = clientId;
    }

    public WebSocketSession getWebSocketSession() {
        return webSocketSession;
    }

    public void setWebSocketSession(WebSocketSession webSocketSession) {
        this.webSocketSession = webSocketSession;
    }

    public int getClientId() {
        return clientId;
    }

    public void setClientId(int clientId) {
        this.clientId = clientId;
    }
}

5.前段

websocketTest.html

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>websocket调试页面</title>
</head>
<script type="text/javascript" src="jquery.min.js"></script>
<body>
<div style="float: left; padding: 20px">
  <strong>location:</strong> <br />
  <input type="text" id="serverUrl" size="35" value="" /> <br />
  <button onclick="connect()">connect</button>
  <button onclick="wsclose()">disConnect</button>
  <br /> <strong>message:</strong> <br /> <input id="txtMsg" type="text" size="50" />
  <br />
  <button onclick="sendEvent()">发送</button>
</div>
 
<div style="float: left; margin-left: 20px; padding-left: 20px; width: 350px; border-left: solid 1px #cccccc;"> <strong>消息记录</strong>
  <div style="border: solid 1px #999999;border-top-color: #CCCCCC;border-left-color: #CCCCCC; padding: 5px;width: 100%;height: 172px;overflow-y: scroll;" id="echo-log"></div>
  <button onclick="clearLog()" style="position: relative; top: 3px;">清除消息</button>
</div>
 
</div>
</body>
<!-- 下面是h5原生websocket js写法 -->
<script type="text/javascript">
  let output ;
  let websocket;
  function connect(){ //初始化连接
    output = document.getElementById("echo-log")
    let inputNode = document.getElementById("serverUrl");
    let wsUri = inputNode.value;
    try{
		websocket = new WebSocket(wsUri);
    }catch(ex){
      console.log(ex)
      alert("对不起websocket连接异常")
    }
 
    connecting();
    window.addEventListener("load", connecting, false);
  }
 
 
  function connecting()
  {
    websocket.onopen = function(evt) { onOpen(evt) };
    websocket.onclose = function(evt) { onClose(evt) };
    websocket.onmessage = function(evt) { onMessage(evt) };
    websocket.onerror = function(evt) { onError(evt) };
  }
 
  function sendEvent(){
    let msg = document.getElementById("txtMsg").value
    doSend(msg);
  }
 
  //连接上事件
  function onOpen(evt)
  {
    writeToScreen("CONNECTED");
    doSend("WebSocket 已经连接成功!");
  }
 
  //关闭事件
  function onClose(evt)
  {
    writeToScreen("连接已经断开!");
  }
 
  //后端推送事件
  function onMessage(evt)
  {
    writeToScreen('<span style="color: blue;">服务器: ' + evt.data+'</span>');
  }
 
  function onError(evt)
  {
    writeToScreen('<span style="color: red;">异常信息:</span> ' + evt.data);
  }
 
  function doSend(message)
  {
    writeToScreen("客户端A: " + message);
    websocket.send(message);
  }
 
  //清除div的内容
  function clearLog(){
    output.innerHTML = "";
  }
 
  //浏览器主动断开连接
  function wsclose(){
    websocket.close();
  }
 
  function writeToScreen(message)
  {
    let pre = document.createElement("p");
    pre.innerHTML = message;
    output.appendChild(pre);
  }
</script>
</html>

五.效果展示

六、引用

课程介绍_WebSocket入门与案例实战-慕课网

最全面的SpringMVC教程(六)——WebSocket_springmvc websocket_小新要变强的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/952253.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

专线连接交换机设置 – 如何实现高效率的网络连接?

专线链接交换机设置 – 如何实现高效率的网络连接&#xff1f; 什么是专线连接交换机&#xff1f; 在现代互联网中&#xff0c;网络连接的快速和高效是至关重要的。尤其是对于需要大量数据传输和保证网络稳定性的企业和组织来说&#xff0c;专线连接交换机是一项非常重要的技…

华为云Stack的学习(四)

五、Service OM资源管理 1.Service OM简介 1.1 Service OM介绍 在华为云Stack解决方案中&#xff0c;Service OM是FusionSphere OpenStack的操作管理界面&#xff0c;是资源池&#xff08;计算、存储、网络&#xff09;以及基础云服务的管理工具。 1.2 Service OM定位 Serv…

分类算法系列②:KNN算法

目录 KNN算法 1、简介 2、原理分析 数学原理 相关公式及其过程分析 距离度量 k值选择 分类决策规则 3、API 4、⭐案例实践 4.1、分析 4.2、代码 5、K-近邻算法总结 &#x1f343;作者介绍&#xff1a;准大三网络工程专业在读&#xff0c;努力学习Java&#xff0c;涉…

Vue-关于路由规则模块的封装

路由的封装抽离 对路由的封装进行封装&#xff0c;方便main.js文件维护 首先&#xff1a; 我们需要再src文件夹中创建一个router文件夹&#xff0c;在里面在创建一个index.js文件夹。 然后&#xff1a; 我们再index.js文件夹中进行封装路由规则 import Find from /views/F…

技术深入解析与教程:网络安全技术探秘

第一章&#xff1a;引言 在当今数字化时代&#xff0c;网络安全已经成为了重要议题。随着各种信息和业务在网络上的传输与存储&#xff0c;安全问题也日益突出。本文将带您深入探讨网络安全领域中的关键技术&#xff0c;涵盖渗透测试、漏洞挖掘以及恶意软件分析等方面&#xf…

opencv android sdk 使用中的问题

Plugin with id ‘kotlin-android’ not found 在build.gradle(:app)中添加以下内容 buildscript {ext {Kotlin_Verion "1.9.10"}dependencies {classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$Kotlin_Verion"}repositories {mavenCentral()} …

SpringBoot通过@Cacheable注解实现缓存功能

目录 一、Spring从3.1开始支持Cache二、Cacheable常用属性1、value/cacheNames2、key3、condition4、unless5、keyGenerator6、sync7、cacheManager 三、整合步骤1、加入pom2、启动类加EnableCaching注解3、controller或service加Cacheable注解即可 四、代码实例五、Spring Boo…

Linux下批量创建文件夹

检测文件是否存在 这里的文件包含普通文件或者是目录文件,下面是CentOS 7环境下的测试. #include <sys/stat.h> #include <unistd.h> #include <iostream>int main() {int ret access("../lesson01/file.txt", F_OK);if (ret 0){std::cout <…

经管博士科研基础【6】:如何理解箱式图

箱形图,也叫盒须图,盒式图,boxplot。有95%的把握猜中你现在已经不太确定,这图中有几条线?每条线代表什么意思?中间的那条线代表的究竟是算数平均数还是中位数,还是众数? 再问的深点,箱形图存在的意义为何?之于数据分析的实践意义在哪里? 接下来,带你从概念开始,…

如何回答‘行为面试题’:用实例展示你的能力

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Linux 8 下的容器引擎Podman概述

一、前言 最近在进行OS国产化交流中&#xff0c;了解到部分业务迁移到BClinux 8.2或Anolis 8.2时&#xff0c;原有docker业务需要迁移到新的容器平台&#xff1a;Podman&#xff0c;来完成容器的新的管理。Podman&#xff08;全称 Pod Manager&#xff09;是一款用于在 Linux 系…

MOS管的损耗分析

目的 1、MOS管的损耗分类&#xff1a; 开关损耗&#xff1a; 栅驱动损耗&#xff1a; 导通损耗&#xff1a; 主要内容 MOS管损耗主要有开关损耗&#xff08;开通损耗和关断损耗&#xff0c;关注参数Cgd(Crss)&#xff09;、栅极驱动损耗&#xff08;关注参数Qg&#xff09;和…

面试流程解析:从初面到终面,程序员需要注意什么

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

RabbitMQ 的快速使用

docker部署rabbitmq # management才有管理页面 docker pull rabbitmq:management# 新建容器并运行 docker run \-e RABBITMQ_DEFAULT_USERadmin \ -e RABBITMQ_DEFAULT_PASSadmin \ -v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \-itd \ra…

客服系统哪个好用?

在当今竞争激烈的商业环境中&#xff0c;良好的客户服务是企业成功的关键因素之一。通过提供优质的客户服务&#xff0c;企业可以吸引、留住、回馈顾客&#xff0c;增加口碑宣传&#xff0c;提高产品或服务质量&#xff0c;同时还可以减少客户投诉率&#xff0c;从而为企业带来…

docker容器运行成功但无法访问,原因分析及对应解决方案(最新,以Tomcat为例,亲测有效)

原因分析&#xff1a; 是否能访问当运行docker容器虚拟机&#xff08;主机&#xff09;地址 虚拟机对应的端口号是否开启或者防墙是否关闭 端口映射是否正确&#xff08;这个是我遇到的&#xff09; tomcat下载的是最新版&#xff0c;docker运行后里面是没有东西的&am…

跨屏无界 | ZlongGames 携手 Google Play Games 打造无缝游戏体验

一款经典游戏&#xff0c;会在时间的沉淀中被每一代玩家所怀念&#xff0c;经久不衰。对于紫龙游戏来讲&#xff0c;他们就是这样一群怀揣着创作出经典游戏的初心而聚集在一起的团队&#xff0c;致力于研发出被广大玩家喜爱的作品。 从 2015 年团队成立&#xff0c;到 2019 年走…

DHCP实验

文章目录 一、实验背景与目的二、实验拓扑三、 实验需求四、实验解法1. R1配置IP地址部分2. 配置R1的DHCP服务3. 配置IP地址排除4. 配置PC3和PC4的IP地址为自动获取&#xff0c;然后可以自动获得192.168.1.0/24网段的IP地址。 摘要&#xff1a; 本实验旨在通过配置DHCP服务器和…

2023-8-30 Dijkstra 求最短路(一)

题目链接&#xff1a;Dijkstra求最短路 I #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 510;int n, m; int g[N][N]; int dist[N]; bool st[N];int dijkstra() {memset(dist, 0x3f, sizeof dist);dist[1…

【力扣每日一题】2023.8.30 到家的最少跳跃次数

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一只跳蚤&#xff0c;我们可以操控它前跳 a 格或是后跳 b 格&#xff0c;不能跳到小于0的位置&#xff0c;有一些被禁止的点不…