SpringBoot 使用WebSocket详解

1、导入websocket包

      <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-websocketartifactId>
        <version>2.2.13.RELEASEversion>
      dependency>

2、配置类

package com.ruoyi.websocket.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig  {
    /**
     * 会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     * 要注意,如果使用独立的servlet容器,
     * 而不是直接使用springboot的内置容器,
     * 就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3、常量类

package com.ruoyi.websocket.constant;
/**
 * 常量类
 */
public class WsConstant {
    public static final String CARDINFO="cardInfo";
    public static final String IMGINFO="imgInfo";
}

4、Websocket工具类,记录当前在线的链接对链接进行操作

package com.ruoyi.websocket.utils;

import com.alibaba.fastjson.JSON;
import com.ruoyi.common.core.domain.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Websocket工具类
 * 记录当前在线的链接对链接进行操作
 */
public class WebsocketUtil {
    /**
     * 日志信息
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketUtil.class);
    /**
     * 记录当前在线的Session
     */
    private static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<>();
    public static final String sessionKey = "deviceId";

    /**
     * 添加session
     *
     * @param userId
     * @param session
     */
    public static void addSession(String userId, Session session) {
        // 此处只允许一个用户的session链接。一个用户的多个连接,我们视为无效。
        ONLINE_SESSION.putIfAbsent(userId, session);
    }

    /**
     * 关闭session
     *
     * @param userId
     */
    public static void removeSession(String userId) {
        ONLINE_SESSION.remove(userId);
    }

    /**
     * 给单个用户推送消息
     *
     * @param session
     * @param message
     */
    public static void sendMessage(Session session, String message) {
        if (session == null) {
            return;
        }

        // 同步
        RemoteEndpoint.Async async = session.getAsyncRemote();
        async.sendText(message);
    }

    /**
     * 向所有在线人发送消息
     *
     * @param message
     */
    public static void sendMessageForAll(String message) {
        //jdk8 新方法
        ONLINE_SESSION.forEach((sessionId, session) -> {
            if (session.isOpen()) {
                sendMessage(session, message);
            }
        });
    }

    /**
     * 根据用户ID发送消息
     *
     * @param result
     */
    public static void sendMessage(String sessionId, AjaxResult result) {
        sendMessage(sessionId, JSON.toJSONString(result));
    }

    /**
     * 根据用户ID发送消息
     *
     * @param message
     */
    public static void sendMessage(String sessionId, String message) {
        Session session = ONLINE_SESSION.get(sessionId);
        //判断是否存在该用户的session,判断是否还在线
        if (session == null || !session.isOpen()) {
            return;
        }
        sendMessage(session, message);
    }

    /**
     * 根据ID获取Session
     *
     * @param sessionId
     */
    public static Session getSession(String sessionId) {
        Session session = ONLINE_SESSION.get(sessionId);
        return session;
    }

    /**
     * 根据传过来的key获取session中的参数
     * @param key
     * @param session
     * @return
     */
    public static String getParam(String key, Session session) {
        Map map = session.getRequestParameterMap();
        Object userId1 = map.get(key);
        if (userId1 == null) {
            return null;
        }

        String s = userId1.toString();
        s = s.replaceAll("\\[", "").replaceAll("]", "");

        if (!StringUtils.isEmpty(s)) {
            return s;
        }
        return null;
    }

}
package com.ruoyi.common.core.domain;

import java.util.HashMap;
import com.ruoyi.common.utils.StringUtils;

/**
 * 操作消息提醒
 *
 * @author ruoyi
 */
public class AjaxResult extends HashMap<String, Object>
{
    private static final long serialVersionUID = 1L;

    /** 状态码 */
    public static final String CODE_TAG = "code";

    /** 返回内容 */
    public static final String MSG_TAG = "msg";

    /** 数据对象 */
    public static final String DATA_TAG = "data";

    /**
     * 状态类型
     */
    public enum Type
    {
        /** 成功 */
        SUCCESS(0),
        /** 警告 */
        WARN(301),
        /** 错误 */
        ERROR(500);
        private final int value;

        Type(int value)
        {
            this.value = value;
        }

        public int value()
        {
            return this.value;
        }
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
     */
    public AjaxResult()
    {
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param type 状态类型
     * @param msg 返回内容
     */
    public AjaxResult(Type type, String msg)
    {
        super.put(CODE_TAG, type.value);
        super.put(MSG_TAG, msg);
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param type 状态类型
     * @param msg 返回内容
     * @param data 数据对象
     */
    public AjaxResult(Type type, String msg, Object data)
    {
        super.put(CODE_TAG, type.value);
        super.put(MSG_TAG, msg);
        if (StringUtils.isNotNull(data))
        {
            super.put(DATA_TAG, data);
        }
    }

    /**
     * 方便链式调用
     *
     * @param key 键
     * @param value 值
     * @return 数据对象
     */
    @Override
    public AjaxResult put(String key, Object value)
    {
        super.put(key, value);
        return this;
    }

    /**
     * 返回成功消息
     *
     * @return 成功消息
     */
    public static AjaxResult success()
    {
        return AjaxResult.success("操作成功");
    }

    /**
     * 返回成功数据
     *
     * @return 成功消息
     */
    public static AjaxResult success(Object data)
    {
        return AjaxResult.success("操作成功", data);
    }

    /**
     * 返回成功消息
     *
     * @param msg 返回内容
     * @return 成功消息
     */
    public static AjaxResult success(String msg)
    {
        return AjaxResult.success(msg, null);
    }

    /**
     * 返回成功消息
     *
     * @param msg 返回内容
     * @param data 数据对象
     * @return 成功消息
     */
    public static AjaxResult success(String msg, Object data)
    {
        return new AjaxResult(Type.SUCCESS, msg, data);
    }

    /**
     * 返回警告消息
     *
     * @param msg 返回内容
     * @return 警告消息
     */
    public static AjaxResult warn(String msg)
    {
        return AjaxResult.warn(msg, null);
    }

    /**
     * 返回警告消息
     *
     * @param msg 返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static AjaxResult warn(String msg, Object data)
    {
        return new AjaxResult(Type.WARN, msg, data);
    }

    /**
     * 返回错误消息
     *
     * @return
     */
    public static AjaxResult error()
    {
        return AjaxResult.error("操作失败");
    }

    /**
     * 返回错误消息
     *
     * @param msg 返回内容
     * @return 警告消息
     */
    public static AjaxResult error(String msg)
    {
        return AjaxResult.error(msg, null);
    }

    /**
     * 返回错误消息
     *
     * @param msg 返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static AjaxResult error(String msg, Object data)
    {
        return new AjaxResult(Type.ERROR, msg, data);
    }
}

5、控制类

package com.ruoyi.websocket.wscontroller;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.netty.manager.DeviceChannelContext;
import com.ruoyi.netty.netty.factory.ChannelFactory;
import com.ruoyi.websocket.utils.WebsocketUtil;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;

@Component
@ServerEndpoint(value = "/verifyDevice")
public class FaceVerifyController {

    /**
     * 连接事件,加入注解
     *
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        String deviceId = WebsocketUtil.getParam(WebsocketUtil.sessionKey, session);
        // 添加到session的映射关系中
        WebsocketUtil.addSession(deviceId, session);
        //获取链接的设备信息
        DeviceChannelContext deviceChannelContext = ChannelFactory.getChannelBySerialNo(deviceId);
        //判断是否存在人脸验证设备与服务器 socket的链接
        if (deviceChannelContext != null && (!deviceChannelContext.getCtx().isRemoved())) {
            //已连接
            WebsocketUtil.sendMessage(deviceId, AjaxResult.success("ok"));
        } else {
            //未连接
            WebsocketUtil.sendMessage(deviceId, AjaxResult.success("no"));
        }
    }

    /**
     * 连接事件,加入注解
     * 用户断开链接
     *
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        String deviceId = WebsocketUtil.getParam(WebsocketUtil.sessionKey, session);
        // 删除映射关系
        WebsocketUtil.removeSession(deviceId);
    }

    /**
     * 当接收到用户上传的消息
     *
     * @param session
     */
    @OnMessage
    public void onMessage(Session session, String message) {
        System.out.println(message);
//        Map map = session.getRequestParameterMap();
//        String userId = map.get(WebsocketUtil.sessionKey) == null ? null : map.get(WebsocketUtil.sessionKey).toString();
    }

    /**
     * 处理用户活连接异常
     *
     * @param session
     * @param throwable
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        try {
            if (session.isOpen()) {
                session.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        throwable.printStackTrace();
    }
}

6、前端js页面

	var url = "ws://" + window.location.host + "/verifyDevice?deviceId=" + facedeviceCode;
    //建立webSocket连接
    websocket = new WebSocket(url);
    //打开webSokcet连接时,回调该函数
    websocket.onopen = () => console.log("连接建立");

    //关闭webSocket连接时,回调该函数
    websocket.onclose = () => console.log("连接关闭");
    //接收信息
    websocket.onmessage = function (res) {
        var obj = eval('(' + res.data + ')');
        //显示身份证信息和图片
        if (obj && obj.msg == "cardInfo") {
            console.info("调用discernToInfo方法");
            discernToInfo(obj);
        }
        //只显示图片
        else if (obj && obj.msg == "imgInfo") {
            console.info("调用imgToInfo方法");
            imgToInfo(obj);
        }
    }

求关注~~~

点关注不迷路,喜欢的朋友们关注支持一下
给点继续写的动力,感谢!!

你可能感兴趣的:(Java,websocket,spring,boot,java)