springboot项目中websocket入门示例

接上上一篇的springboot项目搭建(idea版)https://blog.csdn.net/qq516071744/article/details/86360166,本计划把两者写到一篇里面的,后来考虑到,篇幅有点大,而且,需要搭建springboot项目的也不一定同时就需要websocket;故又分开来写了;本人菜鸟一枚,写的过程中有什么不对的地方,还望大家不吝指教;再次先行谢过啦;下面进入我们的正题;

websocket是什么呢?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。

WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

以上是百度百科给对websocket的解析;其实,以我个人的理解来说,websocket的主要用武之地是全双工;他可以双向数据传送,可以替代服务器有消息需要通知客户端了,可以直接推送过去,而不必非得被动的等着客户端去请求;如果有客户端需要服务器端的一些信息,就只能通过,不断的请求服务器,比如前端编写定时任务;这样有两个弊端,一是太浪费资源,二是实时性也不好;如果使用websocket就可以解决这个问题。服务器端一有消息就立刻推送到客户端,既解决了资源的浪费问题,又解决了实时性的问题。

下面开始我们的示例:

步骤入下;

第一步:pom.xml添加依赖;

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-websocket</artifactId>
   <version>4.3.8.RELEASE</version>
</dependency>

第二步:启动类中添加bean;

@Bean
public ServerEndpointExporter serverEndpointExporter() {
   return new ServerEndpointExporter();
}

第三步:添加测试页面

将测试页面的代码放到static目录下方;

copy1.html

<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>springboot项目WebSocket测试demo</title>
</head>
<body>
<h3>springboot项目websocket测试demo</h3>
<h4>测试说明</h4>
<h5>文本框中数据数据,点击‘发送测试’,文本框中的数据会发送到后台websocket,后台接受到之后,会再推送数据到前端,展示在下方;点击关闭连接,可以关闭该websocket;可以跟踪代码,了解具体的流程;代码上有详细注解</h5>
<br />
<input id="text" type="text" />
<button onclick="send()">发送测试</button>
<hr />
<button onclick="clos()">关闭连接</button>
<hr />
<div id="message"></div>
<script>
    var websocket = null;
    if('WebSocket' in window){
        websocket = new WebSocket("ws://127.0.0.1:8888/demo/websocket/1");
    }else{
        alert("您的浏览器不支持websocket");
    }
    websocket.onerror = function(){
        setMessageInHtml("send error!");
    }
    websocket.onopen = function(){
        setMessageInHtml("connection success!")
    }
    websocket.onmessage  = function(event){
        setMessageInHtml(event.data);
    }
    websocket.onclose = function(){
        setMessageInHtml("closed websocket!")
    }
    window.onbeforeunload = function(){
        clos();
    }
    function setMessageInHtml(message){
        document.getElementById('message').innerHTML += message;
    }
    function clos(){
        websocket.close(3000,"强制关闭");
    }
    function send(){
        var msg = document.getElementById('text').value;
        websocket.send(msg);
    }
</script>
</body>
</html>

copy2.html

<html>
<head>
    <meta charset="UTF-8"></meta>
    <title>springboot项目WebSocket测试demo</title>
</head>
<body>
<h3>springboot项目websocket测试demo</h3>
<h4>测试说明</h4>
<h5>文本框中数据数据,点击‘发送测试’,文本框中的数据会发送到后台websocket,后台接受到之后,会再推送数据到前端,展示在下方;点击关闭连接,可以关闭该websocket;可以跟踪代码,了解具体的流程;代码上有详细注解</h5>
<br />
<input id="text" type="text" />
<button onclick="send()">发送测试</button>
<hr />
<button onclick="clos()">关闭连接</button>
<hr />
<div id="message"></div>
<script>
    var websocket = null;
    if('WebSocket' in window){
        websocket = new WebSocket("ws://127.0.0.1:8888/demo/websocket/2");
    }else{
        alert("您的浏览器不支持websocket");
    }
    websocket.onerror = function(){
        setMessageInHtml("send error!");
    }
    websocket.onopen = function(){
        setMessageInHtml("connection success!")
    }
    websocket.onmessage  = function(event){
        setMessageInHtml(event.data);
    }
    websocket.onclose = function(){
        setMessageInHtml("closed websocket!")
    }
    window.onbeforeunload = function(){
        clos();
    }
    function setMessageInHtml(message){
        document.getElementById('message').innerHTML += message;
    }
    function clos(){
        websocket.close(3000,"强制关闭");
    }
    function send(){
        var msg = document.getElementById('text').value;
        websocket.send(msg);
    }
</script>
</body>
</html>

第四步:添加websocket server类

WebSocket.java

package com.example.springboot_one.websocket;


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.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Auther: shigc
 * @Date: 2018/12/15 11:53
 * @Description: websocket
 */
@ServerEndpoint("/websocket/{pageCode}")
@Component
public class WebSocket {

    private static final String loggerName=WebSocket.class.getName();
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    public static Map<String, List<Session>> electricSocketMap = new ConcurrentHashMap<String, List<Session>>();

    /**
     * 连接建立成功调用的方法
     *
     * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam("pageCode") String pageCode, Session session) {
        List<Session> sessions = electricSocketMap.get(pageCode);
        if(null==sessions){
            List<Session> sessionList = new ArrayList<>();
            sessionList.add(session);
            electricSocketMap.put(pageCode,sessionList);
        }else{
            sessions.add(session);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("pageCode") String pageCode,Session session) {
        if (electricSocketMap.containsKey(pageCode)){
            electricSocketMap.get(pageCode).remove(session);
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("websocket received message:"+message);
        try {
            session.getBasicRemote().sendText("这是推送测试数据!您刚发送的消息是:"+message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");;
    }
}

第五步:测试websocket

启动服务;浏览器中输入;http://localhost:8888/demo/copy1.html

后台控制台输出如下信息:

注:其实,websocket的主要方法是:

一:这是server端向client端推送消息的方法;只要能获取到客户端的session,即可推送消息;

session.getBasicRemote().sendText("这是推送测试数据!您刚发送的消息是:"+message);

所以说,真正需要考虑的是,根据自己的实际业务情况,将client端连接过来的session,保存起来,比如保存到一个全局map中,或者是Redis缓存中等等;等需要给客户端推送消息的时候,可以找到对应需要推送的session,这个是重点;

猜你喜欢

转载自blog.csdn.net/qq516071744/article/details/86363040