Springboot集成WebSocket功能

      近期公司消息中心组件中想增加一个功能:后端能够向web前端发送消息,也就是我们所说的站内信,于是我们想到了WebSocket通信这一技术实现,实现步骤如下:

1.定义WebSocket配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
 * @Author: 
 * @Description: WebSocket配置
 * @Date: 2020/2/17
 **/
@Configuration
public class WebSocketConfig {

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

2.定义websocket服务器

import com.cjkj.message.push.util.StringUtils;
import com.cjkj.message.utils.WebSocketUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

/**
 * @Description: 向前端实时推送消息
 * @Date: 2020/2/17
 **/
@Component
@ServerEndpoint(value = "/websocket/{userKey}")
@Slf4j
public class WebSocketController {


    /**
     * @Description: 加入连接
     * @Param userKey: 用户标识
     * @Param session:
     * @Return:
     **/
    @OnOpen
    public void onOpen(@PathParam("userKey") String userKey, Session session) {
        log.info("[" + userKey + "]加入连接!");
        WebSocketUtil.addSession(userKey, session);
    }

    /**
     * @Description: 断开连接
     * @Param userKey: 用户标识
     * @Param session:
     * @Return:
     **/
    @OnClose
    public void onClose(@PathParam("userKey") String userKey, Session session) {
        log.info("[" + userKey + "]断开连接!");
        WebSocketUtil.remoteSession(userKey);
    }

    /**
     * @Description: 发送消息
     * @Param userKey: 用户标识
     * @Param message: 消息
     * @Return:
     **/
    @OnMessage
    public boolean OnMessage(@PathParam("userKey") String userKey, String message) {
        if(StringUtils.isEmpty(userKey) || StringUtils.isEmpty(message)){
            log.info("[参数userKey:{}, message:{}]", userKey, message);
            return false;
        }
        log.info("服务器对[{}]发送消息:{}", userKey, message);
        Session session = WebSocketUtil.ONLINE_SESSION.get(userKey);
        //发送普通信息
        return WebSocketUtil.sendMessage(session, message);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        log.error(session.getId() + "异常:", throwable);
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        throwable.printStackTrace();
    }
}

3.定义推送功能

import com.cjkj.common.model.ResultData;
import com.cjkj.message.dto.req.WebSocketMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description: 向前端推送消息
 * @Date: 2020/2/17
 **/
@RestController
@RequestMapping("/socket")
public class WebSocketPushController {

    @Autowired
    private WebSocketController webSocketController;

    /**
     * @Description:
     * @Param appNo: 用户标识
     * @Param message: 发送的信息
     * @Return:
     **/
    @PostMapping("/push")
    public ResultData pushToWeb(@RequestBody WebSocketMsg webSocketMsg) {
        webSocketController.OnMessage(webSocketMsg.getUserKey(), webSocketMsg.getMessage());
        return ResultData.ok();
    }
}

4.websocket消息发送工具类

import lombok.extern.slf4j.Slf4j;
import javax.websocket.RemoteEndpoint.Async;
import javax.websocket.Session;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;

/**
 * @Description:
 * @Date: 2019/7/16
 **/
@Slf4j
public class WebSocketUtil {

    /**
     * @Description: 使用map进行存储在线的session
     **/
    public static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<>();

    /**
     * @Description: 添加Session
     * @Param userKey:
     * @Param session:
     * @Return:
     **/
    public static void addSession(String userKey, Session session) {
        ONLINE_SESSION.put(userKey, session);
    }

    public static void remoteSession(String userKey) {
        ONLINE_SESSION.remove(userKey);
    }

    /**
     * @Description: 向某个用户发送消息
     * @Param session:
     * @Param message:
     * @Return:
     **/
    public static Boolean sendMessage(Session session, String message) {
        if (session == null) {
            return false;
        }
        // getAsyncRemote()和getBasicRemote()异步与同步
        Async async = session.getAsyncRemote();
        //发送消息
        Future<Void> future = async.sendText(message);
        boolean done = future.isDone();
        log.info("服务器发送消息给客户端[{}]的消息:{},状态为:{}", session.getId(), message, done);
        return done;

    }
}

5.测试

使用第三方工具连接:http://www.websocket-test.com/ 模拟前端

 5.1 连接后端Websocket服务器请求地址:ws://ip:端口/websocket/用户唯一标识

 5.2 调用推送接口向前端推送消息

5.3 Websocket连接成功后前端会收到后端推送过来的消息

猜你喜欢

转载自blog.csdn.net/weixin_39352976/article/details/104510139
今日推荐