package com.cloudyoung.wx.comet.server;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloudyoung.common.enums.PlatformNameEnum;
import com.cloudyoung.common.utils.LogUtil;
import com.cloudyoung.common.wx.constant.WebsocketConstants;
import com.cloudyoung.common.wx.vo.message.WebsocketDialogueVo;
import com.cloudyoung.wx.comet.jedis.JedisTemplate;
import com.cloudyoung.wx.comet.service.WxWebsocketMessageService;
/**
* @Description websocket处理类
* @date 2018年3月7日上午9:05:44
* @version V1.0
* @author 邹立强 (zoulq@cloud-young.com)
*
Copyright (c) Department of Research and Development/Beijing.
*/
@Component
public class SystemWebSocketHandler implements WebSocketHandler {
private static final Logger logger = LogManager.getLogger(SystemWebSocketHandler.class);
private static final Map> wxUser = new ConcurrentHashMap>();
@Autowired
private JedisTemplate jedisTemplate;
@Autowired
private WxWebsocketMessageService wxWebsocketMessageService;
/**
* Description websocket 客户端建立握手连接
* @param session
* @throws Exception
* @version V1.0
* @auth 邹立强 (zoulq@cloud-young.com)
* 2018年3月8日 上午10:10:06
*/
@Override
public void afterConnectionEstablished(WebSocketSession session){
Map handshakeAttributes = session.getHandshakeAttributes();
String appId = handshakeAttributes.get(WebsocketConstants.WX_WEBSOCKET_APPID_KEY).toString();
String module = handshakeAttributes.get(WebsocketConstants.WX_WEBSOCKET_MODULE_KEY).toString();
String serverId = WebSocketInit.serverIdMap.get(WebsocketConstants.WX_WEBSOCKET_SERVER_ID);
LogUtil.info(logger, PlatformNameEnum.WX, String.format("appId:%s, module:%s, module:%s", appId, module, serverId), "afterConnectionEstablished_invoke_method", null);
if (StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(module)) {
CopyOnWriteArrayList wxUserList = wxUser.get(module + appId);
if (CollectionUtils.isEmpty(wxUserList)) {
wxUserList = new CopyOnWriteArrayList();
}
jedisTemplate.addSetMember(module+appId, serverId);
wxUserList.addIfAbsent(session);
wxUser.put(module + appId, wxUserList);
}
}
/**
* @Description 消息处理
* @param session
* @param message
* @throws Exception
* @version V1.0
* @auth 邹立强 (zoulq@cloud-young.com)
* 2018年3月9日 上午10:48:13
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage> message) {
try {
Map handshakeAttributes = session.getHandshakeAttributes();
LogUtil.info(logger, PlatformNameEnum.WX, String.format("attributes:%s, message:%s", JSONObject.toJSONString(handshakeAttributes), JSONObject.toJSONString(message)), "handleMessage_invoke_method", "");
String appId = String.valueOf(handshakeAttributes.get(WebsocketConstants.WX_WEBSOCKET_APPID_KEY));
if(StringUtils.isNotBlank(appId) && !"null".equals(appId)) {
//String module = handshakeAttributes.get(WebsocketConstants.WX_WEBSOCKET_MODULE_KEY).toString();
//LogUtil.info(logger, PlatformNameEnum.WX, String.format("ip:%s, message:%s", session.getRemoteAddress(), JSONObject.toJSONString(message.getPayload())), "handleMessage_invoke_method", null);
WebsocketDialogueVo websocketDialogueVo=new WebsocketDialogueVo();
websocketDialogueVo.setContent(message.getPayload().toString());
websocketDialogueVo.setAuthorizerAppid(appId);
wxWebsocketMessageService.sendDialogueMessage(websocketDialogueVo);
//session.sendMessage(new TextMessage(message.getPayload().toString()));
}
} catch (Exception e) {
e.printStackTrace();
//LogUtil.error(logger, e, PlatformNameEnum.WX, String.format("message:%s",JSONObject.toJSONString(message)), "handleMessageError_invoke_fail");
}
}
/**
* @Description websocket 客户端异常
* @param session
* @param exception
* @throws Exception
* @version V1.0
* @auth 邹立强 (zoulq@cloud-young.com)
* 2018年3月8日 上午10:09:47
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
Map handshakeAttributes = session.getHandshakeAttributes();
if (null != handshakeAttributes) {
Object appIdO = handshakeAttributes.get(WebsocketConstants.WX_WEBSOCKET_APPID_KEY);
Object moduleO = handshakeAttributes.get(WebsocketConstants.WX_WEBSOCKET_MODULE_KEY);
if(appIdO!=null&&moduleO!=null) {
String appId = appIdO.toString();
String module = moduleO.toString();
String serverId = WebSocketInit.serverIdMap.get(WebsocketConstants.WX_WEBSOCKET_SERVER_ID);
LogUtil.info(logger, PlatformNameEnum.WX, String.format("appId:%s, module:%s", appId, module), "handleTransportError_invoke_method", null);
try {
if (session.isOpen()) {
session.close();
}
if (StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(module)) {
CopyOnWriteArrayList wxUserList = wxUser.get(module + appId);
if (wxUserList != null && wxUserList.size() > 0) {
wxUserList.remove(session);
}
if (wxUserList != null && wxUserList.size() == 0) {
wxUser.remove(module + appId);
jedisTemplate.removeSetMember(module + appId, serverId);
}
if (wxUserList != null && wxUserList.size() > 0) {
wxUser.put(module + appId, wxUserList);
}
handshakeAttributes.remove(WebsocketConstants.WX_WEBSOCKET_APPID_KEY);
handshakeAttributes.remove(WebsocketConstants.WX_WEBSOCKET_MODULE_KEY);
}
} catch (Exception e) {
LogUtil.error(logger, e, PlatformNameEnum.WX, String.format("appId:%s,module:%s", appId, module), "handleTransportError_invoke_fail");
}
}
}
}
/**
* @Description websocket 客户端关闭连接
* @param session
* @param closeStatus
* @throws Exception
* @version V1.0
* @auth 邹立强 (zoulq@cloud-young.com)
* 2018年3月8日 上午10:09:21
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
Map handshakeAttributes = session.getHandshakeAttributes();
if (null != handshakeAttributes) {
Object appIdO = handshakeAttributes.get(WebsocketConstants.WX_WEBSOCKET_APPID_KEY);
Object moduleO = handshakeAttributes.get(WebsocketConstants.WX_WEBSOCKET_MODULE_KEY);
if(appIdO!=null&&moduleO!=null) {
String appId = appIdO.toString();
String module = moduleO.toString();
String serverId = WebSocketInit.serverIdMap.get(WebsocketConstants.WX_WEBSOCKET_SERVER_ID);
LogUtil.info(logger, PlatformNameEnum.WX, String.format("appId:%s, module:%s", appId, module), "handleTransportError_invoke_method", null);
try {
if (session.isOpen()) {
session.close();
}
if (StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(module)) {
CopyOnWriteArrayList wxUserList = wxUser.get(module + appId);
if (wxUserList != null && wxUserList.size() > 0) {
wxUserList.remove(session);
}
if (wxUserList != null && wxUserList.size() == 0) {
wxUser.remove(module + appId);
jedisTemplate.removeSetMember(module + appId, serverId);
}
if (wxUserList != null && wxUserList.size() > 0) {
wxUser.put(module + appId, wxUserList);
}
handshakeAttributes.remove(WebsocketConstants.WX_WEBSOCKET_APPID_KEY);
handshakeAttributes.remove(WebsocketConstants.WX_WEBSOCKET_MODULE_KEY);
}
} catch (Exception e) {
LogUtil.error(logger, e, PlatformNameEnum.WX, String.format("appId:%s,module:%s", appId, module), "afterConnectionClosed_invoke_fail");
}
}
}
}
/**
* @Description 是否支持部分消息
* @return
* @version V1.0
* @auth 邹立强 (zoulq@cloud-young.com)
* 2018年3月9日 上午10:46:57
*/
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* @Description 微信粉丝单发消息
* @param sign
* @param module
* @param websocketDialogueVo
* @return
* @return Boolean
* @version V1.0
* @auth 邹立强 (zoulq@cloud-young.com)
* 2018年3月6日 下午12:03:35
*/
public Boolean sendMessageToUser(String sign, String module, WebsocketDialogueVo websocketDialogueVo) {
CopyOnWriteArrayList wxUserList = wxUser.get(module + sign);
Boolean isSuccess = false;
if (wxUserList != null) {
for (int i = 0; i < wxUserList.size(); i++) {
WebSocketSession user = wxUserList.get(i);
if (sign.equals((String) user.getHandshakeAttributes().get(WebsocketConstants.WX_WEBSOCKET_APPID_KEY))) {
try {
if (user.isOpen()) {
String clientSign = (String) user.getHandshakeAttributes().get(WebsocketConstants.WX_WEBSOCKET_CLIENT_SIGN);
websocketDialogueVo.setClientSign(clientSign);
TextMessage message = new TextMessage(JSON.toJSONString(websocketDialogueVo));
isSuccess = true;
synchronized (user) {
user.sendMessage(message);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
LogUtil.info(logger, PlatformNameEnum.WX, String.format("appId:%s,module:%s,websocketDialogueVo:%s\n", sign, module, JSON.toJSONString(websocketDialogueVo)),
"sendMessageToUserDefault_invoker", isSuccess.toString());
return isSuccess;
}
public static Map> getWxuser() {
return wxUser;
}
}