Springboot整合WebSocket实现浏览器和服务器交互

Websocket定义

代码实现

引入maven依赖

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>

配置类

  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.web.socket.server.standard.ServerEndpointExporter;
  
  /**
   * WebSocket配置类
   */
  @Configuration
  public class WebSocketConfig {
  
      @Bean
      public ServerEndpointExporter serverEndpointExporter() {
          return new ServerEndpointExporter();
      }
  
  }

WebSocketServer 服务端

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.hc.dialer_server.service.SendMessageService;
import com.hc.dialer_server.utils.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.DependsOn;
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.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * WebSocket的操作类
 */
@Component
@Slf4j
@ServerEndpoint("/websocket/{number}")
@DependsOn("springContext")
public class WebSocketServer {

    SendMessageService sendMessageServiceImpl = SpringContextUtils.getBean("sendMessageServiceImpl");

    // 记录当前在线连接数
    private static AtomicInteger onlineSessionClientCount = new AtomicInteger(0);

    // 记录number和 session的对应关系
    public static Map<String, Session> connectionMap = new ConcurrentHashMap<>();

    private String number;


    @OnOpen
    public void onOpen(@PathParam("number") String number, Session session) throws IOException {
        log.info("连接建立中 ==> session_id = {}, number = {}", session.getId(), number);
        // 在线人数+1
        onlineSessionClientCount.incrementAndGet();
        this.number = number;

        connectionMap.put(number, session);
        session.getBasicRemote().sendText("连接建立成功");
        log.info("连接建立成功, 当前在线数为: {}, session_id = {}, number = {}", onlineSessionClientCount, session.getId(), number);
    }


    @OnClose
    public void onClose(@PathParam("number") String number, Session session) {
        connectionMap.remove(number);
        onlineSessionClientCount.decrementAndGet();
        log.info("连接关闭成功, 当前在线数为: {} ==> 关闭该连接信息: session_id = {}, number = {}", onlineSessionClientCount, session.getId(), number);
    }


    @OnMessage
    public void onMessage(String message, Session session) throws Exception {
        if (StringUtils.isBlank(message)) {
            return;
        }
        JSONObject jsonObject = JSON.parseObject(message);
        String eventType = jsonObject.getString("eventType");
        String msg = jsonObject.getString("message");
        log.info("服务端收到客户端消息 ==> number = {}, eventType = {}, message = {}", number, eventType, msg);
        session.getBasicRemote().sendText("服务端给客户端发送消息");
    }


    @OnDisconnect
    public void onDisconnect(Session session) {
        connectionMap.remove(number);
        onlineSessionClientCount.decrementAndGet();
        log.info("disconnect event ==> number: {}, session_id: {}, 当前在线数: {}", number, session.getId(), onlineSessionClientCount);
    }


    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误, session id = {}, 错误信息为:{}", session.getId(), error.getMessage());
    }

}

工具类


import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component("springContext")
public class SpringContextUtils implements ApplicationContextAware {
    /**
     * Spring应用上下文环境
     */
    private static ApplicationContext applicationContext;

    /**
     * 获取对象
     *
     * @return Object 一个以所给名字注册的bean的实例
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        return (T) applicationContext.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     */
    public static <T> T getBean(Class<T> clz) {
        return applicationContext.getBean(clz);
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @return boolean
     */
    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @return boolean
     */
    public static boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }

    /**
     * @return Class 注册对象的类型
     */
    public static Class<?> getType(String name) {
        return applicationContext.getType(name);
    }


    @Override
    public synchronized void setApplicationContext(ApplicationContext applicationContext) {
        if (SpringContextUtils.applicationContext == null) {
            SpringContextUtils.applicationContext = applicationContext;
        }
    }
}

前端

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>测试webSocket</title>
</head>
<body>
Client传来的number:
<!--<input type="text" th:value="${number}" id="number"/>-->
<p>【eventType】:
<div><input id="toUserId" name="toUserId" type="text" value="message"></div>
<p>【messageText】:
<div><input id="contentText" name="contentText" type="text" value="hello websocket"></div>
<p>【操作】:
<div>
    <button type="button" onclick="sendMessage()">发送消息</button>
    <button type="button" onclick="sendMessage1()">1626</button>

</div>
</body>

<script type="text/javascript">
    var socket;
    if (typeof (WebSocket) == "undefined") {
        console.log("您的浏览器不支持WebSocket");
    } else {
        console.log("您的浏览器支持WebSocket");
        //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接

        var number = '1626';
        console.log("number-->" + number);
        // socket服务器端的ip和端口
        var reqUrl = "http://localhost:8080/websocket/" + number;
        socket = new WebSocket(reqUrl.replace("http", "ws"));
        //打开事件
        socket.onopen = function () {
            console.log("Socket 已打开");
            //socket.send("这是来自客户端的消息" + location.href + new Date());
        };
        //获得消息事件
        socket.onmessage = function (msg) {
            console.log("onmessage--" + msg.data);
            //发现消息进入,开始处理前端触发逻辑
        };
        //关闭事件
        socket.onclose = function () {
            console.log("Socket已关闭");
        };
        //发生了错误事件
        socket.onerror = function () {
            alert("Socket发生了错误");
            //此时可以尝试刷新页面
        }
    }

    function sendMessage() {
        if (typeof (WebSocket) == "undefined") {
            console.log("您的浏览器不支持WebSocket");
        } else {
            // console.log("您的浏览器支持WebSocket");
            var toUserId = document.getElementById('toUserId').value;
            var contentText = document.getElementById('contentText').value;
            var msg = '{"eventType":"' + toUserId + '","message":"' + contentText + '"}';
            console.log(msg);
            socket.send(msg);
        }
    }

    //发送json串
    function sendMessage1() {
        if (typeof (WebSocket) == "undefined") {
            console.log("您的浏览器不支持WebSocket");
        } else {
            // console.log("您的浏览器支持WebSocket");
            var toUserId = document.getElementById('toUserId').value;
            var contentText = document.getElementById('contentText').value;
            // var msg = '{"eventType":"' + toUserId + '","message":"' + contentText + '"}';

            var msg = '{"eventType":"' + toUserId + '","message":{"number":"1626","serviceNumber":"60600","req":"event01"}}';
            console.log(msg);
            socket.send(msg);
        }
    }

    
</script>
</html>

测试

Springboot整合WebSocket实现浏览器和服务器交互_第1张图片

你可能感兴趣的:(spring,boot,websocket,服务器)