在開發一個項目的時候使用到了WebSocket協議
- 什么是WebSocket?
WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。
2.使用
-
-
- 工具類
1 package com.mz.usps.common.component; 2 3 import org.apache.log4j.Logger; 4 import org.springframework.stereotype.Component; 5 6 import javax.websocket.*; 7 import javax.websocket.server.PathParam; 8 import javax.websocket.server.ServerEndpoint; 9 import java.io.IOException; 10 import java.util.concurrent.ConcurrentHashMap; 11 import java.util.concurrent.ConcurrentMap; 12 13 //該注解用來指定一個URI,客戶端可以通過這個URI來連接到WebSocket。類似Servlet的注解mapping。無需在web.xml中配置。 14 @ServerEndpoint("/webSocket/{id}") 15 @Component("webSocket") 16 public class WebSocket { 17 18 private static Logger logger = Logger.getLogger(WebSocket.class); 19 //靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。 20 private static int onlineCount = 0; 21 //與某個客戶端的連接會話,需要通過它來給客戶端發送數據 22 private Session session; 23 //concurrent包的線程安全Map,用來存放每個客戶端對應的MyWebSocket對象。若要實現服務端與單一客戶端通信的話,可以使用Map來存放,其中Key可以為用戶標識 24 private static ConcurrentMap<String, WebSocket> webSocketMap = new ConcurrentHashMap<>(); 25 private static ConcurrentMap<String, WebSocket> webSocketMapAdmin = new ConcurrentHashMap<>(); 26 27 public Session getSession() { 28 return session; 29 } 30 31 public static WebSocket getWebSocket(String id) { 32 return webSocketMap.get(id); 33 } 34 35 /** 36 * 連接建立成功調用的方法 37 * 38 * @param session 可選的參數。session為與某個客戶端的連接會話,需要通過它來給客戶端發送數據 39 */ 40 @OnOpen 41 public void onOpen(Session session, @PathParam("id") String id) { 42 this.session = session; 43 //String sessionId = session.getId(); 44 webSocketMap.put(id, this); //加入map中 45 if (id.contains("admin")) {// 后台登陸用戶,加入list 46 webSocketMapAdmin.put(id, this); 47 } 48 addOnlineCount(); //在線數加1 49 System.out.println("有新連接加入!當前在線人數為" + getOnlineCount()); 50 } 51 52 /** 53 * 連接關閉調用的方法 54 */ 55 @OnClose 56 public void onClose(@PathParam("id") String id) { 57 webSocketMap.remove(id); //從map中刪除 58 webSocketMapAdmin.remove(id); 59 subOnlineCount(); //在線數減1 60 System.out.println("有一連接關閉!當前在線人數為" + getOnlineCount()); 61 } 62 63 /** 64 * 收到客戶端消息后調用的方法 65 * 66 * @param message 客戶端發送過來的消息 67 * @param session 可選的參數 68 */ 69 @OnMessage 70 public static void onMessage(String message, Session session) { 71 //群發消息 72 if (webSocketMapAdmin.size() > 0) { 73 for (WebSocket item : webSocketMapAdmin.values()) { 74 try { 75 //System.out.println(item.session.getId()); 76 item.session.getBasicRemote().sendText(message); 77 } catch (IOException e) { 78 logger.error("IO異常"); 79 continue; 80 } 81 } 82 } 83 84 } 85 86 /** 87 * 發生錯誤時調用 88 * 89 * @param session 90 * @param error 91 */ 92 @OnError 93 public void onError(Session session, Throwable error) { 94 //System.out.println("發生錯誤"); 95 logger.error("發生錯誤"); 96 } 97 98 /** 99 * 這個方法與上面幾個方法不一樣。沒有用注解,是根據自己需要添加的方法。 100 * 101 * @param message 102 * @throws IOException 103 */ 104 public void sendMessage(String message) throws IOException { 105 this.session.getBasicRemote().sendText(message); 106 //this.session.getAsyncRemote().sendText(message); 107 } 108 109 public static synchronized int getOnlineCount() { 110 return onlineCount; 111 } 112 113 public static synchronized void addOnlineCount() { 114 WebSocket.onlineCount++; 115 } 116 117 public static synchronized void subOnlineCount() { 118 WebSocket.onlineCount--; 119 } 120 121 public static void main(String[] args) { 122 /*WebSocket webSocket = new WebSocket(); 123 System.out.println(webSocket); 124 webSocketMap.put("1", webSocket); 125 webSocketMap.put("1", webSocket); 126 System.out.println(webSocketMap.get("12"));*/ 127 onMessage("123465",null); 128 } 129 }
- 微信登錄成功時將用戶信息發送給前端
-
1 /** 2 * 手機端微信登陸 3 * 4 * @return 5 */ 6 @RequestMapping(value = "/wxLogin", method = RequestMethod.GET) 7 @ResponseBody 8 public R wxLogin(String userResult, String state, @RequestParam(required = false, value = "userId") String userId) throws Exception { 9 //System.out.println(userResult+"\n"+state+"\n"+userId); 10 WxUser wxUser = JSON.parseObject(userResult, WxUser.class); 11 UserInfo userInfo = new UserInfo(); 12 userInfo.setUnionId(wxUser.getUnionid()); 13 userInfo.setOpenid(wxUser.getOpenid()); 14 userInfo.setSex((long) wxUser.getSex()); 15 userInfo.setHeadImgUrl(wxUser.getHeadimgurl()); 16 if (EmojiUtil.containsEmoji(wxUser.getNickName())) { 17 logger.info(wxUser.getNickName()); 18 userInfo.setNickName(EmojiUtil.emojiConverterToAlias(wxUser.getNickName())); 19 } else { 20 userInfo.setNickName(wxUser.getNickName()); 21 } 22 System.out.println(userInfo.getUnionId()); 23 UserInfo userInfo1; 24 WebSocket webSocket = WebSocket.getWebSocket(state); 25 Map<String, Object> m = new HashMap<>(); 26 //登錄 27 if (userId == null || "".equals(userId)) { 28 if ((userInfo1 = userInfoService.selectWx(userInfo)) != null) { 29 //判定賬號是否被禁用 30 if (userInfo1.getUserState() != 1) { 31 R r = new R(); 32 r.put("code", 500); 33 r.put("msg", "此賬號因為特殊原因已被禁用,若想重新啟用,請聯系管理員"); 34 webSocket.sendMessage(JSON.toJSONString(r)); 35 return null; 36 } 37 38 userInfo.setUserId(userInfo1.getUserId()); 39 //System.out.println(userInfo1.getHeadImgUrl()+"你好呀"); 40 if (userInfo1.getHeadImgUrl() != null) { 41 userInfo.setHeadImgUrl(null); 42 } 43 //System.out.println(userInfo.getHeadImgUrl()+"你好"); 44 userInfoService.updateByPrimaryKeySelective(userInfo); 45 UserInfo userInfo2 = userInfoService.selectWx(userInfo); 46 if (EmojiUtil.containsEmoji(userInfo2.getNickName())) { 47 userInfo2.setNickName(EmojiUtil.emojiConverterUnicodeStr(userInfo2.getNickName())); 48 } 49 m.put("openId", userInfo2.getOpenid()); 50 m.put("userId", userInfo2.getUserId()); 51 m.put("createTime", new Date()); 52 String javaWebToken = WebTokenUtil.createJavaWebToken(m); 53 userInfo2.setToken(javaWebToken); 54 redisCache.setValue(javaWebToken, "1", 1, TimeUnit.DAYS); 55 webSocket.sendMessage(JSON.toJSONString(userInfo2));//登錄用戶信息發送給web 56 return R.ok("登錄成功"); 57 } else { 58 userInfo.setUserName(userInfo.getNickName()); 59 userInfoService.insertSelective(userInfo); 60 UserInfo userInfo3 = userInfoService.selectWx(userInfo); 61 if (EmojiUtil.containsEmoji(userInfo3.getNickName())) { 62 userInfo3.setNickName(EmojiUtil.emojiConverterUnicodeStr(userInfo3.getNickName())); 63 } 64 //判定賬號是否被禁用 65 if (userInfo3.getUserState() != 1) { 66 R r = new R(); 67 r.put("code", 500); 68 r.put("msg", "此賬號因為特殊原因已被禁用,若想啟用,請聯系管理員"); 69 webSocket.sendMessage(JSON.toJSONString(r)); 70 return null; 71 } 72 73 System.out.println(userInfo.getOpenid()); 74 m.put("openId", userInfo3.getOpenid()); 75 m.put("userId", userInfo3.getUserId()); 76 m.put("createTime", new Date()); 77 String javaWebToken = WebTokenUtil.createJavaWebToken(m); 78 userInfo3.setToken(javaWebToken); 79 redisCache.setValue(javaWebToken, "1", 1, TimeUnit.DAYS); 80 webSocket.sendMessage(JSON.toJSONString(userInfo3));//登錄用戶信息發送給web 81 return R.ok("登錄成功"); 82 } 83 } else { 84 userInfo.setUserId(Long.valueOf(userId)); 85 //綁定微信前先判斷數據庫中是否有頭像,如果有,不更改頭像 86 List<UserInfo> selectmemberlist = userInfoService.selectmemberlist(userInfo); 87 if (selectmemberlist.get(0).getHeadImgUrl() != null) { 88 userInfo.setHeadImgUrl(null); 89 } 90 91 UserInfo userInfo2 = userInfoService.selectWx(userInfo); 92 if (userInfo2 != null) { 93 R r = new R(); 94 r.put("code", 500); 95 r.put("msg", "此微信已被注冊,若確認是你本人微信,請聯系管理員幫你更改"); 96 webSocket.sendMessage(JSON.toJSONString(r)); 97 return R.error(""); 98 } 99 if (EmojiUtil.containsEmoji(wxUser.getNickName())) { 100 userInfo.setNickName( EmojiUtil.emojiConverterToAlias(wxUser.getNickName())); 101 } 102 R r = userInfoService.updateByPrimaryKeySelective(userInfo); 103 if (r.get("code").equals(200)) { 104 R r1 = new R(); 105 r1.put("code", 200); 106 r1.put("msg", "更改成功"); 107 webSocket.sendMessage(JSON.toJSONString(r1)); 108 } else { 109 R r2 = new R(); 110 r2.put("code", 500); 111 r2.put("msg", "更改失敗"); 112 webSocket.sendMessage(JSON.toJSONString(r2)); 113 } 114 return r; 115 } 116 } 117 118 }
- 工具類
-