Java WebSocket实现网络聊天室(群聊+私聊)

1、简单说明

在网上看到一份比较nice的基于webSocket网页聊天项目,准备看看学习学习,如是有了这篇文章!原博主博客:http://blog.csdn.net/Amayadream/article/details/50551617

谢谢博主的文章和项目,我是抱着学习的态度,若有理解错的地方,请指正。

2、项目内容

项目的功能说明去原博主博客看吧,项目上改进的地方,我具体做以下说明。

(1)webSocket服务

对于webSocket服务代码,我进行一部分的封装和优化,主要是消息内容的封装、用户信息封装。

页面显示用户的昵称,指定用户昵称进行消息发送。

ChatServer.java

[java]  view plain  copy
  1. package com.ccq.webSocket;  
  2.   
  3. import com.ccq.pojo.User;  
  4. import com.ccq.utils.CommonDate;  
  5. import net.sf.json.JSONObject;  
  6. import org.apache.log4j.Logger;  
  7.   
  8. import javax.servlet.http.HttpSession;  
  9. import javax.websocket.*;  
  10. import javax.websocket.server.PathParam;  
  11. import javax.websocket.server.ServerEndpoint;  
  12. import java.util.Map;  
  13. import java.util.concurrent.ConcurrentHashMap;  
  14.   
  15. /** 
  16.  * @author ccq 
  17.  * @Description webSocket服务 
  18.  * @date 2017/12/16 17:31 
  19.  */  
  20. @ServerEndpoint(value="/chatServer/{userid}", configurator = HttpSessionConfigurator.class)  
  21. public class ChatServer {  
  22.   
  23.     private static Logger logger = Logger.getLogger(ChatServer.class);  
  24.     private static int onlineCount = 0// 记录连接数目  
  25.     // Map<用户id,用户信息>  
  26.     private static Map<String, OnlineUser> onlineUserMap = new ConcurrentHashMap<String, OnlineUser>(); //在线用户  
  27.   
  28.     /** 
  29.      * 连接成功调用的方法 
  30.      */  
  31.     @OnOpen  
  32.     public void onOpen(@PathParam("userid") String userid , Session session, EndpointConfig config){  
  33.   
  34.         logger.info("[ChatServer] connection : userid = " + userid + " , sessionId = " + session.getId());  
  35.   
  36.         // 增加用户数量  
  37.         addOnlineCount();  
  38.   
  39.         // 获取当前用户的session  
  40.         HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());  
  41.         User user  = (User) httpSession.getAttribute("user"); // 获得当前用户信息  
  42.   
  43.         // 将当前用户存到在线用户列表中  
  44.         OnlineUser onlineUser = new OnlineUser(user.getUserid(),user.getNickname(),session);  
  45.         onlineUserMap.put(user.getUserid(),onlineUser);  
  46.   
  47.         // 通知所有在线用户,当前用户上线  
  48.         String content = "[" + CommonDate.getTime24() + " : " + user.getNickname() + "加入聊天室,当前在线人数为 " + getOnlineCount() + "位" + "]";  
  49.         JSONObject msg = new JSONObject();  
  50.         msg.put("content",content);  
  51.         String message = Message.getMessage(msg.toString(),Message.NOTICE,onlineUserMap.values());  
  52.         Message.broadcast(message,onlineUserMap.values());  
  53.   
  54.     }  
  55.   
  56.     /** 
  57.      * 连接关闭方法 
  58.      */  
  59.     @OnClose  
  60.     public void onClose(@PathParam("userid") String userid,Session session,CloseReason closeReason){  
  61.   
  62.         logger.info("[ChatServer] close : userid = " + userid + " , sessionId = " + session.getId() +  
  63.                 " , closeCode = " + closeReason.getCloseCode().getCode() + " , closeReason = " +closeReason.getReasonPhrase());  
  64.   
  65.         // 减少当前用户  
  66.         subOnlienCount();  
  67.   
  68.         // 移除的用户信息  
  69.         OnlineUser removeUser = onlineUserMap.remove(userid);  
  70.         onlineUserMap.remove(userid);  
  71.   
  72.         // 通知所有在线用户,当前用户下线  
  73.         String content = "["+ CommonDate.getTime24() + " : " + removeUser.getNickname() + " 离开聊天室,当前在线人数为 " + getOnlineCount() + "位" + "]";  
  74.         JSONObject msg = new JSONObject();  
  75.         msg.put("content",content);  
  76.         if(onlineUserMap.size() > 0){  
  77.             String message = Message.getMessage(msg.toString(), Message.NOTICE, onlineUserMap.values());  
  78.             Message.broadcast(message,onlineUserMap.values());  
  79.         }else{  
  80.             logger.info("content : ["+ CommonDate.getTime24() + " : " + removeUser.getNickname() + " 离开聊天室,当前在线人数为 " + getOnlineCount() + "位" + "]");  
  81.         }  
  82.   
  83.     }  
  84.   
  85.     /** 
  86.      * 接收客户端的message,判断是否有接收人而选择进行广播还是指定发送 
  87.      * @param data 客户端发来的消息 
  88.      */  
  89.     @OnMessage  
  90.     public void onMessage(@PathParam("userid") String userid,String data){  
  91.         logger.info("[ChatServer] onMessage : userid = " + userid + " , data = " + data);  
  92.   
  93.         JSONObject messageJson = JSONObject.fromObject(data);  
  94.         JSONObject message = messageJson.optJSONObject("message");  
  95.         String to = message.optString("to");  
  96.         String from = message.optString("from");  
  97.         // 将用户id转换为名称  
  98.         to = this.userIdCastNickName(to);  
  99.   
  100.         OnlineUser fromUser = onlineUserMap.get(from);  
  101.         String sendMessage = Message.getContent(fromUser,to,message.optString("content"),message.optString("time"));  
  102.         String returnData = Message.getMessage(sendMessage, messageJson.optString("type"),null);  
  103.   
  104.         if(to == null || to.equals("")){ // 进行广播  
  105.             Message.broadcast(returnData.toString(),onlineUserMap.values());  
  106.         }else{  
  107.             Message.singleSend(returnData.toString(), onlineUserMap.get(from));   // 发送给自己  
  108.             String[] useridList = message.optString("to").split(",");  
  109.             for(String id : useridList){  
  110.                 if(!id.equals(from)){  
  111.                     Message.singleSend(returnData.toString(), onlineUserMap.get(id)); // 分别发送给指定的用户  
  112.                 }  
  113.             }  
  114.         }  
  115.     }  
  116.   
  117.     /** 
  118.      * 发生错误 
  119.      * @param throwable 
  120.      */  
  121.     @OnError  
  122.     public void onError(@PathParam("userid") String userid,Session session,Throwable throwable){  
  123.         logger.info("[ChatServer] close : userid = " + userid + " , sessionId = " + session.getId() +" , throwable = " + throwable.getMessage() );  
  124.     }  
  125.   
  126.   
  127.     public static int getOnlineCount() {  
  128.         return onlineCount;  
  129.     }  
  130.   
  131.     public synchronized void addOnlineCount(){  
  132.         onlineCount++;  
  133.     }  
  134.   
  135.     public synchronized void subOnlienCount(){  
  136.         onlineCount--;  
  137.     }  
  138.   
  139.     /** 
  140.      * 将用户id转换为名称 
  141.      * @param userIds 
  142.      * @return 
  143.      */  
  144.     private String userIdCastNickName(String userIds){  
  145.         String niceNames = "";  
  146.         if(userIds != null && !userIds.equals("")){  
  147.             String[] useridList = userIds.split(",");  
  148.             String toName = "";  
  149.             for (String id : useridList){  
  150.                 toName = toName + onlineUserMap.get(id).getNickname() + ",";  
  151.             }  
  152.             niceNames = toName.substring(0,toName.length() - 1);  
  153.         }  
  154.         return niceNames;  
  155.     }  
  156. }  

OnlineUser.java

[java]  view plain  copy
  1. public class OnlineUser {  
  2.     private String userid;  
  3.     private String nickname;  
  4.     private Session session;  
  5. }  

Message.java

[java]  view plain  copy
  1. package com.ccq.webSocket;  
  2.   
  3. import net.sf.json.JSONArray;  
  4. import net.sf.json.JSONObject;  
  5. import org.apache.commons.collections.CollectionUtils;  
  6. import org.apache.log4j.Logger;  
  7.   
  8. import javax.websocket.Session;  
  9. import java.io.IOException;  
  10. import java.util.ArrayList;  
  11. import java.util.Collection;  
  12. import java.util.List;  
  13.   
  14. /** 
  15.  * @author ccq 
  16.  * @Description 消息类 
  17.  * @date 2017/12/16 19:08 
  18.  */  
  19. public class Message {  
  20.   
  21.     private static Logger logger = Logger.getLogger(Message.class);  
  22.   
  23.     /** 
  24.      * 消息类型 
  25.      */  
  26.     public static String NOTICE = "notice";     //通知  
  27.     public static String MESSAGE = "message";   //消息  
  28.   
  29.     /** 
  30.      * 组装信息返回给前台 
  31.      * @param message  交互信息 
  32.      * @param type     信息类型 
  33.      * @param userList 在线列表 
  34.      * @return 
  35.      * 
  36.      * "massage" : { 
  37.      *              "from" : "xxx", 
  38.      *              "to" : "xxx", 
  39.      *              "content" : "xxx", 
  40.      *              "time" : "xxxx.xx.xx" 
  41.      *          }, 
  42.      * "type" : {notice|message}, 
  43.      * "list" : {[xx],[xx],[xx]} 
  44.      */  
  45.     public static String getMessage(String message,String type,Collection<OnlineUser> userList){  
  46.         JSONObject msg = new JSONObject();  
  47.         msg.put("message",message);  
  48.         msg.put("type", type);  
  49.   
  50.         if(CollectionUtils.isNotEmpty(userList)){  
  51.             List<String> propertys = new ArrayList<String>();  
  52.             propertys.add("session");  
  53.             JSONArray userListArray = JSONArray.fromObject(userList,JsonConfigUtils.getJsonConfig(propertys));  
  54.             msg.put("list", userListArray);  
  55.         }  
  56.         return msg.toString();  
  57.     }  
  58.   
  59.     /** 
  60.      * 消息内容 
  61.      * @param fromUser 
  62.      * @param to 
  63.      * @param content 
  64.      * @param time 
  65.      * @return 
  66.      *          { 
  67.      *              "from" : "xxx", 
  68.      *              "to" : "xxx", 
  69.      *              "content" : "xxx", 
  70.      *              "time" : "xxxx.xx.xx" 
  71.      *          } 
  72.      */  
  73.     public static String getContent(OnlineUser fromUser,String to,String content,String time){  
  74.         JSONObject contentJson = new JSONObject();  
  75.   
  76.         // 转化为json串时去掉session,用户session不能被序列化  
  77.         List<String> propertys = new ArrayList<String>();  
  78.         propertys.add("session");  
  79.         contentJson.put("from",JSONObject.fromObject(fromUser,JsonConfigUtils.getJsonConfig(propertys)));  
  80.   
  81.         contentJson.put("to",to);  
  82.         contentJson.put("content",content);  
  83.         contentJson.put("time",time);  
  84.         return contentJson.toString();  
  85.     }  
  86.   
  87.     /** 
  88.      * 广播消息 
  89.      * @param message 消息 
  90.      * @param onlineUsers 在线用户 
  91.      */  
  92.     public static void broadcast(String message,Collection<OnlineUser> onlineUsers){  
  93.         /***************************在线用户***************************/  
  94.         StringBuffer userStr = new StringBuffer();  
  95.         for(OnlineUser user : onlineUsers){  
  96.             userStr.append(user.getNickname() + ",");  
  97.         }  
  98.         userStr.deleteCharAt(userStr.length()-1);  
  99.         logger.info("[broadcast] message = " + message + ", onlineUsers = " + userStr.toString());  
  100.         /***************************在线用户***************************/  
  101.         for(OnlineUser user : onlineUsers){  
  102.                 try {  
  103.                     user.getSession().getBasicRemote().sendText(message);  
  104.                 } catch (IOException e) {  
  105.                     e.printStackTrace();  
  106.                     logger.info("消息发送失败!" + e.getMessage());  
  107.                     continue;  
  108.                 }  
  109.         }  
  110.     }  
  111.   
  112.     /** 
  113.      * 对特定用户发送消息 
  114.      * @param message 
  115.      * @param onlineUser 
  116.      */  
  117.     public static void singleSend(String message, OnlineUser onlineUser){  
  118.         logger.info("[singleSend] message = " + message + ", toUser = " + onlineUser.getNickname());  
  119.         try {  
  120.             onlineUser.getSession().getBasicRemote().sendText(message);  
  121.         } catch (IOException e) {  
  122.             e.printStackTrace();  
  123.             logger.info("消息发送失败!" + e.getMessage());  
  124.         }  
  125.     }  
  126. }  

(2)用户头像上传

在网上找了一个amazeui的图片上传,可以对图片进行裁剪,地址:http://www.jq22.com/jquery-info13022

确实比较好用,贴一下主要代码

[java]  view plain  copy
  1. @RequestMapping(value = "{userid}/upload", method = RequestMethod.POST,produces = "application/json; charset=utf-8")  
  2.   @ResponseBody  
  3.   public String updateUserPassword(@PathVariable("userid") String userid,String image,HttpServletRequest request){  
  4.   
  5.       JSONObject responseJson = new JSONObject();  
  6.       String filePath = "I:\\IDEA2017-02\\img\\";  
  7.       String PicName= UUID.randomUUID().toString()+".png";  
  8.   
  9.       String header ="data:image";  
  10.       String[] imageArr=image.split(",");  
  11.       if(imageArr[0].contains(header)) {//是img的  
  12.   
  13.           // 去掉头部  
  14.           image=imageArr[1];  
  15.           // 修改图片  
  16.           BASE64Decoder decoder = new BASE64Decoder();  
  17.           try {  
  18.               byte[] decodedBytes = decoder.decodeBuffer(image); // 将字符串格式的image转为二进制流(biye[])的decodedBytes  
  19.               String imgFilePath = filePath + PicName;           //指定图片要存放的位  
  20.               File targetFile = new File(filePath);  
  21.               if(!targetFile.exists()){  
  22.                   targetFile.mkdirs();  
  23.               }  
  24.               FileOutputStream out = new FileOutputStream(imgFilePath);//新建一个文件输出器,并为它指定输出位置imgFilePath  
  25.               out.write(decodedBytes); //利用文件输出器将二进制格式decodedBytes输出  
  26.               out.close();  
  27.               // 修改图片  
  28.               User user = userService.getUserById(userid);  
  29.               user.setProfilehead(PicName);  
  30.               int flag = userService.updateUser(user);  
  31.               if(flag > 0){  
  32.                   Log log = LogUtil.setLog(userid, CommonDate.getTime24(), WordDefined.LOG_TYPE_UPDATE,WordDefined.LOG_DETAIL_UPDATE_PROFILEHEAD, NetUtil.getIpAddress(request));  
  33.                   logService.insertLog(log);  
  34.               }else{  
  35.                   responseJson.put("result","error");  
  36.                   responseJson.put("msg","上传失败!");  
  37.               }  
  38.           } catch (IOException e) {  
  39.               e.printStackTrace();  
  40.           }  
  41.       }  
  42.   
  43.       responseJson.put("result","ok");  
  44.       responseJson.put("msg","上传成功!");  
  45.       responseJson.put("fileUrl","/pic/" + PicName);  
  46.       return responseJson.toString();  
  47.   }  


 


3、改进的图片


转载地址:http://blog.csdn.net/qq_27717967/article/details/78826475


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值