websocket的使用

1.引入依赖

java 复制代码
<dependency>

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

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

</dependency>

2.配置websocket服务

java 复制代码
@Configuration
public class WebSocketConfig {

    /**
     * 配置WebSocket服务
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

3.启动类添加注解

java 复制代码
@EnableWebSocket

4.websocket服务端逻辑

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * WebSocketServer服务端
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/{uid}")
public class WebSocketClient {
    /**
     * 静态变量,用来记录当前在线连接数,线程安全的类。
     */
    private static AtomicInteger onlineSessionClientCount = new AtomicInteger(0);
    /**
     * 存放所有在线的客户端
     */
    private static Map<String, Session> onlineSessionClientMap = new ConcurrentHashMap<>();

    /**
     * 连接uid和连接会话
     */
    private String uid;
    private Session session;


    /**
     * 连接建立成功调用的方法。由前端<code>new WebSocket</code>触发
     *
     * @param uid     每次页面建立连接时传入到服务端的id,比如用户id等。可以自定义。
     * @param session 与某个客户端的连接会话,需要通过它来给客户端发送消息
     */
    @OnOpen
    public void onOpen(@PathParam("uid") String uid, Session session) {
        /**
         * session.getId():当前session会话会自动生成一个id,从0开始累加的。
         */
        log.info("连接建立中 ==> session_id = {}, sid = {}", session.getId(), uid);
        //加入 Map中。将页面的uid和session绑定或者session.getId()与session
        //onlineSessionIdClientMap.put(session.getId(), session);
        onlineSessionClientMap.put(uid, session);
        //在线数加1
        onlineSessionClientCount.incrementAndGet();
        this.uid = uid;
        this.session = session;
        sendToOne(uid, "连接成功");
        log.info("连接建立成功,当前在线数为:{} ==> 开始监听新连接:session_id = {}, sid = {},。", onlineSessionClientCount, session.getId(), uid);
    }

    /**
     * 连接关闭调用的方法。由前端<code>socket.close()</code>触发
     *
     * @param uid
     * @param session
     */
    @OnClose
    public void onClose(@PathParam("uid") String uid, Session session) {
        //onlineSessionIdClientMap.remove(session.getId());
        // 从 Map中移除
        onlineSessionClientMap.remove(uid);

        //在线数减1
        onlineSessionClientCount.decrementAndGet();
        log.info("连接关闭成功,当前在线数为:{} ==> 关闭该连接信息:session_id = {}, sid = {},。", onlineSessionClientCount, session.getId(), uid);
    }

    /**
     * 收到客户端消息后调用的方法。由前端<code>socket.send</code>触发
     * * 当服务端执行toSession.getAsyncRemote().sendText(xxx)后,前端的socket.onmessage得到监听。
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        /**
         * html界面传递来得数据格式,可以自定义.
         * {"sid":"user-1","message":"hello websocket"}
         */
        log.info("接收到消息-----------------"+message);
        List<String> uids = session.getRequestParameterMap().get("uid");
        for (String uid : uids) {
            // 接收前端拖推送改的消息
            sendToOne(uid, "来自服务端的推送=====》你好前端! 我已经成功收到消息!消息数据为:" + message);
        }
    }

    /**
     * 发生错误调用的方法
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误,错误信息为:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 群发消息
     *
     * @param message 消息
     */
    public void sendToAll(String message) {
        // 遍历在线map集合
        onlineSessionClientMap.forEach((onlineSid, toSession) -> {
            // 排除掉自己
            if (!uid.equalsIgnoreCase(onlineSid)) {
                log.info("服务端给客户端群发消息 ==> sid = {}, toSid = {}, message = {}", uid, onlineSid, message);
                toSession.getAsyncRemote().sendText(message);
            }
        });
    }

    /**
     * 指定发送消息
     *
     * @param toUid
     * @param message
     */
    public boolean sendToOne(String toUid, String message) {
        /*
         * 判断发送者是否在线
         */
        Session toSession = onlineSessionClientMap.get(toUid);
        if (toSession == null) {
            log.error("服务端给客户端发送消息 ==> toSid = {} 不存在, message = {}", toUid, message);
            return false;
        }
        // 异步发送
        log.info("服务端给客户端发送消息 ==> toSid = {}, message = {}", toUid, message);
        toSession.getAsyncRemote().sendText(message);
        return true;
    }

}

5.service层调用推送消息方法

java 复制代码
@Service
public class WebSocketHandler {

    @Resource
    private WebSocketClient webSocketClient;

    public boolean sendMessageOne(String userId,String content) {
        boolean flag = webSocketClient.sendToOne(userId,content);
        return flag;
    }
}

6.controller层逻辑

java 复制代码
@PostMapping("/send")
    public Map push2(@RequestBody PushDTO pushDTO){
        Map map = new HashMap();
        //1、参数校验,非空~
        if(StringUtils.isEmpty(pushDTO.getMessage()) || pushDTO.getUserId() == null || pushDTO.getPushType() == null )    {
            log.info("【消息推送】 参数异常");
            map.put("code","-1");
            map.put("msg","参数异常");
            return map;
        }

        
        //2、推送消息
        boolean flag = webSocketHandler.sendMessageOne(pushMessage.getUserId() + "", content);
        //3、如果推送成功,修改状态,返回正确的JSON
        if(flag){
            PushMessage updatePushMessage = new PushMessage();
            updatePushMessage.setId(pushMessage.getId());
            updatePushMessage.setPushState(PUSH_SUCCESS);
//            pushMessageService.updateById(updatePushMessage);
            map.put("code","200");
            map.put("msg","成功");
            return map;
        }

        //4、返回用户未上线的JSON
        map.put("code","500");
        map.put("msg","用户离线");
        return map;

    }
相关推荐
fantasy_arch4 小时前
CPU性能优化-磁盘空间和解析时间
网络·性能优化
njnu@liyong5 小时前
图解HTTP-HTTP报文
网络协议·计算机网络·http
是Dream呀6 小时前
Python从0到100(七十八):神经网络--从0开始搭建全连接网络和CNN网络
网络·python·神经网络
kaixin_learn_qt_ing7 小时前
了解RPC
网络·网络协议·rpc
安全小王子8 小时前
Kali操作系统简单介绍
网络·web安全
Hacker_LaoYi9 小时前
【漏洞分析】DDOS攻防分析(四)——TCP篇
网络·tcp/ip·ddos
爱吃水果蝙蝠汤9 小时前
DATACOM-IP单播路由(BGP)-复习-实验
网络·网络协议·tcp/ip
Sun_12_210 小时前
SQL注入(SQL lnjection Base)21
网络·数据库
网络安全Jack10 小时前
网络安全概论——身份认证
网络·数据库·web安全