在網上看到一份比較nice的基於webSocket網頁聊天項目,準備看看學習學習,如是有了這篇文章!原博主博客:http://blog.csdn.net/Amayadream/article/details/50551617java
謝謝博主的文章和項目,我是抱着學習的態度,如有理解錯的地方,請指正。jquery
項目的功能說明去原博主博客看吧,項目上改進的地方,我具體作如下說明。git
(1)webSocket服務github
對於webSocket服務代碼,我進行一部分的封裝和優化,主要是消息內容的封裝、用戶信息封裝。web
頁面顯示用戶的暱稱,指定用戶暱稱進行消息發送。apache
ChatServer.javajson
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.javawebsocket
public class OnlineUser { private String userid; private String nickname; private Session session; }
Message.javasession
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)用戶頭像上傳app
在網上找了一個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(); }
因爲小弟剛學會使用github,因此如今才把修改的代碼地址放出來。
源碼github地址:https://github.com/chengchuanqiang/WebChat
說明一下:
一、github是一個好東西,有時間學習一下如何使用git版本管理工具仍是蠻有用的,有須要的視頻的我能夠免費發給你;
二、使用maven+idea開發項目確實很帶勁;
三、老老實實學習,快快樂樂進步。