spring boot 整合websocket 实现用户上线发送未收到通知,用户为在线缓存消息

一、导入依赖

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

二、新建websocket配置

import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.session.StandardSessionFacade;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

/**
 * @author 736421789@qq.com
 * @date 2020/1/23 12:19
 */

@Component
@Slf4j
public class WebSocketConfig extends ServerEndpointConfig.Configurator{

    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        StandardSessionFacade ssf = (StandardSessionFacade) request.getHttpSession();
        if (ssf != null) {
            HttpSession httpSession = (HttpSession) request.getHttpSession();
            //关键操作
            sec.getUserProperties().put("sessionId", httpSession.getId());
            log.info("获取到的SessionID:" + httpSession.getId());
        }
        super.modifyHandshake(sec, request, response);

    }

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

三、新建websocket配置类,由于还没有想好吧消息存储到其他地方,暂时用map存储,后续想到办法会更新

import cn.suse.edu.wasterecovery.utils.BasesUtil;
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.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
 * @author 736421789@qq.com
 * @date 2020/1/23 12:21
 */

@Component
@ServerEndpoint("/webSocket/{username}")
@Slf4j
public class WebSocket {
    /**
     * 在线人数
     */
    public static int onlineNumber = 0;

    /**
     * 以用户的姓名为key,WebSocket为对象保存起来
     */
    private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
    /**
     * 设置为静态的 公用一个消息map ConcurrentMap为线程安全的map  HashMap不安全
     */
    private static ConcurrentMap<String, List<Map>> messageMap=new ConcurrentHashMap<>();

    /**
     * 会话
     */
    private Session session;
    /**
     * 用户名称
     */
    private String username;
    /**
     * 建立连接
     *
     * @param session
     */
    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session) throws IOException, InterruptedException {
        onlineNumber++;
        log.info("现在来连接的客户id:"+session.getId()+"用户名:"+username);
        this.username = username;
        this.session = session;
        clients.put(username, this);
        log.info("有新连接加入! 当前在线人数" + onlineNumber);
        log.info("存储的列队消息:{}",messageMap);
        List<Map> userMessage = messageMap.get(username);
        if(!BasesUtil.isEmpty(userMessage)){
            for (int i = userMessage.size() - 1; i >= 0; i--) {
                Map messages =userMessage.get(i);
                String o = (String) messages.get(username);
                sendMessageTo(o,username);
                Thread.sleep(10000);
            }
            messageMap.remove(username);
            }
    }


    @OnError
    public void onError(Session session, Throwable error) {
        log.info("服务端发生了错误"+error.getMessage());
        error.printStackTrace();
    }
    /**
     * 连接关闭
     */
    @OnClose
    public void onClose()
    {
        onlineNumber--;
        clients.remove(username);
        log.info("{}连接关闭! 当前在线人数{}",username, onlineNumber);
    }

    /**
     * 收到客户端的消息
     *
     * @param message 消息
     * @param session 会话
     */
    @OnMessage
    public void onMessage(String message, Session session)
    {
            log.info("来自客户端消息:" + message+"客户端的id是:"+session.getId());

    }


    public void sendMessageTo(String message, String ToUserName) throws IOException {
        for (WebSocket item : clients.values()) {
            if (item.username.equals(ToUserName) ) {
                item.session.getAsyncRemote().sendText(message);
                return;
            }else {
                List<Map> objects=new ArrayList<>();
                Map<String,String> amp=new HashMap<>();
                if(!BasesUtil.isEmpty(messageMap.get(ToUserName))){
                    List list=  messageMap.get(ToUserName);
                    log.info("有待发送的消息,继续存储");
                    amp.put(ToUserName,message);
                    list.add(amp);
                    return;
                }else {
                    //该用户发的离线消息的集合
                    amp.put(ToUserName,message);
                    objects.add(amp);
                    messageMap.put(ToUserName, objects );
                    log.info("用户不在线保存信息");
                    return;
                }
            }
        }
    }

    public void sendMessageAll(String message) throws IOException {
        for (WebSocket item : clients.values()) {
            item.session.getAsyncRemote().sendText(message);
        }
    }

    /**
     * 获取消息列队
     * @return
     */
    public ConcurrentMap<String, List<Map>> getMessageMap(){
        return messageMap;
    }

    /**
     * 获取用户消息
     * @param username
     * @return
     */
    public List<Map> getuserMessageMap(String username){
        return messageMap.get(username);
    }

    /**
     * 删除用户消息
     * @param username
     */
    public void delMessageMap(String username){
        messageMap.remove(username);
    }
    public static synchronized int getOnlineCount() {
        return onlineNumber;
    }

}

四、新建一个消息实体类

import lombok.Data;

/**
 * @author 736421789@qq.com
 * @date 2020/3/3 10:08
 */
@Data
public class TemporaryInformation {
    /**
     * 发送时间
     */
    private String sendTime;
    /**
     * 发送内容
     */
    private String message;
    private String title;

}

 

五、controller测试


    @GetMapping("contactUs")
    public void GetContactUs(String ToUserName) throws IOException {
        TemporaryInformation temporaryInformation = new TemporaryInformation();
        temporaryInformation.setTitle("消息实时推送服务");
        temporaryInformation.setSendTime(DateUtil.getCurrentDate());
        temporaryInformation.setMessage("尊敬的用户你好:您附近有新订单,请注意查看!");
        //Result.toJsonPObject():把消息转换成自己定义的json格式
webSocketService.sendMessageTo(Result.toJsonPObject(temporaryInformation),ToUserName);
    }

希望大佬勿喷,java学习中,后续更新更多

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值