Java版WebSocket消息推送系统搭建

Java版WebSocket消息推送系统搭建

        最近在做消息推送,网上查了一些资料,开始想的是用MQ来做,后面发现用WebSocket来做的话感觉应该要简单点,话不多说,准备撸代码。


后端核心代码



/**
 * 监听器类:主要任务是用ServletRequest将我们的HttpSession携带过去
 * @author Monkey
 * @date 2020-05-23
 */
@Component
public class RequestListener implements ServletRequestListener {
  @Override
  public void requestInitialized(ServletRequestEvent sre) {
    //将所有request请求都携带上httpSession
      HttpSession httpSession= ((HttpServletRequest) sre.getServletRequest()).getSession();
      String uid = sre.getServletRequest().getParameter("uid");
      if (!StringUtils.isEmpty(uid)) {
          httpSession.setAttribute("uid", uid);
          SysContent.setUserLocal(uid);
      }

  }
/**
 * Type: WebSocketConfig
 * Description: WebSocket配置类
 * @author Monkey
 * @date 2020-05-23
 */
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
  
}

/**
 * Type: WebSocketServer
 * Description: WebSocketServer,实现服务器客户端平等交流,达到服务器可以主动向客户端发送消息
 *
 * @author Monkey
 * @date 2020-05-23
 */
@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {
	
	//日志记录器
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);
	
    //高效,弱一致性,放的是WebSocketServer而非session是为了复用自身的方法
    private static transient volatile Set webSocketSet = ConcurrentHashMap.newKeySet();

    private static transient volatile Set tempWebSocketSet = ConcurrentHashMap.newKeySet();
 
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    private static transient ConcurrentHashMap map = new ConcurrentHashMap();
 
    /**
     * Title: sendInfo
     * Description: 群发消息
     * @param message
     */
    public static void sendInfo(String message, String sid) throws IOException {
    	LOGGER.info("webSocket-sendInfo群发消息:" + message);
        RecordLogUtil.info("在线人数:" + getOnlineCount());
        if (!StringUtils.isEmpty(sid)) {
            Set> entries = map.entrySet();
            for(Map.Entry m : entries){
                if (m.getKey().equals(sid)) {
                    Session s2 = m.getValue();
                    webSocketSet.forEach(ws -> {
                        if (ws.session.getId() == s2.getId()) {
                            ws.sendMessage(message);
                            return;
                        }
                    });
                    map.remove(m);
                    break;
                }
            }
        } else {
            tempWebSocketSet = ConcurrentHashMap.newKeySet();
            for (Map.Entry m : map.entrySet()) {
                Session s2 = m.getValue();
                webSocketSet.forEach(ws -> {
                    if (ws.session.getId() == s2.getId()) {
                        ws.sendMessage(message);
                        tempWebSocketSet.add(ws);
                        return;
                    }
                });
            }
            //过滤完已经挂断的session
            webSocketSet = tempWebSocketSet;
        }

    }
 
    /**
     * Title: getOnlineCount
     * Description: 获取连接数
     * @return
     */
    public static int getOnlineCount() {
        return map.size();
    }
    /* *********************以下为非static方法************************** */
    /**
     * Title: sendMessage
     * Description: 向客户端发送消息
     * @param message
     * @throws IOException
     */
    public boolean sendMessage(String message) {
        try {
			this.session.getBasicRemote().sendText(message);
			return true;
		} catch (IOException error) {
			LOGGER.error("webSocket-sendMessage发生错误:" + error.getClass() + error.getMessage());
			return false;
		}
    }
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session) throws IOException {
        String uid = SysContent.getUserLocal();
        RecordLogUtil.info("uid=" + uid);
        this.session = session;
        if (StringUtils.isEmpty(uid)){
            sendMessage("连接失败");
            session.close();
            return;
        } else {
            map.put(uid, this.session);
            webSocketSet.add(this);     //加入set中
            sendMessage("连接成功-" + uid);
            RecordLogUtil.info("当前在线人数: " + getOnlineCount());
        }
    }
 
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        //这里要删除map里面对象
        for(Map.Entry m : map.entrySet()){
            if (m.getValue() == this.session) {
                map.remove(m);
                RecordLogUtil.info("用户" + m.getKey() + "已关闭连接!");
                break;
            }
        }
        RecordLogUtil.info("在线人数:" + getOnlineCount() + ", 关联在线人数:" + map.size());
    }
 
    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
    	LOGGER.info("来自客户端(" + session.getId() + ")的消息:" + message);
    	sendMessage("Hello, nice to hear you! There are " + webSocketSet.size() + " users like you in total here!");
    }
 
	/**
	 * Title: onError
	 * Description: 发生错误时候回调函数
	 * @param session
	 * @param error
	 */
    @OnError
    public void onError(Session session, Throwable error) {
        LOGGER.error("webSocket发生错误:" + error.getClass() + error.getMessage());
    }
 
    @Override
    public int hashCode() {
    	return super.hashCode();
    }
    
    @Override
    public boolean equals(Object obj) {
    	return super.equals(obj);
    }
}

/**
 * 监听器类:主要任务是用ServletRequest将我们的HttpSession携带过去
 * @author Monkey
 * @date 2020-05-23
 */
public class SysContent {
    private static ThreadLocal requestLocal = new ThreadLocal();
    private static ThreadLocal responseLocal = new ThreadLocal();
    private static ThreadLocal userLocal = new ThreadLocal();

    public static String getUserLocal() {
        return userLocal.get();
    }

    public static void setUserLocal(String userLocal) {
        SysContent.userLocal.set(userLocal);
    }

    public static HttpServletRequest getRequest() {
        return (HttpServletRequest) requestLocal.get();
    }

    public static void setRequest(HttpServletRequest request) {
        requestLocal.set(request);
    }

    public static HttpServletResponse getResponse() {
        return (HttpServletResponse) responseLocal.get();
    }

    public static void setResponse(HttpServletResponse response) {
        responseLocal.set(response);
    }

    public static HttpSession getSession() {
        return (HttpSession) ((HttpServletRequest) requestLocal.get()).getSession();
    }
}

前端代码





    WebSocket测试
    
    
    



socketTest


前端示意图


Java版WebSocket消息推送系统搭建_第1张图片 


demo 测试代码已经上传到csdn,喜欢的话可以前往下载。

https://download.csdn.net/download/lj88811498/12453985

你可能感兴趣的:(技术分享)