定制开发springboot整合webSocket(看完即入门)

webSocket

1、什么是webSocket?

WebSocket定制开发是一种在单个TCP定制开发连接上进行全双工通信的协议。WebSocket定制开发使得客户端和服务器之定制开发间的数据交换变得更加简单,定制开发允许服务端主动向客户定制开发端推送数据。在WebSocket 中,定制开发浏览器和服务器只需要定制开发完成一次握手,定制开发两者之间就直接可以定制开发创建持久性的连接,并进行双向数据传输

2、webSocket可以用来做什么?

利用双向数据传输的特点可以用来完成很多功能,不需要前端轮询,浪费资源。例如:

1、通告功能
2、聊天功能 (如下是逻辑图)

3、实时更新数据功能
4、弹幕
等等。。。。。。

3、webSocket协议

本协议有两部分:握手和数据传输。
握手是基于http协议的。

来自客户端的握手看起来像如下形式:

GET ws://localhost/chat HTTP/1.1Host: localhostUpgrade: websocketConnection: UpgradeSec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==Sec-WebSocket-Protocol: chat,superchatSec-WebSocket-Version: 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

来自服务器的握手看起来像如下形式:

HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=Sec-WebSocket-Protocol: chat
  • 1
  • 2
  • 3
  • 4
  • 5

4、服务端

maven依赖

   <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-websocket</artifactId>  </dependency>
  • 1
  • 2
  • 3
  • 4

WebSocket配置类

mport org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configurationpublic class WebSocketConfig {    /**     * 	注入ServerEndpointExporter,     * 	这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint     */    @Bean    public ServerEndpointExporter serverEndpointExporter() {        return new ServerEndpointExporter();    }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

WebSocket操作类

通过该类WebSocket可以进行群推送以及单点推送

import java.util.HashMap;import java.util.Map;import java.util.concurrent.CopyOnWriteArraySet;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 org.springframework.stereotype.Component;import lombok.extern.slf4j.Slf4j;@Component@Slf4j@ServerEndpoint("/websocket/{userId}")  // 接口路径 ws://localhost:8087/webSocket/userId;public class WebSocket {        //与某个客户端的连接会话,需要通过它来给客户端发送数据    private Session session;        /**     * 用户ID     */    private String userId;        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。    //虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。    //  注:底下WebSocket是当前类名    private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();    // 用来存在线连接用户信息    private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>();        /**     * 链接成功调用的方法     */    @OnOpen    public void onOpen(Session session, @PathParam(value="userId")String userId) {        try {			this.session = session;			this.userId = userId;			webSockets.add(this);			sessionPool.put(userId, session);			log.info("【websocket消息】有新的连接,总数为:"+webSockets.size());		} catch (Exception e) {		}    }        /**     * 链接关闭调用的方法     */    @OnClose    public void onClose() {        try {			webSockets.remove(this);			sessionPool.remove(this.userId);			log.info("【websocket消息】连接断开,总数为:"+webSockets.size());		} catch (Exception e) {		}    }    /**     * 收到客户端消息后调用的方法     *     * @param message     * @param session     */    @OnMessage    public void onMessage(String message) {    	log.info("【websocket消息】收到客户端消息:"+message);    }    	  /** 发送错误时的处理     * @param session     * @param error     */    @OnError    public void onError(Session session, Throwable error) {        log.error("用户错误,原因:"+error.getMessage());        error.printStackTrace();    }        // 此为广播消息    public void sendAllMessage(String message) {    	log.info("【websocket消息】广播消息:"+message);        for(WebSocket webSocket : webSockets) {            try {            	if(webSocket.session.isOpen()) {            		webSocket.session.getAsyncRemote().sendText(message);            	}            } catch (Exception e) {                e.printStackTrace();            }        }    }        // 此为单点消息    public void sendOneMessage(String userId, String message) {        Session session = sessionPool.get(userId);        if (session != null&&session.isOpen()) {            try {            	log.info("【websocket消息】 单点消息:"+message);                session.getAsyncRemote().sendText(message);            } catch (Exception e) {                e.printStackTrace();            }        }    }        // 此为单点消息(多人)    public void sendMoreMessage(String[] userIds, String message) {    	for(String userId:userIds) {    		Session session = sessionPool.get(userId);            if (session != null&&session.isOpen()) {                try {                	log.info("【websocket消息】 单点消息:"+message);                    session.getAsyncRemote().sendText(message);                } catch (Exception e) {                    e.printStackTrace();                }            }    	}            }    }
  • 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
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130

方法调用示例

注入我们的操作类

@Resourceprivate WebSocket webSocket;
  • 1
  • 2

发送消息给前端

//创建业务消息信息JSONObject obj = new JSONObject();obj.put("cmd", "topic");//业务类型obj.put("msgId", sysAnnouncement.getId());//消息idobj.put("msgTxt", sysAnnouncement.getTitile());//消息内容//全体发送webSocket.sendAllMessage(obj.toJSONString());		//单个用户发送 (userId为用户id)webSocket.sendOneMessage(userId, obj.toJSONString());		//多个用户发送 (userIds为多个用户id,逗号‘,’分隔)webSocket.sendMoreMessage(userIds, obj.toJSONString());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

5、客户端

前端中VUE使用WebSocket

<script>    import store from '@/store/'    export default {        data() {            return {            }        },        mounted() {               //初始化websocket              this.initWebSocket()        },        destroyed: function () { // 离开页面生命周期函数              this.websocketclose();        },        methods: {            initWebSocket: function () { // 建立连接                // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https                var userId = store.getters.userInfo.id;                var url = window._CONFIG['domianURL'].replace("https://","wss://").replace("http://","ws://")+"/websocket/"+userId;                this.websock = new WebSocket(url);                this.websock.onopen = this.websocketonopen;                this.websock.send = this.websocketsend;                this.websock.onerror = this.websocketonerror;                this.websock.onmessage = this.websocketonmessage;                this.websock.onclose = this.websocketclose;              },              // 连接成功后调用              websocketonopen: function () {                console.log("WebSocket连接成功");              },              // 发生错误时调用              websocketonerror: function (e) {                console.log("WebSocket连接发生错误");              },              // 给后端发消息时调用              websocketsend: function (e) {                console.log("WebSocket连接发生错误");              },							// 接收后端消息              // vue 客户端根据返回的cmd类型处理不同的业务响应              websocketonmessage: function (e) {                var data = eval("(" + e.data + ")");                  //处理订阅信息                if(data.cmd == "topic"){                   //TODO 系统通知                             }else if(data.cmd == "user"){                   //TODO 用户消息                        }              },              // 关闭连接时调用              websocketclose: function (e) {                console.log("connection closed (" + e.code + ")");              }        }    }</script>
  • 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

接口调用顺序,进来页面 : 先建立连接–》调用websocketonopen方法,链接成功调用的方法
websocketonmessage方法为接收后端时处理。
当我们要发送消息给后端时调用websocketsend。
当我们要关闭连接时调用websocketclose。
当发现错误时调用websocketonerror。

浏览器查看日志:
朝上的绿色箭头是发出去的消息
朝下的红色箭头是收到的消息

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发