websokcet服务端实现

一/websokcet服务端实现

步骤一: springboot底层帮我们自动配置了websokcet,引入maven依赖

1

2

3

4

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-websocket</artifactId>

</dependency>

步骤二:如果是你采用springboot内置容器启动项目的,则需要配置一个Bean。如果是采用外部的容器,则可以不需要配置。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/**

 * @Description: 配置类

 */

@Component

public class WebSocketConfig {

  

    /**

     * ServerEndpointExporter 作用

     *

     * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint

     *

     * @return

     */

    @Bean

    public ServerEndpointExporter serverEndpointExporter() {

        return new ServerEndpointExporter();

    }

}

 步骤三:最后一步当然是编写服务端核心代码了,其实本人不是特别想贴代码出来,贴很多代码影响文章可读性。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

package com.example.socket.code;

  

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

  

import javax.websocket.OnClose;

import javax.websocket.OnMessage;

import javax.websocket.OnOpen;

import javax.websocket.Session;

import javax.websocket.server.PathParam;

import javax.websocket.server.ServerEndpoint;

import java.util.concurrent.ConcurrentHashMap;

  

/**

 * @Description: websocket 服务类

 */

  

/**

 *

 * @ServerEndpoint 这个注解有什么作用?

 *

 * 这个注解用于标识作用在类上,它的主要功能是把当前类标识成一个WebSocket的服务端

 * 注解的值用户客户端连接访问的URL地址

 *

 */

  

@Slf4j

@Component

@ServerEndpoint("/websocket/{name}")

public class WebSocket {

  

    /**

     *  与某个客户端的连接对话,需要通过它来给客户端发送消息

     */

    private Session session;

  

     /**

     * 标识当前连接客户端的用户名

     */

    private String name;

  

    /**

     *  用于存所有的连接服务的客户端,这个对象存储是安全的

     */

    private static ConcurrentHashMap<String,WebSocket> webSocketSet = new ConcurrentHashMap<>();

  

  

    @OnOpen

    public void OnOpen(Session session, @PathParam(value = "name") String name){

        this.session = session;

        this.name = name;

        // name是用来表示唯一客户端,如果需要指定发送,需要指定发送通过name来区分

        webSocketSet.put(name,this);

        log.info("[WebSocket] 连接成功,当前连接人数为:={}",webSocketSet.size());

    }

  

  

    @OnClose

    public void OnClose(){

        webSocketSet.remove(this.name);

        log.info("[WebSocket] 退出成功,当前连接人数为:={}",webSocketSet.size());

    }

  

    @OnMessage

    public void OnMessage(String message){

        log.info("[WebSocket] 收到消息:{}",message);

        //判断是否需要指定发送,具体规则自定义

        if(message.indexOf("TOUSER") == 0){

            String name = message.substring(message.indexOf("TOUSER")+6,message.indexOf(";"));

            AppointSending(name,message.substring(message.indexOf(";")+1,message.length()));

        }else{

            GroupSending(message);

        }

  

    }

  

    /**

     * 群发

     * @param message

     */

    public void GroupSending(String message){

        for (String name : webSocketSet.keySet()){

            try {

                webSocketSet.get(name).session.getBasicRemote().sendText(message);

            }catch (Exception e){

                e.printStackTrace();

            }

        }

    }

  

    /**

     * 指定发送

     * @param name

     * @param message

     */

    public void AppointSending(String name,String message){

        try {

            webSocketSet.get(name).session.getBasicRemote().sendText(message);

        }catch (Exception e){

            e.printStackTrace();

        }

    }

}

二、客户端实现

HTML5实现:以下就是核心代码了,其实其他博客有很多,本人就不多说了。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

var websocket = null;

   if('WebSocket' in window){

       websocket = new WebSocket("ws://192.168.2.107:8085/websocket/testname");

   }

   websocket.onopen = function(){

       console.log("连接成功");

   }

   websocket.onclose = function(){

       console.log("退出连接");

   }

   websocket.onmessage = function (event){

       console.log("收到消息"+event.data);

   }

   websocket.onerror = function(){

       console.log("连接出错");

   }

   window.onbeforeunload = function () {

       websocket.close(num);

   }

SpringBoot后台实现:本人发现多数博客都是采用js来实现客户端,很少有用后台来实现,所以本人也就写了写,大神请勿喷?。很多时候,项目与项目之间通讯也需要后台作为客户端来连接。

步骤一:首先我们要导入后台连接websocket的客户端依赖

1

2

3

4

5

6

<!--websocket作为客户端-->

<dependency>

    <groupId>org.java-websocket</groupId>

    <artifactId>Java-WebSocket</artifactId>

    <version>1.3.5</version>

</dependency>

 步骤二:把客户端需要配置到springboot容器里面去,以便程序调用。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

package com.example.socket.config;

  

import lombok.extern.slf4j.Slf4j;

import org.java_websocket.client.WebSocketClient;

import org.java_websocket.drafts.Draft_6455;

import org.java_websocket.handshake.ServerHandshake;

import org.springframework.context.annotation.Bean;

import org.springframework.stereotype.Component;

  

import java.net.URI;

  

/**

 * @Description: 配置websocket后台客户端

 */

@Slf4j

@Component

public class WebSocketConfig {

  

    @Bean

    public WebSocketClient webSocketClient() {

        try {

            WebSocketClient webSocketClient = new WebSocketClient(new URI("ws://localhost:8085/websocket/test"),new Draft_6455()) {

                @Override

                public void onOpen(ServerHandshake handshakedata) {

                    log.info("[websocket] 连接成功");

                }

  

                @Override

                public void onMessage(String message) {

                    log.info("[websocket] 收到消息={}",message);

  

                }

  

                @Override

                public void onClose(int code, String reason, boolean remote) {

                    log.info("[websocket] 退出连接");

                }

  

                @Override

                public void onError(Exception ex) {

                    log.info("[websocket] 连接错误={}",ex.getMessage());

                }

            };

            webSocketClient.connect();

            return webSocketClient;

        catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }

  

}

步骤三:使用后台客户端发送消息

1、首先本人写了一个接口,里面有指定发送和群发消息两个方法。

2、实现发送的接口,区分指定发送和群发由服务端来决定(本人在服务端写了,如果带有TOUSER标识的,则代表需要指定发送给某个websocket客户端)。

3、最后采用get方式用浏览器请求,也能正常发送消息。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

package com.example.socket.code;

  

/**

 * @Description: websocket 接口

 */

public interface WebSocketService {

  

    /**

     * 群发

     * @param message

     */

     void groupSending(String message);

  

    /**

     * 指定发送

     * @param name

     * @param message

     */

     void appointSending(String name,String message);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

package com.example.socket.chat;

  

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

  

/**

 * @Description: 测试后台websocket客户端

 */

@RestController

@RequestMapping("/websocket")

public class IndexController {

  

    @Autowired

    private WebSocketService webSocketClient;

  

    @GetMapping("/sendMessage")

    public String sendMessage(String message){

        webScoketClient.groupSending(message);

        return message;

    }

}

三、最后

注意:

如果是单例的情况下,这个对象的值都会被修改。

本人就抽了时间Debug了一下,经过下图也可以反映出,能够看出,webSokcetSet中存在三个成员,并且vlaue值都是不同的,所以在这里没有出现对象改变而把之前对象改变的现象。

服务端这样写是没问题的。

最后总结:在实际WebSocket服务端案例中为什么没有出现这种情况,当WebSokcet这个类标识为服务端的时候,每当有新的连接请求,这个类都是不同的对象,并非单例。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

import com.alibaba.fastjson.JSON;

  

import java.util.concurrent.ConcurrentHashMap;

  

/**

 * @Description:

 */

public class TestMain {

  

    /**

     * 用于存所有的连接服务的客户端,这个对象存储是安全的

     */

    private static ConcurrentHashMap<String, Student> webSocketSet = new ConcurrentHashMap<>();

  

    public static void main(String[] args) {

        Student student = Student.getStudent();

        student.name = "张三";

        webSocketSet.put("1", student);

  

        Student students = Student.getStudent();

        students.name = "李四";

        webSocketSet.put("2", students);

  

        System.out.println(JSON.toJSON(webSocketSet));

    }

}

  

/**

 * 提供一个单例类

 */

class Student {

  

    public String name;

  

    private Student() {

    }

  

    private static final Student student = new Student();

  

    public static Student getStudent() {

        return student;

  

    }

}

 打印结果:

1

{"1":{"name":"李四"},"2":{"name":"李四"}}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣刷题 二叉树遍历的统一迭代法

题干 给定一个二叉树的根节点 root &#xff0c;返回 它的 前中后序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#xff1a;root […

Python 之 Fastapi 框架学习

依赖安装 Fastapi 有版本要求&#xff0c;需要的 Python 版本至少是 Python 3.8&#xff08;不要犟&#xff0c;按照版本要求来&#xff0c;我最先也是在我 Python3.6 上装的&#xff0c;果不其然跑不起来&#xff09;&#xff0c;幸好我 Win7 老古董能支持的 Python 最高版本…

FastWiki发布`0.2.4`支持js 函数

Release v0.2.4 AIDotNet/fast-wiki (github.com) 支持JS动态functioncall调用支持动态function管理支持JS在线编辑提供智能代码提示支持JS在线编辑提供部分绑定的c#类&#xff08;默认提供Console&#xff0c;HttpClient&#xff09;支持Application绑定多个Function Call优…

跨站请求伪造漏洞(CSRF)

什么是CSRF CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;也被称为 one-click attack 或者 session riding&#xff0c;即跨站请求伪造攻击。 漏洞原理 跨站请求伪造漏洞的原理主要是利用了网站对用户请求的验证不严谨。攻击者会在恶意网站中构造一个…

linux 文件提权|属性修改

文章目录 suid&#xff08;set uid&#xff09;添加文件属性查看文件属性i &#xff08;immutable&#xff09; umask suid&#xff08;set uid&#xff09; 让文件在执行的时候具有属主&#xff08;对应文件 user &#xff09;的权限 chmod 7744 temp.txt 第一位的7表示权限位…

探寻大数据思想的主要贡献者与核心内容

引言&#xff1a; 在当今数字化时代&#xff0c;大数据已成为企业和科学研究的关键要素。其背后的思想和概念不仅引领了数据处理和分析的革新&#xff0c;也推动了人类对于信息时代的理解与认知。 大数据思想的起源&#xff1a; 在信息爆炸的时代背景下&#xff0c;大数据思…

海外仓的出入库流程有什么痛点?位像素海外仓系统怎么提高出入库效率?

随着跨境电商的蓬勃发展&#xff0c;海外仓是其中不可或缺的一个关键环节。而货物的出库与入库则是海外仓管理中的一个核心业务流程&#xff0c;它的运作效率直接影响到整个跨境物流的效率和客户体验。今天&#xff0c;让我们具体来看一看关于海外仓出入库的流程&#xff0c;其…

150行Python代码模拟太阳系行星运转

今天我们用Python来模拟一下太阳系行星运动轨迹~ 先上成品图&#xff08;运行效果含音乐的呦&#xff09; 想要实现这样的效果并不难 准备材料 首先我们需要准备这样一些材料 宇宙背景图 背景透明的行星图 编写代码 代码分块详解 导入需要的模块 import pygame import …

深度学习理论基础(六)多头注意力机制的自定义及Pytoch库的使用详细代码

目录 1. Scaled Dot-Product Attention2. 多头注意力机制框图&#xff08;1&#xff09;计算公式&#xff08;2&#xff09;具体计算过程&#xff08;3&#xff09;具体代码 深度学习中的注意力机制&#xff08;Attention Mechanism&#xff09;是一种模仿人类视觉和认知系统的…

轻量应用服务器4核8G12M配置优惠价格646元一年零3个月,12M公网带宽

腾讯云轻量4核8G12M服务器优惠价格646元15个月&#xff0c;买一年送3个月&#xff0c;配置为轻量4核8G12M、180GB SSD盘、2000GB月流量、12M带宽&#xff0c;腾讯云优惠活动页面 yunfuwuqiba.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云4核8G服务器租用价格 腾讯云&…

SaaS模式Java版云HIS系统源码 覆盖医院所有业务的HIS信息管理系统源码

SaaS模式Java版云HIS系统源码 覆盖医院所有业务的HIS信息管理系统源码 HIS&#xff08;Hospital Information System&#xff09;是覆盖医院所有业务和业务全过程的信息管理系统。 HIS系统以财务信息、病人信息和物资信息为主线&#xff0c;通过对信息的收集、存储、传递、统…

Android 窗口那些事儿

目录 1. &#x1f4c2; 前言 你&#xff0c;是否有过这些疑问&#xff1f; 2. &#x1f531; Window 2.1 认识 Window 的几个阶段 1&#xff09;阶段一&#xff1a;Window 约等于 Activity 2&#xff09;阶段二&#xff1a;Window 约等于 View 3&#xff09;阶段三&…

list的使用

前言 我们前面已经对string和vector进行了学习使用&#xff0c;以及对他们的底层进行了模拟实现&#xff01;本期我们继续学习STL的另外一个容器---list。 本期内容介绍 什么是list&#xff1f; list的常用接口 什么是list? 还是来看看官方的文档说明&#xff01; 这里通过…

[蓝桥杯 2017 国 C] 合根植物

[蓝桥杯 2017 国 C] 合根植物 题目描述 w 星球的一个种植园&#xff0c;被分成 m n m \times n mn 个小格子&#xff08;东西方向 m m m 行&#xff0c;南北方向 n n n 列&#xff09;。每个格子里种了一株合根植物。 这种植物有个特点&#xff0c;它的根可能会沿着南北…

【MySQL】增删改查操作(基础)

文章目录 1、新增操作&#xff08;Create&#xff09;1.1单行数据全列插入1.2多行数据指定列插入 2、查询操作&#xff08;Retrieve&#xff09;2.1全列查询2.2指定列查询2.3指定列查询2.4别名&#xff08;as&#xff09;2.5去重&#xff08;distinct&#xff09;2.6排序&#…

数据结构—图

图的基本概念 图就是由顶点的有穷非空集合和顶点之间的边组成的集合。通常表示为&#xff1a;G(V,E)&#xff0c;其中&#xff0c;G 表示一个图&#xff0c;V 表示顶点的集合&#xff0c;E 表示边的集合。 顶点 图中的数据元素&#xff0c;我们称之为顶点&#xff0c;图至少有…

常见现代卷积神经网络(Pytorch 09)

本章将介绍现代的 卷积神经网络架构&#xff0c;许多现代卷积神经网络的研究都是建立在这一章的基础上的。在本章中的每一个模型都曾一度占据主导地位&#xff0c;其中许多模型都是 ImageNet竞赛 的优胜者。ImageNet竞赛自2010年以来&#xff0c;一直是计算机视觉中监督学习进展…

面试题——JVM老年代空间担保机制(我的想法)

这里借用一下人家的图&#xff0c;来说一下我的想法&#xff0c;嘻嘻。。。。 原文链接&#xff1a;一道面试题&#xff1a;JVM老年代空间担保机制-CSDN博客? 嗯&#xff0c;我觉得老年代担保机制的主要作用就是避免频繁触发FULL GC&#xff0c;这其实也是因为年轻代Minor GC…

Java项目:基于Springboot+vue社区医院管理系统设计与实现(源码+数据库+毕业论文)

一、项目简介 本项目是一套基于Springbootvue社区医院管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功能…

数据结构之顺序表的相关知识点及应用

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 目录 顺序表的概念及结构 顺序表的分类 顺序表的实现 在顺序表中增加数据 在顺序表中删除数据 在顺序表中查找数据 顺序表源码 顺序表的概念…