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

首先给大家推荐一下我老师大神的人工智能教学网站。教学不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵黄段子!点这里可以跳转到网站

1、简单说明

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

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

2、项目内容

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

(1)webSocket服务

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

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

ChatServer.java

package com.ccq.webSocket; import com.ccq.pojo.User;import com.ccq.utils.CommonDate;import net.sf.json.JSONObject;import org.apache.log4j.Logger; import javax.servlet.http.HttpSession;import javax.websocket.*;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint;import java.util.Map;import java.util.concurrent.ConcurrentHashMap; /** * @author ccq * @Description webSocket服务 * @date 2017/12/16 17:31 */@ServerEndpoint(value="/chatServer/{userid}", configurator = HttpSessionConfigurator.class)public class ChatServer {     private static Logger logger = Logger.getLogger(ChatServer.class);    private static int onlineCount = 0; // 记录连接数目    // Map<用户id,用户信息>    private static Map<String, OnlineUser> onlineUserMap = new ConcurrentHashMap<String, OnlineUser>(); //在线用户     /**     * 连接成功调用的方法     */    @OnOpen    public void onOpen(@PathParam("userid") String userid , Session session, EndpointConfig config){         logger.info("[ChatServer] connection : userid = " + userid + " , sessionId = " + session.getId());         // 增加用户数量        addOnlineCount();         // 获取当前用户的session        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());        User user  = (User) httpSession.getAttribute("user"); // 获得当前用户信息         // 将当前用户存到在线用户列表中        OnlineUser onlineUser = new OnlineUser(user.getUserid(),user.getNickname(),session);        onlineUserMap.put(user.getUserid(),onlineUser);         // 通知所有在线用户,当前用户上线        String content = "[" + CommonDate.getTime24() + " : " + user.getNickname() + "加入聊天室,当前在线人数为 " + getOnlineCount() + "位" + "]";        JSONObject msg = new JSONObject();        msg.put("content",content);        String message = Message.getMessage(msg.toString(),Message.NOTICE,onlineUserMap.values());        Message.broadcast(message,onlineUserMap.values());     }     /**     * 连接关闭方法     */    @OnClose    public void onClose(@PathParam("userid") String userid,Session session,CloseReason closeReason){         logger.info("[ChatServer] close : userid = " + userid + " , sessionId = " + session.getId() +                " , closeCode = " + closeReason.getCloseCode().getCode() + " , closeReason = " +closeReason.getReasonPhrase());         // 减少当前用户        subOnlienCount();         // 移除的用户信息        OnlineUser removeUser = onlineUserMap.remove(userid);        onlineUserMap.remove(userid);         // 通知所有在线用户,当前用户下线        String content = "["+ CommonDate.getTime24() + " : " + removeUser.getNickname() + " 离开聊天室,当前在线人数为 " + getOnlineCount() + "位" + "]";        JSONObject msg = new JSONObject();        msg.put("content",content);        if(onlineUserMap.size() > 0){            String message = Message.getMessage(msg.toString(), Message.NOTICE, onlineUserMap.values());            Message.broadcast(message,onlineUserMap.values());        }else{            logger.info("content : ["+ CommonDate.getTime24() + " : " + removeUser.getNickname() + " 离开聊天室,当前在线人数为 " + getOnlineCount() + "位" + "]");        }     }     /**     * 接收客户端的message,判断是否有接收人而选择进行广播还是指定发送     * @param data 客户端发来的消息     */    @OnMessage    public void onMessage(@PathParam("userid") String userid,String data){        logger.info("[ChatServer] onMessage : userid = " + userid + " , data = " + data);         JSONObject messageJson = JSONObject.fromObject(data);        JSONObject message = messageJson.optJSONObject("message");        String to = message.optString("to");        String from = message.optString("from");        // 将用户id转换为名称        to = this.userIdCastNickName(to);         OnlineUser fromUser = onlineUserMap.get(from);        String sendMessage = Message.getContent(fromUser,to,message.optString("content"),message.optString("time"));        String returnData = Message.getMessage(sendMessage, messageJson.optString("type"),null);         if(to == null || to.equals("")){ // 进行广播            Message.broadcast(returnData.toString(),onlineUserMap.values());        }else{            Message.singleSend(returnData.toString(), onlineUserMap.get(from));   // 发送给自己            String[] useridList = message.optString("to").split(",");            for(String id : useridList){                if(!id.equals(from)){                    Message.singleSend(returnData.toString(), onlineUserMap.get(id)); // 分别发送给指定的用户                }            }        }    }     /**     * 发生错误     * @param throwable     */    @OnError    public void onError(@PathParam("userid") String userid,Session session,Throwable throwable){        logger.info("[ChatServer] close : userid = " + userid + " , sessionId = " + session.getId() +" , throwable = " + throwable.getMessage() );    }      public static int getOnlineCount() {        return onlineCount;    }     public synchronized void addOnlineCount(){        onlineCount++;    }     public synchronized void subOnlienCount(){        onlineCount--;    }     /**     * 将用户id转换为名称     * @param userIds     * @return     */    private String userIdCastNickName(String userIds){        String niceNames = "";        if(userIds != null && !userIds.equals("")){            String[] useridList = userIds.split(",");            String toName = "";            for (String id : useridList){                toName = toName + onlineUserMap.get(id).getNickname() + ",";            }            niceNames = toName.substring(0,toName.length() - 1);        }        return niceNames;    }}

OnlineUser.java

public class OnlineUser {    private String userid;    private String nickname;    private Session session;}

Message.java

package com.ccq.webSocket; import net.sf.json.JSONArray;import net.sf.json.JSONObject;import org.apache.commons.collections.CollectionUtils;import org.apache.log4j.Logger; import javax.websocket.Session;import java.io.IOException;import java.util.ArrayList;import java.util.Collection;import java.util.List; /** * @author ccq * @Description 消息类 * @date 2017/12/16 19:08 */public class Message {     private static Logger logger = Logger.getLogger(Message.class);     /**     * 消息类型     */    public static String NOTICE = "notice";     //通知    public static String MESSAGE = "message";   //消息     /**     * 组装信息返回给前台     * @param message  交互信息     * @param type     信息类型     * @param userList 在线列表     * @return     *     * "massage" : {     *              "from" : "xxx",     *              "to" : "xxx",     *              "content" : "xxx",     *              "time" : "xxxx.xx.xx"     *          },     * "type" : {notice|message},     * "list" : {[xx],[xx],[xx]}     */    public static String getMessage(String message,String type,Collection<OnlineUser> userList){        JSONObject msg = new JSONObject();        msg.put("message",message);        msg.put("type", type);         if(CollectionUtils.isNotEmpty(userList)){            List<String> propertys = new ArrayList<String>();            propertys.add("session");            JSONArray userListArray = JSONArray.fromObject(userList,JsonConfigUtils.getJsonConfig(propertys));            msg.put("list", userListArray);        }        return msg.toString();    }     /**     * 消息内容     * @param fromUser     * @param to     * @param content     * @param time     * @return     *          {     *              "from" : "xxx",     *              "to" : "xxx",     *              "content" : "xxx",     *              "time" : "xxxx.xx.xx"     *          }     */    public static String getContent(OnlineUser fromUser,String to,String content,String time){        JSONObject contentJson = new JSONObject();         // 转化为json串时去掉session,用户session不能被序列化        List<String> propertys = new ArrayList<String>();        propertys.add("session");        contentJson.put("from",JSONObject.fromObject(fromUser,JsonConfigUtils.getJsonConfig(propertys)));         contentJson.put("to",to);        contentJson.put("content",content);        contentJson.put("time",time);        return contentJson.toString();    }     /**     * 广播消息     * @param message 消息     * @param onlineUsers 在线用户     */    public static void broadcast(String message,Collection<OnlineUser> onlineUsers){        /***************************在线用户***************************/        StringBuffer userStr = new StringBuffer();        for(OnlineUser user : onlineUsers){            userStr.append(user.getNickname() + ",");        }        userStr.deleteCharAt(userStr.length()-1);        logger.info("[broadcast] message = " + message + ", onlineUsers = " + userStr.toString());        /***************************在线用户***************************/        for(OnlineUser user : onlineUsers){                try {                    user.getSession().getBasicRemote().sendText(message);                } catch (IOException e) {                    e.printStackTrace();                    logger.info("消息发送失败!" + e.getMessage());                    continue;                }        }    }     /**     * 对特定用户发送消息     * @param message     * @param onlineUser     */    public static void singleSend(String message, OnlineUser onlineUser){        logger.info("[singleSend] message = " + message + ", toUser = " + onlineUser.getNickname());        try {            onlineUser.getSession().getBasicRemote().sendText(message);        } catch (IOException e) {            e.printStackTrace();            logger.info("消息发送失败!" + e.getMessage());        }    }}


(2)用户头像上传

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

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

  @RequestMapping(value = "{userid}/upload", method = RequestMethod.POST,produces = "application/json; charset=utf-8")    @ResponseBody    public String updateUserPassword(@PathVariable("userid") String userid,String image,HttpServletRequest request){         JSONObject responseJson = new JSONObject();        String filePath = "I:\\IDEA2017-02\\img\\";        String PicName= UUID.randomUUID().toString()+".png";         String header ="data:image";        String[] imageArr=image.split(",");        if(imageArr[0].contains(header)) {//是img的             // 去掉头部            image=imageArr[1];            // 修改图片            BASE64Decoder decoder = new BASE64Decoder();            try {                byte[] decodedBytes = decoder.decodeBuffer(image); // 将字符串格式的image转为二进制流(biye[])的decodedBytes                String imgFilePath = filePath + PicName;           //指定图片要存放的位                File targetFile = new File(filePath);                if(!targetFile.exists()){                    targetFile.mkdirs();                }                FileOutputStream out = new FileOutputStream(imgFilePath);//新建一个文件输出器,并为它指定输出位置imgFilePath                out.write(decodedBytes); //利用文件输出器将二进制格式decodedBytes输出                out.close();                // 修改图片                User user = userService.getUserById(userid);                user.setProfilehead(PicName);                int flag = userService.updateUser(user);                if(flag > 0){                    Log log = LogUtil.setLog(userid, CommonDate.getTime24(), WordDefined.LOG_TYPE_UPDATE,WordDefined.LOG_DETAIL_UPDATE_PROFILEHEAD, NetUtil.getIpAddress(request));                    logService.insertLog(log);                }else{                    responseJson.put("result","error");                    responseJson.put("msg","上传失败!");                }            } catch (IOException e) {                e.printStackTrace();            }        }         responseJson.put("result","ok");        responseJson.put("msg","上传成功!");        responseJson.put("fileUrl","/pic/" + PicName);        return responseJson.toString();    }


3、改进的图片

4、源码地址(2017-12-17晚更新)

由于小弟刚学会使用github,所以现在才把修改的代码地址放出来。

源码github地址:https://github.com/chengchuanqiang/WebChat

说明一下:

1、github是一个好东西,有时间学习一下如何使用git版本管理工具还是蛮有用的;

2、使用maven+idea开发项目确实很带劲;

3、老老实实学习,快快乐乐进步。

点这里可以跳转到人工智能网站

0 0 投票数
文章评分
订阅评论
提醒
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请发表评论。x
()
x