在开发一个项目的时候使用到了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+" "+state+" "+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 }
- 工具类
-