Springboot增加Layui即时通讯支持

原创
05/14 17:09
阅读数 87

1、在pom.xml中增加jar包支持

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

2、增加websocket配置类

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

/**
 * describe: websocketConfig
 * current user Maochao.zhu
 * current system 2020/5/12
 */
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return  new ServerEndpointExporter();
    }
}

3、增加websocket服务支持类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cn.zx.common.StringUtil;
import com.cn.zx.config.MyApplicationContextAware;
import com.cn.zx.po.sys.User;
import com.cn.zx.service.sys.UserService;
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;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * describe: websocket服务支持
 * current user Maochao.zhu
 * current system 2020/5/12
 */
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocketServer {
    public static Logger logger = LoggerFactory.getLogger(WebSocketServer.class);
    UserService userService;
    //ConcurrentHashMap是线程安全的,而HashMap是线程不安全的。
    //根据用户获取Session信息
    private static ConcurrentHashMap<String, Session> mapUS = new ConcurrentHashMap<String,Session>();
    //根据Session获取用户信息
    private static ConcurrentHashMap<Session,String> mapSU = new ConcurrentHashMap<Session,String>();
    //存储消息
    private static ConcurrentHashMap<String,String> messageMap = new ConcurrentHashMap<String,String>();

    /**
     * 连接建立成功调用的方法
     * @param session
     * @param userId
     */
    @OnOpen
    public void onOpen(Session session,@PathParam("userId") Integer userId) {
        mapUS.put(userId+"",session);
        mapSU.put(session,userId+"");
        logger.info("用户"+userId+"进入llws,当前在线人数为" + mapUS.size() );
        //发送离线消息
        sendMessage(session, userId+"");
    }

    /**
     * 连接关闭调用的方法
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        String userId=mapSU.get(session);
        if(userId!=null&&userId!=""){
            mapUS.remove(userId);
            mapSU.remove(session);
            logger.info("用户"+userId+"退出llws,当前在线人数为" + mapUS.size());
        }
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("############## 收到客户端消息:" + message );
        if(StringUtil.isBlank(message)){
            return;
        }
        JSONObject jsonObject= JSONObject.parseObject(message);
        jsonObject = jsonObject.getJSONObject("data");
        //请求数据为空
        if(null==jsonObject){
            return;
        }
        String type = jsonObject.getJSONObject("to").getString("type");
        if(type.equals("onlineStatus")){
            for(Session s:session.getOpenSessions()){		//循环发给所有在线的人
                JSONObject toMessage=new JSONObject();
                toMessage.put("id", jsonObject.getJSONObject("mine").getString("id"));
                toMessage.put("content", jsonObject.getJSONObject("mine").getString("content"));
                toMessage.put("type",type);
                for (String value : mapSU.values()) {
                    try {
                        mapUS.get(value).getBasicRemote().sendText(toMessage.toString());
                    } catch (IOException e) {
                        logger.info(e.getMessage());
                    }
                }
            }
        }else{
            int toId=jsonObject.getJSONObject("to").getInteger("id");
            JSONObject toMessage=new JSONObject();
            toMessage.put("username",jsonObject.getJSONObject("mine").getString("username"));
            toMessage.put("avatar", jsonObject.getJSONObject("mine").getString("avatar"));
            toMessage.put("type",type);
            toMessage.put("content", jsonObject.getJSONObject("mine").getString("content"));
            if(type.equals("friend")||type.equals("fankui")){
                toMessage.put("id", jsonObject.getJSONObject("mine").getInteger("id"));
            }else{
                toMessage.put("id", jsonObject.getJSONObject("to").getInteger("id"));
            }
            switch (type) {
                case "friend":           							//单聊,记录到mongo
                    if(mapUS.containsKey(toId+"")){
                        mapUS.get(toId+"").getAsyncRemote().sendText(toMessage.toString());//发送消息给对方
                        logger.info("单聊-来自客户端的消息:" + toMessage.toString());
                    }else{//如果不在线 就记录到数据库,下次对方上线时推送给对方。
                        logger.info("单聊-对方不在线,消息已存入" + toMessage.toString());
                        messageMap.put(toId+"", toMessage.toString());
                    }
                    break;
                case "group":
                    User userT= new User();
                    userT.setBranchId(toId);
                    userService = MyApplicationContextAware.getApplicationContext().getBean(UserService.class);
                    List<User> userList = userService.getImUserList(userT);
                    List<String> idStrList = new ArrayList<String>();
                    for(User u:userList){
                        idStrList.add(u.getId()+"");
                    }
                    String useridStr =  JSON.toJSONString(idStrList);
                    JSONArray memberList=JSONArray.parseArray(useridStr);  //获取群成员userId列表
                    if(memberList.size()>0){
                        for(int i=0;i<memberList.size();i++){ //发送到在线用户(除了发送者)
                            if(!memberList.get(i).equals(jsonObject.getJSONObject("mine").getInteger("id")+"")){
                                if(null==mapUS.get(memberList.get(i))){
                                    messageMap.put(memberList.get(i)+"", toMessage.toString());
                                    continue;//不在线、不能发送消息
                                }
                                mapUS.get(memberList.get(i)).getAsyncRemote().sendText(toMessage.toString());
                                logger.info("群聊-来自客户端的消息:" + toMessage.toString());
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
        }

    }

    /**
     * 发生错误时调用的方法
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        String userId=mapSU.get(session);
        if(userId!=null&&userId!=""){
            mapUS.remove(userId);
            mapSU.remove(session);
            logger.info("用户"+userId+"退出llws!当前在线人数为" + mapUS.size());
        }
        logger.info("#############################llws发生错误!"+userId);
    }

    /**
     * 用户上线以后发送保存的离线消息
     * @param session
     * @param userId
     */
    public void sendMessage(Session session,String userId) {
        String message = messageMap.get(userId);
        if(null!=message && !"".equals(message)){
            mapUS.get(userId).getAsyncRemote().sendText(message);
            //发送成功以后移除消息存储
            messageMap.remove(userId);
        }
    }
}

4、页面采用layUI的即时通讯LayIM前端页面调用websocket服务, 前端下载地址:https://layim.layui.com/

var socket = new WebSocket('ws://ip地址/websocket/'+ userId);
    //连接成功时触发
    socket.onopen = function(){
      console.log("WebSocket is open now.");
    };
	//初始化
    layim.config({
      init:{
        url:"初始化数据接口地址"
      },
      members: {
        url:"获取群成员接口地址",
        data:{
          "id":"id"
        }
      },
      notice: false,
      isfriend: true
    });

    //监听查看群员
    layim.on("members", function(data){
      console.log(data);
    });
    layim.on('sendMessage', function(res){
      var mine = res.mine; //包含我发送的消息及我的信息
      var to = res.to; //对方的信息
      //socket关闭
      if(socket.readyState!= socket.OPEN){
        console.log("--------socket closed--")
      }
      socket.send(JSON.stringify({
        type: 'chatMessage' //用于在服务端区分消息类型
        ,data: {
          "mine":mine,
          "to":to
        }
      }));
    });

    //监听收到的聊天消息,假设你服务端emit的事件名为:chatMessage
    socket.onmessage = function(res){
      var message = JSON.parse(res.data);
      layim.getMessage(message);
    };

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function() {
      socket.close();
    };
	
    //监听签名修改
    layim.on('sign', function(value){
       console.log(value);
    });
  });

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部