作者 crossoverJie

:sparkles: Introducing new features.私聊

@@ -30,7 +30,7 @@ public interface MsgHandle { @@ -30,7 +30,7 @@ public interface MsgHandle {
30 * @param p2PReqVO 私聊请求 30 * @param p2PReqVO 私聊请求
31 * @throws Exception 31 * @throws Exception
32 */ 32 */
33 - void p2pChat(P2PReqVO p2PReqVO) ; 33 + void p2pChat(P2PReqVO p2PReqVO) throws Exception;
34 34
35 35
36 // TODO: 2018/12/26 后续对消息的处理可以优化为责任链模式 36 // TODO: 2018/12/26 后续对消息的处理可以优化为责任链模式
@@ -2,6 +2,7 @@ package com.crossoverjie.cim.client.service; @@ -2,6 +2,7 @@ package com.crossoverjie.cim.client.service;
2 2
3 import com.crossoverjie.cim.client.vo.req.GroupReqVO; 3 import com.crossoverjie.cim.client.vo.req.GroupReqVO;
4 import com.crossoverjie.cim.client.vo.req.LoginReqVO; 4 import com.crossoverjie.cim.client.vo.req.LoginReqVO;
  5 +import com.crossoverjie.cim.client.vo.req.P2PReqVO;
5 import com.crossoverjie.cim.client.vo.res.CIMServerResVO; 6 import com.crossoverjie.cim.client.vo.res.CIMServerResVO;
6 import com.crossoverjie.cim.client.vo.res.OnlineUsersResVO; 7 import com.crossoverjie.cim.client.vo.res.OnlineUsersResVO;
7 8
@@ -23,9 +24,18 @@ public interface RouteRequest { @@ -23,9 +24,18 @@ public interface RouteRequest {
23 */ 24 */
24 void sendGroupMsg(GroupReqVO groupReqVO) throws Exception; 25 void sendGroupMsg(GroupReqVO groupReqVO) throws Exception;
25 26
  27 +
  28 + /**
  29 + * 私聊
  30 + * @param p2PReqVO
  31 + * @throws Exception
  32 + */
  33 + void sendP2PMsg(P2PReqVO p2PReqVO)throws Exception;
  34 +
26 /** 35 /**
27 * 获取服务器 36 * 获取服务器
28 * @return 服务ip+port 37 * @return 服务ip+port
  38 + * @param loginReqVO
29 * @throws Exception 39 * @throws Exception
30 */ 40 */
31 CIMServerResVO.ServerInfo getCIMServer(LoginReqVO loginReqVO) throws Exception; 41 CIMServerResVO.ServerInfo getCIMServer(LoginReqVO loginReqVO) throws Exception;
@@ -35,4 +45,6 @@ public interface RouteRequest { @@ -35,4 +45,6 @@ public interface RouteRequest {
35 * @return 获取所有在线用户 45 * @return 获取所有在线用户
36 */ 46 */
37 List<OnlineUsersResVO.DataBodyBean> onlineUsers()throws Exception ; 47 List<OnlineUsersResVO.DataBodyBean> onlineUsers()throws Exception ;
  48 +
  49 +
38 } 50 }
@@ -50,7 +50,11 @@ public class MsgHandler implements MsgHandle { @@ -50,7 +50,11 @@ public class MsgHandler implements MsgHandle {
50 p2PReqVO.setUserId(configuration.getUserId()); 50 p2PReqVO.setUserId(configuration.getUserId());
51 p2PReqVO.setReceiveUserId(Long.parseLong(totalMsg[0])); 51 p2PReqVO.setReceiveUserId(Long.parseLong(totalMsg[0]));
52 p2PReqVO.setMsg(totalMsg[1]); 52 p2PReqVO.setMsg(totalMsg[1]);
  53 + try {
53 p2pChat(p2PReqVO); 54 p2pChat(p2PReqVO);
  55 + } catch (Exception e) {
  56 + LOGGER.error("Exception",e);
  57 + }
54 58
55 } else { 59 } else {
56 //群聊 60 //群聊
@@ -69,7 +73,9 @@ public class MsgHandler implements MsgHandle { @@ -69,7 +73,9 @@ public class MsgHandler implements MsgHandle {
69 } 73 }
70 74
71 @Override 75 @Override
72 - public void p2pChat(P2PReqVO p2PReqVO) { 76 + public void p2pChat(P2PReqVO p2PReqVO) throws Exception {
  77 +
  78 + routeRequest.sendP2PMsg(p2PReqVO);
73 79
74 } 80 }
75 81
@@ -6,6 +6,7 @@ import com.crossoverjie.cim.client.config.AppConfiguration; @@ -6,6 +6,7 @@ import com.crossoverjie.cim.client.config.AppConfiguration;
6 import com.crossoverjie.cim.client.service.RouteRequest; 6 import com.crossoverjie.cim.client.service.RouteRequest;
7 import com.crossoverjie.cim.client.vo.req.GroupReqVO; 7 import com.crossoverjie.cim.client.vo.req.GroupReqVO;
8 import com.crossoverjie.cim.client.vo.req.LoginReqVO; 8 import com.crossoverjie.cim.client.vo.req.LoginReqVO;
  9 +import com.crossoverjie.cim.client.vo.req.P2PReqVO;
9 import com.crossoverjie.cim.client.vo.res.CIMServerResVO; 10 import com.crossoverjie.cim.client.vo.res.CIMServerResVO;
10 import com.crossoverjie.cim.client.vo.res.OnlineUsersResVO; 11 import com.crossoverjie.cim.client.vo.res.OnlineUsersResVO;
11 import com.crossoverjie.cim.common.enums.StatusEnum; 12 import com.crossoverjie.cim.common.enums.StatusEnum;
@@ -39,6 +40,9 @@ public class RouteRequestImpl implements RouteRequest { @@ -39,6 +40,9 @@ public class RouteRequestImpl implements RouteRequest {
39 @Value("${cim.group.route.request.url}") 40 @Value("${cim.group.route.request.url}")
40 private String groupRouteRequestUrl; 41 private String groupRouteRequestUrl;
41 42
  43 + @Value("${cim.p2p.route.request.url}")
  44 + private String p2pRouteRequestUrl;
  45 +
42 @Value("${cim.server.route.request.url}") 46 @Value("${cim.server.route.request.url}")
43 private String serverRouteRequestUrl; 47 private String serverRouteRequestUrl;
44 48
@@ -70,6 +74,25 @@ public class RouteRequestImpl implements RouteRequest { @@ -70,6 +74,25 @@ public class RouteRequestImpl implements RouteRequest {
70 } 74 }
71 75
72 @Override 76 @Override
  77 + public void sendP2PMsg(P2PReqVO p2PReqVO) throws Exception {
  78 + JSONObject jsonObject = new JSONObject();
  79 + jsonObject.put("msg",p2PReqVO.getMsg());
  80 + jsonObject.put("userId",p2PReqVO.getUserId());
  81 + jsonObject.put("receiveUserId",p2PReqVO.getReceiveUserId());
  82 + RequestBody requestBody = RequestBody.create(mediaType,jsonObject.toString());
  83 +
  84 + Request request = new Request.Builder()
  85 + .url(p2pRouteRequestUrl)
  86 + .post(requestBody)
  87 + .build();
  88 +
  89 + Response response = okHttpClient.newCall(request).execute() ;
  90 + if (!response.isSuccessful()){
  91 + throw new IOException("Unexpected code " + response);
  92 + }
  93 + }
  94 +
  95 + @Override
73 public CIMServerResVO.ServerInfo getCIMServer(LoginReqVO loginReqVO) throws Exception { 96 public CIMServerResVO.ServerInfo getCIMServer(LoginReqVO loginReqVO) throws Exception {
74 97
75 JSONObject jsonObject = new JSONObject(); 98 JSONObject jsonObject = new JSONObject();
@@ -13,6 +13,9 @@ logging.level.root=info @@ -13,6 +13,9 @@ logging.level.root=info
13 # 群发消息 13 # 群发消息
14 cim.group.route.request.url=http://45.78.28.220:8083/groupRoute 14 cim.group.route.request.url=http://45.78.28.220:8083/groupRoute
15 15
  16 +# 私聊消息
  17 +cim.p2p.route.request.url=http://45.78.28.220:8083/p2pRoute
  18 +
16 # 登录并获取服务器ip+port 19 # 登录并获取服务器ip+port
17 cim.server.route.request.url=http://45.78.28.220:8083/login 20 cim.server.route.request.url=http://45.78.28.220:8083/login
18 21
@@ -23,7 +26,10 @@ cim.server.online.user.url=http://45.78.28.220:8083/onlineUser @@ -23,7 +26,10 @@ cim.server.online.user.url=http://45.78.28.220:8083/onlineUser
23 ###=======本地模拟======### 26 ###=======本地模拟======###
24 ## 群发消息 27 ## 群发消息
25 #cim.group.route.request.url=http://localhost:8083/groupRoute 28 #cim.group.route.request.url=http://localhost:8083/groupRoute
26 -# 29 +
  30 +# 私聊消息
  31 +#cim.p2p.route.request.url=http://localhost:8083/p2pRoute
  32 +
27 ## 登录并获取服务器ip+port 33 ## 登录并获取服务器ip+port
28 #cim.server.route.request.url=http://localhost:8083/login 34 #cim.server.route.request.url=http://localhost:8083/login
29 35
@@ -80,16 +80,29 @@ public class RouteController { @@ -80,16 +80,29 @@ public class RouteController {
80 return res; 80 return res;
81 } 81 }
82 82
83 - @ApiOperation("客户端下线")  
84 - @RequestMapping(value = "offLine", method = RequestMethod.POST) 83 + // TODO: 2018/12/26 这些基于 HTTP 接口的远程通信都可以换为 SpringCloud
  84 +
  85 + /**
  86 + * 私聊路由
  87 + *
  88 + * @param p2pRequest
  89 + * @return
  90 + */
  91 + @ApiOperation("私聊 API")
  92 + @RequestMapping(value = "p2pRoute", method = RequestMethod.POST)
85 @ResponseBody() 93 @ResponseBody()
86 - public BaseResponse<NULLBody> offLine(@RequestBody ChatReqVO groupReqVO) throws Exception { 94 + public BaseResponse<NULLBody> p2pRoute(@RequestBody P2PReqVO p2pRequest) throws Exception {
87 BaseResponse<NULLBody> res = new BaseResponse(); 95 BaseResponse<NULLBody> res = new BaseResponse();
88 96
89 - CIMUserInfo cimUserInfo = userInfoCacheService.loadUserInfoByUserId(groupReqVO.getUserId()); 97 + //获取接收消息用户的路由信息
  98 + CIMServerResVO cimServerResVO = accountService.loadRouteRelatedByUserId(p2pRequest.getReceiveUserId());
  99 + //推送消息
  100 + String url = "http://" + cimServerResVO.getIp() + ":" + cimServerResVO.getHttpPort() + "/sendMsg" ;
  101 +
  102 + //p2pRequest.getReceiveUserId()==>消息接收者的 userID
  103 + ChatReqVO chatVO = new ChatReqVO(p2pRequest.getReceiveUserId(),p2pRequest.getMsg()) ;
  104 + accountService.pushMsg(url,p2pRequest.getUserId(),chatVO);
90 105
91 - LOGGER.info("下线用户[{}]", cimUserInfo.toString());  
92 - accountService.offLine(groupReqVO.getUserId());  
93 106
94 res.setCode(StatusEnum.SUCCESS.getCode()); 107 res.setCode(StatusEnum.SUCCESS.getCode());
95 res.setMessage(StatusEnum.SUCCESS.getMessage()); 108 res.setMessage(StatusEnum.SUCCESS.getMessage());
@@ -97,18 +110,17 @@ public class RouteController { @@ -97,18 +110,17 @@ public class RouteController {
97 } 110 }
98 111
99 112
100 - /**  
101 - * 私聊路由  
102 - *  
103 - * @param p2pRequest  
104 - * @return  
105 - */  
106 - @ApiOperation("私聊 API")  
107 - @RequestMapping(value = "p2pRoute", method = RequestMethod.POST) 113 + @ApiOperation("客户端下线")
  114 + @RequestMapping(value = "offLine", method = RequestMethod.POST)
108 @ResponseBody() 115 @ResponseBody()
109 - public BaseResponse<NULLBody> p2pRoute(@RequestBody P2PReqVO p2pRequest) { 116 + public BaseResponse<NULLBody> offLine(@RequestBody ChatReqVO groupReqVO) throws Exception {
110 BaseResponse<NULLBody> res = new BaseResponse(); 117 BaseResponse<NULLBody> res = new BaseResponse();
111 118
  119 + CIMUserInfo cimUserInfo = userInfoCacheService.loadUserInfoByUserId(groupReqVO.getUserId());
  120 +
  121 + LOGGER.info("下线用户[{}]", cimUserInfo.toString());
  122 + accountService.offLine(groupReqVO.getUserId());
  123 +
112 res.setCode(StatusEnum.SUCCESS.getCode()); 124 res.setCode(StatusEnum.SUCCESS.getCode());
113 res.setMessage(StatusEnum.SUCCESS.getMessage()); 125 res.setMessage(StatusEnum.SUCCESS.getMessage());
114 return res; 126 return res;
@@ -46,6 +46,13 @@ public interface AccountService { @@ -46,6 +46,13 @@ public interface AccountService {
46 */ 46 */
47 Map<Long,CIMServerResVO> loadRouteRelated() ; 47 Map<Long,CIMServerResVO> loadRouteRelated() ;
48 48
  49 + /**
  50 + * 获取某个用户的路有关系
  51 + * @param userId
  52 + * @return 获取某个用户的路有关系
  53 + */
  54 + CIMServerResVO loadRouteRelatedByUserId(Long userId) ;
  55 +
49 56
50 /** 57 /**
51 * 推送消息 58 * 推送消息
@@ -117,6 +117,14 @@ public class AccountServiceRedisImpl implements AccountService { @@ -117,6 +117,14 @@ public class AccountServiceRedisImpl implements AccountService {
117 return routes; 117 return routes;
118 } 118 }
119 119
  120 + @Override
  121 + public CIMServerResVO loadRouteRelatedByUserId(Long userId) {
  122 + String value = redisTemplate.opsForValue().get(ROUTE_PREFIX + userId);
  123 + String[] server = value.split(":");
  124 + CIMServerResVO cimServerResVO = new CIMServerResVO(server[0], Integer.parseInt(server[1]), Integer.parseInt(server[2]));
  125 + return cimServerResVO;
  126 + }
  127 +
120 private void parseServerInfo(Map<Long, CIMServerResVO> routes, String key) { 128 private void parseServerInfo(Map<Long, CIMServerResVO> routes, String key) {
121 long userId = Long.valueOf(key.split(":")[1]); 129 long userId = Long.valueOf(key.split(":")[1]);
122 String value = redisTemplate.opsForValue().get(key); 130 String value = redisTemplate.opsForValue().get(key);
@@ -6,7 +6,7 @@ import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import io.swagger.annotations.ApiModelProperty;
6 import javax.validation.constraints.NotNull; 6 import javax.validation.constraints.NotNull;
7 7
8 /** 8 /**
9 - * Function: 9 + * Function: 单聊请求
10 * 10 *
11 * @author crossoverJie 11 * @author crossoverJie
12 * Date: 2018/05/21 15:56 12 * Date: 2018/05/21 15:56
@@ -14,10 +14,39 @@ import javax.validation.constraints.NotNull; @@ -14,10 +14,39 @@ import javax.validation.constraints.NotNull;
14 */ 14 */
15 public class P2PReqVO extends BaseRequest { 15 public class P2PReqVO extends BaseRequest {
16 16
  17 + @NotNull(message = "userId 不能为空")
  18 + @ApiModelProperty(required = true, value = "消息发送者的 userId", example = "1545574049323")
  19 + private Long userId ;
  20 +
  21 +
  22 + @NotNull(message = "userId 不能为空")
  23 + @ApiModelProperty(required = true, value = "消息接收者的 userId", example = "1545574049323")
  24 + private Long receiveUserId ;
  25 +
  26 +
  27 +
  28 +
17 @NotNull(message = "msg 不能为空") 29 @NotNull(message = "msg 不能为空")
18 @ApiModelProperty(required = true, value = "msg", example = "hello") 30 @ApiModelProperty(required = true, value = "msg", example = "hello")
19 private String msg ; 31 private String msg ;
20 32
  33 + public P2PReqVO() {
  34 + }
  35 +
  36 + public P2PReqVO(Long userId, Long receiveUserId, String msg) {
  37 + this.userId = userId;
  38 + this.receiveUserId = receiveUserId;
  39 + this.msg = msg;
  40 + }
  41 +
  42 + public Long getReceiveUserId() {
  43 + return receiveUserId;
  44 + }
  45 +
  46 + public void setReceiveUserId(Long receiveUserId) {
  47 + this.receiveUserId = receiveUserId;
  48 + }
  49 +
21 public String getMsg() { 50 public String getMsg() {
22 return msg; 51 return msg;
23 } 52 }
@@ -25,4 +54,20 @@ public class P2PReqVO extends BaseRequest { @@ -25,4 +54,20 @@ public class P2PReqVO extends BaseRequest {
25 public void setMsg(String msg) { 54 public void setMsg(String msg) {
26 this.msg = msg; 55 this.msg = msg;
27 } 56 }
  57 +
  58 + public Long getUserId() {
  59 + return userId;
  60 + }
  61 +
  62 + public void setUserId(Long userId) {
  63 + this.userId = userId;
  64 + }
  65 +
  66 + @Override
  67 + public String toString() {
  68 + return "GroupReqVO{" +
  69 + "userId=" + userId +
  70 + ", msg='" + msg + '\'' +
  71 + "} " + super.toString();
  72 + }
28 } 73 }