WebClientSocket.java 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. package com.cnd3b.common.websocket;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.cnd3b.common.BaseClass;
  4. import com.cnd3b.common.D3BReturnObject_Err;
  5. import com.cnd3b.common.data.Row;
  6. import com.cnd3b.common.parameter.parameter;
  7. import javax.websocket.*;
  8. import javax.websocket.server.PathParam;
  9. import javax.websocket.server.ServerEndpoint;
  10. import java.io.IOException;
  11. import java.lang.reflect.Constructor;
  12. import java.lang.reflect.InvocationTargetException;
  13. import java.lang.reflect.Method;
  14. import java.util.Calendar;
  15. import java.util.Date;
  16. import java.util.concurrent.ConcurrentHashMap;
  17. //ws://127.0.0.1:8080/samex/webSocket/829fef9884bbf7f9fb9c51499d7b332f
  18. @ServerEndpoint("/webSocket/{accesstoken}")
  19. public class WebClientSocket extends BaseClass {
  20. private Session session;
  21. //当前连接对象的账号ID
  22. private long userid;
  23. private Row userRow;
  24. private String accesstoken;
  25. private Date createdate;
  26. /**
  27. * 连接开启
  28. *
  29. * @param accesstoken
  30. * @param session
  31. * @throws IOException
  32. */
  33. @OnOpen
  34. private void onOpen(@PathParam("accesstoken") String accesstoken, Session session) throws IOException {
  35. this.session = session;
  36. this.accesstoken = accesstoken;
  37. createdate = getDateTime();
  38. if (parameter.tokenlist.containsKey(accesstoken)) {
  39. userid = parameter.tokenlist.get(accesstoken);
  40. userRow = parameter.userIdList.get(userid);
  41. } else {
  42. JSONObject methodobject = new JSONObject();
  43. methodobject.put("type", "err");
  44. methodobject.put("msg", "请登陆");
  45. sendSystemMessage(methodobject);
  46. return;
  47. }
  48. if (parameter.websocketClients.containsKey(userid)) {
  49. parameter.websocketClients.get(userid).put(accesstoken, this);
  50. } else {
  51. ConcurrentHashMap<String, WebClientSocket> map = new ConcurrentHashMap<>();
  52. map.put(accesstoken, this);
  53. parameter.websocketClients.put(userid, map);
  54. }
  55. parameter.loginDate.put(userid, createdate);
  56. }
  57. /**
  58. * 连接关闭
  59. *
  60. * @throws IOException
  61. */
  62. @OnClose
  63. private void onClose() throws IOException {
  64. if (parameter.websocketClients.containsKey(userid)) {
  65. parameter.websocketClients.get(userid).remove(accesstoken);
  66. if (parameter.websocketClients.get(userid).isEmpty()) {
  67. parameter.websocketClients.remove(userid);
  68. }
  69. }
  70. }
  71. /**
  72. * {
  73. * "dialogid":1,//对话框id
  74. * "messagetype":"text",//消息类型
  75. * "description":"",//消息摘要
  76. * "data":{
  77. * "message":""//文字正文,
  78. * }
  79. * },
  80. * {
  81. * "dialogid":1,
  82. * "messagetype":"file",//text,file,data,image,
  83. * "description":"",
  84. * "data":{
  85. * "ownertable":"",
  86. * "ownerid":"",
  87. * "serialnumber":"",
  88. * "postfix":"",
  89. * "fobsurl":"",
  90. * "fobsurl_minimage":"",
  91. * "fobsurl_hls":"",
  92. * "fdocument":""
  93. * }
  94. * },
  95. * {
  96. * "dialogid":1,
  97. * "messagetype":"data",//text,file,data,image
  98. * "description":"",
  99. * "data":{
  100. * "type":"",
  101. * "ownertable":"",
  102. * "ownerid":""
  103. * }
  104. * }
  105. *
  106. * @param messageObject
  107. * @throws IOException
  108. */
  109. /**
  110. * 消息接收
  111. *
  112. * @param RequestContent
  113. * @throws IOException
  114. */
  115. @OnMessage
  116. private void onMessage(String RequestContent) throws IOException {
  117. /**
  118. * 验证请求正文是否为规范的SONObject格式
  119. */
  120. JSONObject requestcontent = null;
  121. try {
  122. requestcontent = JSONObject.parseObject(RequestContent);
  123. } catch (Exception e) {
  124. return;
  125. }
  126. /**
  127. * 验证请求正文中是否包含必填的键值
  128. */
  129. String[] mustkeys = {"classname", "method", "content"};
  130. for (String mustkey : mustkeys) {
  131. if (!requestcontent.containsKey(mustkey)) {
  132. return;
  133. }
  134. }
  135. /**
  136. * 验证请求正文中的content是否为规范的SONObject格式
  137. */
  138. JSONObject content = new JSONObject();
  139. try {
  140. content = requestcontent.getJSONObject("content");
  141. } catch (Exception e) {
  142. return;
  143. }
  144. /**
  145. * 验证正文中的token是否有效
  146. */
  147. String className = requestcontent.getString("classname");
  148. parameter.requesttime.put(accesstoken, Calendar.getInstance().getTime());
  149. String methodName = requestcontent.getString("method");
  150. if (content.isEmpty()) {
  151. content = new JSONObject();
  152. }
  153. content.put("$classname", className);
  154. content.put("$method", methodName);
  155. content.put("$accesstoken", accesstoken);
  156. String key = className + "." + methodName;
  157. String result;
  158. Object obj = null;
  159. try {
  160. long starttimes = Calendar.getInstance().getTimeInMillis();
  161. /**
  162. * 执行请求方法
  163. */
  164. Class clz = Class.forName("com.cnd3b.websocketcontroller." + className);
  165. Constructor cla = clz.getDeclaredConstructor(JSONObject.class);
  166. obj = cla.newInstance(content);
  167. Method method = obj.getClass().getDeclaredMethod(methodName);
  168. result = (String) method.invoke(obj);
  169. long endtimes = Calendar.getInstance().getTimeInMillis();
  170. saveCallMethodMsg(key, true, endtimes - starttimes);
  171. } catch (ClassNotFoundException e) {
  172. e.printStackTrace();
  173. result = new D3BReturnObject_Err().setErrMsg("找不到指定的类" + className).toString();
  174. } catch (InstantiationException e) {
  175. e.printStackTrace();
  176. result = new D3BReturnObject_Err().setErrMsg("类" + className + "实例化异常").toString();
  177. } catch (IllegalAccessException e) {
  178. e.printStackTrace();
  179. result = new D3BReturnObject_Err().setErrMsg("类" + className + "安全权限异常,可能该类为非public类").toString();
  180. } catch (NoSuchMethodException e) {
  181. e.printStackTrace();
  182. result = new D3BReturnObject_Err().setErrMsg("找不到指定的类" + className + "的" + methodName + "方法").toString();
  183. } catch (IllegalArgumentException e) {
  184. e.printStackTrace();
  185. result = new D3BReturnObject_Err().setErrMsg("类" + className + "的" + methodName + "方法参数不合法").toString();
  186. } catch (InvocationTargetException e) {
  187. Throwable targetException = e.getTargetException();
  188. D3BReturnObject_Err d3BReturnObject_err = new D3BReturnObject_Err();
  189. d3BReturnObject_err.setErrMsg(targetException.getMessage());
  190. result = d3BReturnObject_err.toString();
  191. } catch (Exception e) {
  192. e.printStackTrace();
  193. result = new D3BReturnObject_Err().setErrMsg("发生未知异常" + e.getMessage()).toString();
  194. } finally {
  195. if (obj != null) {
  196. try {
  197. obj.getClass().getMethod("p2ServerSystemPaoSetClose").invoke(obj);
  198. } catch (Exception e) {
  199. e.printStackTrace();
  200. }
  201. }
  202. }
  203. return;
  204. }
  205. /**
  206. * 记录请求数
  207. *
  208. * @param key
  209. * @param fromdb
  210. * @param time
  211. */
  212. private void saveCallMethodMsg(String key, boolean fromdb, long time) {
  213. long callmethodTimes = parameter.callmethodTimes.containsKey(key) ? parameter.callmethodTimes.get(key) : 0L;
  214. //更新请求总数
  215. parameter.callmethodTimes.put(key, callmethodTimes + 1L);
  216. //最新请求时间
  217. parameter.lastcallmethodtime.put(key, Calendar.getInstance().getTime());
  218. //从缓存获取的次数
  219. long callmethod_fromcacheTimes = parameter.callmethod_fromcacheTimes.containsKey(key) ? parameter.callmethod_fromcacheTimes.get(key) : 0L;
  220. if (!fromdb) {
  221. /**
  222. * 方法请求从缓存获取次数
  223. */
  224. parameter.callmethod_fromcacheTimes.put(key, callmethod_fromcacheTimes + 1L);
  225. } else {
  226. /**
  227. * 方法请求查询最新耗时
  228. */
  229. parameter.callmethodLastTimeLong.put(key, time);
  230. long totaltimes = callmethodTimes - callmethod_fromcacheTimes;
  231. /**
  232. * 方法请求查询平均时间
  233. */
  234. long callmethodTimeLong = parameter.callmethodTimeLong.containsKey(key) ? parameter.callmethodTimeLong.get(key) : 0L;
  235. parameter.callmethodTimeLong.put(key, (callmethodTimeLong * totaltimes + time) / (totaltimes + 1));
  236. }
  237. }
  238. @OnError
  239. private void onError(Session session, Throwable error) {
  240. error.printStackTrace();
  241. }
  242. /**
  243. * 对当前连接发送对话框消息
  244. *
  245. * @param message
  246. */
  247. public void sendDialogMessage(JSONObject message) {
  248. JSONObject object = new JSONObject();
  249. object.put("msgtype", "imdialog");
  250. object.put("message", message);
  251. session.getAsyncRemote().sendText(object.toJSONString());
  252. }
  253. /**
  254. * 对当前连接发送系统消息
  255. *
  256. * @param message
  257. */
  258. public void sendSystemMessage(JSONObject message) {
  259. JSONObject object = new JSONObject();
  260. object.put("msgtype", "system");
  261. object.put("message", message);
  262. session.getAsyncRemote().sendText(object.toJSONString());
  263. }
  264. }