赞
踩
最近一段时间我们在完善项目,我们在写的项目是一个商城项目。上次考核的时候考虑到进度问题,客服功能只做了一半,这次项目我对它进行了完善。
客服功能因为要实现即时通信,我主要是基于websocket实现的,它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的。因为是第一次去写类似的功能,所以在实现过程中遇到了很多问题。
因为客服和用户并不是一直在线的,但是在用户离线的时候别人向他发送的消息他也应该接收到。所以在发送信息的时候我加了一个判断,当用户离线的时候将接收到的信息存到redis里面,在用户连接websocket的查询redis判断用户是否有离线的信息,如果有,在登录的时候一起发送过来。
发送消息
- Session userSession = map.get("user:" + userId);
- if (userSession != null) {
- userSession.getAsyncRemote().sendText(msgJson);
- }
- {
- String userKey = "msg@" + message.getUserId() + ":offLine";
- redisUtil.lLeftPush(userKey, msgJson);
- }
登录时判断
- String chatKey= "msg@" +userId + ":offLine";
- while(redisUtil.hasKey(chatKey)&&redisUtil.lLen(chatKey)!=0){
- String msg = redisUtil.lRightPop(chatKey);
- session.getAsyncRemote().sendText(msg);
- }
因为店铺与客服是一对多的关系,一个店铺里面可以有多个客服在线,当用户与客服进行聊天时,要保证一个客服和一个用户进行聊天,否则不符合逻辑。所以写项目的时候我给聊天列表设置了一个状态,客服可以查看所有的聊天列表,然后选择性进行接取业务,当一个聊天列表被一个客服接取后,其他客服不能进入这个聊天列表与用户进行聊天。
因为店铺与客服的一对多的关系,所以在用户反馈的时候该店铺的所有客服都可以看到聊天记录。我在用户给店铺发送信息的时候,先查询店铺里面有哪些客服,再查询客服的session,遍历给客服发送消息。
- @ServerEndpoint(value = "/websocket/{userId}")
- @Component
- public class WebSocketUtil {
-
- private static CopyOnWriteArraySet<WebSocketUtil> webSocketSet = new CopyOnWriteArraySet<WebSocketUtil>();
-
- private Session session;
-
- private String key;
-
- private static Map<String,Session> map = new HashMap<>();
- // private static Map<Integer, List<Integer>> storeMap=new HashMap<>();
-
- private static RedisUtil redisUtil;
-
- private static ChatDao chatDao;
-
- @Autowired
- public void setRedisUtil(RedisUtil redisUtil){
- WebSocketUtil.redisUtil = redisUtil;
- }
-
- @Autowired
- public void setChatDao(ChatDao chatDao){
- WebSocketUtil.chatDao = chatDao;
- }
-
- /**
- * 连接建立成功调用的方法
- */
-
- @OnOpen
- public void onOpen(Session session,@PathParam("userId")Integer userId) {
- this.session = session;
- this.key="user:"+userId;
- map.put(key, session);
- String chatKey= "msg@" +userId + ":offLine";
- while(redisUtil.hasKey(chatKey)&&redisUtil.lLen(chatKey)!=0){
- String msg = redisUtil.lRightPop(chatKey);
- session.getAsyncRemote().sendText(msg);
- }
- webSocketSet.add(this);
- //加入set中
- System.out.println("有新连接加入:"+userId+",当前在线人数为" + webSocketSet.size());
- this.session.getAsyncRemote().sendText("恭喜"+userId+"成功连接上WebSocket(其频道号:"+userId+")-->当前在线人数为:"+webSocketSet.size());
- }
- /**
- * 连接关闭调用的方法
- */
- @OnClose
- public void onClose() {
- webSocketSet.remove(this); //从set中删除
- System.out.println("有一连接关闭!当前在线人数为" + webSocketSet.size());
- }
-
- /**
- * 收到客户端消息后调用的方法
- *
- * @param message 客户端发送过来的消息*/
- @OnMessage
- public void onMessage(String message,@PathParam("id") String id) {
- }
- /**
- * 发生错误时调用
- *
- */
- @OnError
- public void onError( Throwable error) {
- System.out.println("发生错误");
- error.printStackTrace();
- }
- /**
- * 群发自定义消息
- * */
- public void broadcast(String message){
- for (WebSocketUtil item : webSocketSet) {
- //同步异步说明参考:http://blog.csdn.net/who_is_xiaoming/article/details/53287691
- //this.session.getBasicRemote().sendText(message);
- item.session.getAsyncRemote().sendText(message);//异步发送消息.
- }
- }
-
- public void sendMessage(Integer userId, Integer storeId, Message message) {
- Session userSession = map.get("user:" + userId);
- String msgJson = JSON.toJSONString(message);
- String userListKey = "userList:" + userId + "@chat";
- String storeListKey = "storeList:" + storeId + "@chat";
- int userList = (int) Double.parseDouble(redisUtil.zScore(userListKey, storeId + "") + "");
- int storeList = (int) Double.parseDouble(redisUtil.zScore(storeListKey, userId + "") + "");
- //发送给用户.
- if (userSession != null) {
- userSession.getAsyncRemote().sendText(msgJson);
- }
- {
- String userKey = "msg@" + message.getUserId() + ":offLine";
- redisUtil.lLeftPush(userKey, msgJson);
- }
- // List<Integer> list = storeMap.get(storeId);
- String userKey = "msg@" + userList + ":message";
- redisUtil.lLeftPush(userKey, msgJson);
- String storeKey = "msg@" + storeList + ":message";
- redisUtil.lLeftPush(storeKey, msgJson);
- Integer chatListId;
- if (message.getMessageStatus() == 0) {
- chatListId = storeId;
- } else {
- chatListId = userId;
- }
- String numKey = "chat@No:" + chatListId + "num";
- if (redisUtil.hasKey(numKey)) {
- redisUtil.incrBy(numKey, 1);
- } else {
- redisUtil.set(numKey, "1");
- }
- List<Integer> list=null;
- if(redisUtil.hasKey("chatService:"+storeId)){
- Set<String> strings = redisUtil.setMembers("chatService:" + storeId);
- list = strings.stream().map(Integer::parseInt).collect(Collectors.toList());
- }
- if (list != null) {
- for (Integer id :
- list) {
- Session chatSession = map.get("user:" + id);
- String chatKey;
- if (chatSession != null) {
- chatSession.getAsyncRemote().sendText(msgJson);
- } else {
- chatKey = "msg@" + message.getUserId() + ":offLine";
- redisUtil.lLeftPush(chatKey, msgJson);
- }
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。