{"id":220015,"date":"2014-04-19T20:16:03","date_gmt":"2014-04-19T16:16:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=220015"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=220015","title":{"rendered":"<span class=\"post_title\">\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c Spring<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t\u0421\u043a\u0430\u0436\u0443 \u0441\u0440\u0430\u0437\u0443, \u0447\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u2014 <a href=\"http:\/\/habrahabr.ru\/post\/187822\/\">\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442<\/a>.<\/p>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043c\u044b &quot;<a href=\"http:\/\/habrahabr.ru\/post\/211937\/\">\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u044b\u0437\u043e\u0432 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0432 \u043e\u0434\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445<\/a>&quot;, \u0437\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u043d\u044b ajax \u043d\u0430 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u044b, <br \/>  \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0430(jrspc), \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0432\u044b\u0448\u0435\u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0439 \u0442\u0435\u043c\u0435. <\/p>\n<p>  \u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u2014 \u0431\u044b\u043b \u043e\u043f\u0438\u0441\u0430\u043d \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0432\u044b\u0437\u043e\u0432\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c ajax.<\/p>\n<p>  \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u2014 \u043e\u043f\u0438\u0441\u0430\u043d\u043e, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u0441 \u0437\u0430\u043c\u0435\u043d\u043e\u0439 ajax \u043d\u0430 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u044b,<br \/>  \u043d\u0435 \u043c\u0435\u043d\u044f\u044f \u043a\u043e\u0434 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <\/p>\n<p>  \u0422\u0430\u043a\u0430\u044f \u0437\u0430\u043c\u0435\u043d\u0430 \u0434\u0430\u0451\u0442 \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435(\u0442\u0435\u0441\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435), \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u044e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438, <br \/>  \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. <\/p>\n<p>  \u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 <a href=\"http:\/\/94.127.68.13\/jrspc-ws\/demo-chat\/\">\u0447\u0430\u0442-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/a>, \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c <a href=\"https:\/\/github.com\/janson13\/demo-jrspc-ws\">\u043d\u0430 \u0433\u0438\u0442\u0445\u0430\u0431\u0435<\/a>.<br \/>  \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e, \u044f \u043f\u043e\u043f\u044b\u0442\u0430\u044e\u0441\u044c \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. <br \/>  \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 tomcat 7.042.<br \/>  \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 https \u0438 wss (\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u043d\u0435\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u044b\u0439), \u0438 \u043d\u0435 \u0432\u0435\u0434\u0451\u0442 \u043b\u043e\u0433\u043e\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<p>  <a name=\"habracut\"><\/a><\/p>\n<h4>\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/h4>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c, \u0432\u043e\u0437\u043d\u0438\u043a\u0448\u0435\u043c \u043f\u0440\u0438 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c Spring,<br \/>  \u0431\u044b\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u2014 \u043a\u0430\u043a \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u044b\u0437\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 Spring, \u0438\u0437 \u0435\u0433\u043e \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0435\u0439,<br \/>  \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b \u043a http-\u0441\u0435\u0441\u0441\u0438\u0438, \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 StreamInbound, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u043c createWebSocketInbound<br \/>  \u043a\u043b\u0430\u0441\u0441\u0430 <a href=\"http:\/\/www.tomcatexpert.com\/blog\/2012\/05\/01\/how-apache-tomcat-implemented-websocket\">WebSocketServlet<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a \u0441\u0435\u0441\u0441\u0438\u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d? <\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u0432\u044b\u0437\u043e\u0432\u0443 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432,<br \/>  \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0440\u0430\u0431\u043e\u0447\u0435\u043c\u0443 ApplicationContext \u0438\u0437 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 StreamInbound.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u0430\u0432\u0442\u043e\u0432\u0430\u0435\u0440\u0438\u0442\u044c ApplicationContext, \u0447\u0442\u043e\u0431\u044b \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u043d\u0430\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b,<br \/>  \u0432 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 WebSocketServlet \u0438\u043b\u0438 StreamInbound \u2014 \u043d\u0430\u0441 \u0436\u0434\u0451\u0442 \u0440\u0430\u0437\u043e\u0447\u0430\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043d\u0435 \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f, <br \/>  \u0447\u0442\u043e \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0437\u0430\u043a\u043e\u043d\u043d\u043e.<\/p>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0437 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043d\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u0432 Spring,<br \/>  \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0441 http-\u0441\u0435\u0441\u0441\u0438\u0435\u0439, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b \u0431\u044b\u043b \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u043c \u0441\u043f\u0440\u0438\u043d\u0433\u043e\u0432\u044b\u043c \u0431\u0438\u043d\u043e\u043c,<br \/>  \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b \u0445\u0440\u0430\u043d\u0438\u043b\u0441\u044f \u0432 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u043a\u043b\u0430\u0441\u0441\u0430-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443, \u0438\u043c\u0435\u043b \u0431\u044b \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a StreamInbound. <\/p>\n<p>  \u042d\u0442\u043e\u0442 \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 (\u043d\u0430\u0437\u043e\u0432\u0451\u043c \u0435\u0433\u043e ClientManager), \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 http \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043a\u043b\u0438\u0435\u043d\u0442, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442,<br \/>  \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0434\u0438\u043d http handshake-\u0437\u0430\u043f\u0440\u043e\u0441, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e, \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0434 \u0441\u0432\u043e\u0435\u0433\u043e ClientManager. <\/p>\n<p>  \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u043a\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u2014 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c clientManagerId \u0432 \u043e\u0442\u0434\u0430\u0432\u0430\u0435\u043c\u0443\u044e <br \/>  \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 ajax \u0437\u0430\u043f\u0440\u043e\u0441, \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u0437\u0434\u0435\u0441\u044c \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0447\u0435\u0440\u0435\u0437 ajax).<\/p>\n<p>  \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 initializeClientManager \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 <\/p>\n<pre><code class=\"java\">@Controller @Scope(&quot;session&quot;) public class ClientManagerController {      @Autowired        private ClientManager clientManager;                                      @RequestMapping(value = &quot;\/init&quot;, method = RequestMethod.POST)     @ResponseBody     private String initializeClientManager(HttpSession session) {              JSONObject result = new JSONObject();                try{             boolean loged = ClientManagersStorage.checkClientManager(clientManager, session) ;             result.put(&quot;loged&quot;, loged);                     result.put(&quot;clientManagerId&quot;, clientManager.getId());               }catch(Throwable th){             result.put(&quot;error&quot;, th.toString());          }                  return result.toString();              }  <\/code><\/pre>\n<p>  ClientManagersStorage \u2014 \u044d\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043d\u0430\u0448\u0438\u0445 \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0445 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u043e\u0432 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432,<br \/>  \u0438\u043c\u0435\u044e\u0449\u0435\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u043d\u0430 null, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043d\u043e\u0432\u043e\u0433\u043e, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435,<br \/>  \u043f\u043e\u0438\u0441\u043a\u0443 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044e.<\/p>\n<pre><code class=\"java\">public class ClientManagersStorage {      final static private  Map&lt;String, ClientManager&gt; clientManagers = new ConcurrentHashMap &lt;String, ClientManager&gt;();      public static boolean checkClientManager(ClientManager clientManager, HttpSession session) {         ClientManager registeredClientManager = clientManagers.get(clientManager.getId());         if (registeredClientManager == null) {             clientManager.setSession(session);             addClientManager(clientManager);                registeredClientManager = clientManager;                }         return registeredClientManager.getUser() != null;             }     ... } <\/code><\/pre>\n<p>  (\u0432\u043e\u043f\u0440\u043e\u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u0441\u0435\u0441\u0441\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0438\u0436\u0435)<\/p>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043c\u0430\u043f\u0435, \u043f\u043e \u043a\u043b\u044e\u0447\u0443, \u044f\u0432\u043b\u044f\u044e\u0449\u0435\u043c\u0443\u0441\u044f \u0435\u0433\u043e hashCode,<br \/>  \u0438 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u2014 \u0435\u043c\u0443 \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u0442 \u0436\u0435 \u0441\u0430\u043c\u044b\u0439 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440.<\/p>\n<p>  \u0418\u0434 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u2014 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 clientManagerId \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0438\u0434 \u0441\u0432\u043e\u0435\u0433\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u2014 \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043d\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435,<br \/>  \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0441\u0432\u043e\u0439 clientManagerId \u0432 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 createWebSocketInbound \u043a\u043b\u0430\u0441\u0441\u0430 <br \/>  WebSocketConnectorServlet \u2014 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0433\u043e WebSocketServlet.<\/p>\n<pre><code class=\"java\">@Override \tprotected StreamInbound createWebSocketInbound(String paramString, HttpServletRequest request) { \t\tString clientManagerId = request.getParameter(&quot;clientManagerId&quot;);\t\t \t\tClientManager clientManager = ClientManagersStorage.findClientManager(clientManagerId); \t\tif(clientManager == null){ \t\t    return new WebSocketConnection(null); \t\t}\t\t \t\tlog.debug(&quot;new connection&quot;); \t\treturn new WebSocketConnection(clientManager); \t}  <\/code><\/pre>\n<p>  \u0432 \u043d\u0451\u043c, \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f clientManagerId, \u043f\u043e \u043d\u0435\u043c\u0443 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f ClientManager, \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f<br \/>  \u043e\u0431\u044a\u0435\u043a\u0442 WebSocketConnection (\u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0439\u0441\u044f StreamInbound), \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d ClientManager.<\/p>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a ClientManager \u2014 \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0439, \u0438 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0432 \u00ab\u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u043c\u00bb http \u0437\u0430\u043f\u0440\u043e\u0441\u0435,<br \/>  \u0442\u043e \u0438\u0437 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u0441\u0435 \u0441\u043f\u0440\u0438\u043d\u0433\u043e\u0432\u044b\u0435 \u0431\u0438\u043d\u044b, \u0447\u0435\u0440\u0435\u0437 \u0430\u0432\u0442\u043e\u0432\u0430\u0435\u0440\u0435\u043d\u043d\u044b\u0439 \u0432 \u043d\u0435\u0433\u043e <br \/>  ApllicationContext, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0437\u0434\u0435\u0441\u044c, \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e). <\/p>\n<p>  \u041f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 onOpen<br \/>  \u043a\u043b\u0430\u0441\u0441\u0430 WebSocketConnection, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u043a \u043d\u0435\u043c\u0443 ClientManager, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442<br \/>  \u044d\u0442\u043e\u0442 WebSocketConnection, \u0432 \u0441\u0432\u043e\u044e \u043c\u0430\u043f\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043f\u043e \u0438\u0434(\u0445\u044d\u0448\u043a\u043e\u0434\u0443) \u043e\u0431\u044a\u0435\u043a\u0442\u0430.<\/p>\n<pre><code class=\"java\">   @Override     protected void onOpen(WsOutbound outbound) {         if(clientManager != null){            clientManager.addConnection(this);         }         } <\/code><\/pre>\n<p>  (\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0433 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 <br \/>  \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043e\u043a\u043d\u0430\u0445, \u043a\u0430\u0436\u0434\u043e\u0435 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0451 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043d\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.)<\/p>\n<p>  \u041e\u0442\u043a\u0440\u044b\u0432 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u043a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f<br \/>  \u0432 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 onTextMessage \u043a\u043b\u0430\u0441\u0441\u0430 WebSocketConnection.  <\/p>\n<pre><code class=\"java\">    @Override     protected void onTextMessage(CharBuffer message) throws IOException {         try {                                String connectionId = String.valueOf(this.hashCode());             String request = message.toString();             clientManager.handleClientRequest(request, connectionId);                     } catch (Throwable th) {             log.error(&quot;in onTextMessage: &quot; + th);         }     } <\/code><\/pre>\n<p>  \u043c\u0435\u0442\u043e\u0434 handleClientRequest \u043a\u043b\u0430\u0441\u0441\u0430 ClientManager \u2014 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441, \u0438 \u043f\u0438\u0448\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<br \/>  \u0432 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435: <\/p>\n<pre><code class=\"java\">@Autowired     private RequestHandler requestHandler;          public void handleClientRequest(String request, String connectionId) {         log.debug(&quot;handleClientRequest request=&quot; + request);         log.debug(&quot;handleClientRequest user=&quot; + getUser());            \/** handleRequest - never throws exceptions ! *\/         JSONObject response = requestHandler.handleRequest(request, this);                 String responseJson = response.toString();         CharBuffer buffer = CharBuffer.wrap(responseJson);         WebSocketConnection connection = connections.get(connectionId);         try {             connection.getWsOutbound().writeTextMessage(buffer);         } catch (IOException ioe) {             log.error(&quot;in handleClientRequest: in writeTextMessage: &quot; + ioe);         }     } <\/code><\/pre>\n<p>   requestHandler \u2014 \u0430\u0432\u0442\u043e\u0432\u0430\u0435\u0440\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<br \/>   \u0412 \u043d\u0435\u0433\u043e \u0432\u0432\u0430\u0440\u0435\u043d ApllicationContext, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. <\/p>\n<p>   \u0415\u0433\u043e \u043c\u0435\u0442\u043e\u0434 handleRequest, \u0438\u0449\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u043d\u0451\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u043d\u0443\u0436\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u0443,<br \/>   \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u043c\u0435\u0442\u043e\u0434 processAjaxRequest \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u0430 CommonServiceController, \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438. <\/p>\n<p>   \u0422\u0430\u043a\u043e\u0432\u0430 \u043e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. <\/p>\n<p>   \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 ClientManager&#8217;\u0430 http \u0441\u0435\u0441\u0441\u0438\u0435\u0439.<\/p>\n<p>  \u0421\u0435\u0441\u0441\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043e\u0442\u0432\u0430\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0440\u0430\u0432\u0435\u043d 30 \u043c\u0438\u043d\u0443\u0442\u0430\u043c.<br \/>   \u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u2014 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c, \u0438 \u0438\u043d\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u043c \u0441\u0435\u0441\u0441\u0438\u044e<br \/>   \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u043c \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u2014 \u0430 \u0438\u043c\u0435\u043d\u043d\u043e, \u0432 \u0434\u0432\u0443\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445: \u043f\u0435\u0440\u0432\u044b\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u2014 \u043a\u043e\u0433\u0434\u0430 \u043a\u0442\u043e-\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 <br \/>   \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438 \u0432\u0442\u043e\u0440\u043e\u0439, \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0437\u0430\u043a\u0440\u044b\u043b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>   \u041f\u0435\u0440\u0432\u044b\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438: <\/p>\n<pre><code class=\"java\">  public class ClientManager{     \t    public void setSession(HttpSession session) { \t        \/** session will be invalidated at connection removing *\/ \t        session.setMaxInactiveInterval(Integer.MAX_VALUE);\/\/69.04204112011317 years \t        this.session = session; \t        new Thread(new Runnable() {             \t            @Override \t            public void run() { \t                \/** Giving time to client, for establish websocket connection. *\/ \t                try {Thread.sleep(60000);} catch (InterruptedException ignored) {} \t                \/** if client not connected via websocket until this time - it is bot *\/ \t                if (connections.size() == 0) {removeMe();}                                 \t            }             \t        }).start();         \t    }\t     \t    private void removeMe() {ClientManagersStorage.removeClientManager(this);} \t         \t...   }   <\/code><\/pre>\n<p>   \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u2014 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 onClose \u043a\u043b\u0430\u0441\u0441\u0430 WebSocketConnection: <\/p>\n<pre><code class=\"java\">public class WebSocketConnection{ \t   @Override \t    protected void onClose(int status) { \t        if(clientManager != null){ \t            clientManager.removeConnection(this); \t        }         \t    }         ...    }         public class ClientManager{      \t   public void removeConnection(WebSocketConnection webSocketConnection) { \t        String connectionId = getObjectHash(webSocketConnection); \t        connections.remove(connectionId); \t        if (connections.size() == 0) { \t            log.debug(&quot;removeConnection before wait:  connections.size()=&quot; + connections.size()); \t            \/** may be client just reload page? *\/ \t            try {Thread.sleep(waitForReloadTime);} catch (Throwable ignored) {}             \t            if (connections.size() == 0) { \t                \/** no, client leave us (page closed in browser)*\/       \t                ClientManagersStorage.removeClientManager(this);  \t                log.debug(&quot;client &quot; + getId() + &quot; disconnected&quot;);                     \t            } \t        } \t    }             ...    }    <\/code><\/pre>\n<p>   \u0421\u0435\u0441\u0441\u0438\u044f \u0438\u043d\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 removeClientManager \u043a\u043b\u0430\u0441\u0441\u0430 ClientManagersStorage:<\/p>\n<pre><code class=\"java\">public static void removeClientManager(ClientManager clientManager) {                 ClientManager removed  = clientManagers.remove(clientManager.getId());             if(removed == null){return;}         User user = removed.getUser();         if(user != null){                             Broadcaster.broadcastCommand(&quot;userPanel.setLogedCount&quot;, UserService.logedCount.decrementAndGet());            }                         Broadcaster.broadcastCommand(&quot;userPanel.setOnlineCount&quot;, ClientManagersStorage.getClientManagersCount());                     try {             clientManager.getSession().invalidate();             clientManager.setSession(null);              } catch (Throwable th) {             log.error(&quot;at removeClientManager: &quot; + th);         }             }   <\/code><\/pre>\n<p>   \u0418\u0437 \u044d\u0442\u043e\u0433\u043e \u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c \u0447\u0438\u0441\u043b\u043e<br \/>   \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u044d\u0442\u0438\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u2014 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u043d\u0438\u0436\u0435).<\/p>\n<p>   \u0414\u043b\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 Broadcaster,<br \/>   \u0438\u043c\u0435\u044e\u0449\u0438\u0439 \u0434\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430: broadcastCommand \u0438 sendCommandToUser:<\/p>\n<pre><code class=\"java\">public class Broadcaster{       public static void broadcastCommand(String method, Object params) {         for (ClientManager clientManager : ClientManagersStorage.getClientManagers().values()) {             clientManager.sendCommandToClient(method, params);         }     }          public static void sendCommandToUser(Long userId, String method, Object params) {              List&lt;ClientManager&gt; userClientManagers = ClientManagersStorage.findUserClientManagers(userId);         for(ClientManager clientManager: userClientManagers){             clientManager.sendCommandToClient(method, params);         }             }   }   <\/code><\/pre>\n<p>   \u043c\u0435\u0442\u043e\u0434 sendCommandToClient \u043a\u043b\u0430\u0441\u0441\u0430 \u0421lientManager \u2014 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"java\">public void sendCommandToClient(String method, Object params) {         for(WebSocketConnection connection: connections.values()){             sendCommandToClientConnection(connection, method, params);                      }             }          private void sendCommandToClientConnection(WebSocketConnection connection, String method, Object params) {         JSONObject commandBody = new JSONObject();         if(params == null){params = new JSONObject();}         commandBody.put(&quot;method&quot;, method);         commandBody.put(&quot;params&quot;, params);                 CharBuffer buffer = CharBuffer.wrap(commandBody.toString());         try {             connection.getWsOutbound().writeTextMessage(buffer);                              } catch (IOException ioe) {             log.error(&quot;in sendCommandToClient: in writeTextMessage: &quot; + ioe);         }                     } <\/code><\/pre>\n<p>   \u041d\u0430 \u044d\u0442\u043e\u043c, \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043c, \u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439.<\/p>\n<h4>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/h4>\n<p>  \u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438:<\/p>\n<p>   \u043f\u0435\u0440\u0432\u0430\u044f \u2014 handshake \u043d\u0430 ajax, \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0421lientManager&#8217;\u0430,<br \/>   \u0432\u0442\u043e\u0440\u0430\u044f \u2014 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043d\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442, \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 jsrpc \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u043d\u0438\u0445 \u043e\u0442\u0432\u0435\u0442\u043e\u0432,<br \/>   \u0438 \u0442\u0440\u0435\u0442\u044c\u044f \u2014 \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<p>   \u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u2014 \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f:<\/p>\n<p>   \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0410\u043d\u0433\u0443\u043b\u044f\u0440, \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e http-\u0441\u0435\u0441\u0441\u0438\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 ajax, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f $http:<\/p>\n<pre><code class=\"javascript\">\tvar appName = &quot;jrspc-ws&quot;;  \tvar secured = document.location.protocol == &quot;https:&quot; ? &quot;s&quot; : &quot;&quot;; \tvar HttpSessionInitializer = {url: &quot;http&quot;+secured+&quot;:\/\/&quot;+ document.location.host +&quot;\/&quot;+appName+&quot;\/init&quot;}; \t \t\/** called from root-controller.js after its initialization *\/\t \tHttpSessionInitializer.init = function($http) {\t    \t    \t \t    \t$http.post(this.url, &quot;&quot;).success(function(response){ \t\t\t\t\tif (response.error) { \t\t\t\t\t\terror(response.error); \t\t\t\t\t} else {\t\t\t\t\t \t\t\t\t\t\tloged = response.loged;\t\t\t\t\t \t\t\t\t\t\tServer.initialize(&quot;ws&quot;+secured+&quot;:\/\/&quot;+ document.location.host +&quot;\/&quot;+appName+&quot;\/ws?clientManagerId=&quot;+response.clientManagerId); \t\t\t\t\t\tif(loged){Listeners.notify(&quot;onLogin&quot;);}\t\t\t\t\t \t\t\t\t\t}    \t\t \t    \t}).error(function() {error(&quot;network error!&quot;);});    \t    \t    \t \t} <\/code><\/pre>\n<p>   \u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u044d\u0442\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 initializeClientManager \u043a\u043b\u0430\u0441\u0441\u0430 ClientManagerController, <br \/>   \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u0432\u044b\u0448\u0435, \u0432 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<p>   \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u043e\u043a\u0435\u0442\u043d\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Server.initialize:<\/p>\n<pre><code class=\"javascript\">  \tconnector.initialize = function(url) { \t\tconnector.url = url; \t\ttry { \t\t\tconnector.connect(url); \t\t\treturn true; \t\t} catch (ex) { \t\t\tp(&quot;in connector.initialize: &quot; + ex); \t\t\treturn false; \t\t} \t} <\/code><\/pre>\n<p>   connector \u2014 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 Server, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043d\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435<br \/>   (\u0435\u0433\u043e \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 <a href=\"https:\/\/github.com\/janson13\/demo-jrspc-ws\/blob\/master\/jrspc-ws\/src\/main\/public\/demo-chat\/ws-connector.js\">ws-connector.js<\/a>)<\/p>\n<p>   \u043a\u043e\u0434 \u0438\u0437 ws-connector.js, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 jrspc: <\/p>\n<pre><code class=\"javascript\">  \tServer.socketRequests = {};  \tvar requestId = 0;  \tfunction sendSocket(service, method, params, successCallback, errorCallback, control) { \t\tif (!checkSocket()) {return;} \t\trequestId++; \t\t \t\tif(!params){params = [];} \t\tif(!isArray(params)){params = [params];} \t\t \t\tvar data = { \t\t\tservice : service, \t\t\tmethod : method, \t\t\tparams : params, \t\t\trequestId : requestId \t\t}; \t\tServer.socketRequests[&quot;request_&quot; + requestId] = { \t\t\tsuccessCallback : successCallback, \t\t\terrorCallback : errorCallback, \t\t\tcontrol : control \t\t};  \t\tif (control) {control.disabled = true;} \t \t\tvar message = JSON.stringify(data); \t\tlog(&quot;sendSocket: &quot;+message); \t\tconnector.socket.send(message); \t} \t... \tServer.call = sendSocket; <\/code><\/pre>\n<p>   \u043a\u043e\u0434 \u0438\u0437 ws-connector.js, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, <br \/>   \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434: <\/p>\n<pre><code class=\"javascript\"> \t\tconnector.socket.onmessage = function(message) { \t\t\tvar data = message.data; \t\t\tvar response = JSON.parse(data); \t\t\tvar requestId = response.requestId; \t\t\tif (requestId) {\/** server return response *\/\t\t\t\t\t \t\t\t\tvar control = Server.socketRequests[&quot;request_&quot; + requestId].control; \t\t\t\tif (control) {control.disabled = false;}\t\t\t\t\t\t\t\t\t \t\t\t\tif (response.error) { \t\t\t\t\tvar errorCallback = Server.socketRequests[&quot;request_&quot; + requestId].errorCallback; \t\t\t\t\tif (errorCallback) { \t\t\t\t\t\ttry { \t\t\t\t\t\t\terrorCallback(response.error); \t\t\t\t\t\t} catch (ex) { \t\t\t\t\t\t\terror(&quot;in connector.socket.onmessage errorCallback: &quot; + ex + &quot;, data=&quot; + data); \t\t\t\t\t\t} \t\t\t\t\t}else{ \t\t\t\t\t\terror(response.error); \t\t\t\t\t} \t\t\t\t} else {\t \t\t\t\t\tvar successCallback = Server.socketRequests[&quot;request_&quot; + requestId].successCallback; \t\t\t\t\tif (successCallback) { \t\t\t\t\t\ttry { \t\t\t\t\t\t\tsuccessCallback(response.result); \t\t\t\t\t\t} catch (ex) { \t\t\t\t\t\t\terror(&quot;in connector.socket.onmessage successCallback: &quot; + ex + &quot;, data=&quot; + data); \t\t\t\t\t\t} \t\t\t\t\t} \t\t\t\t} \t\t\t\tdelete Server.socketRequests[&quot;request_&quot; + requestId]; \t\t\t} else { \t\t\t\t\/** server call client or broadcast *\/ \t\t\t\tvar method = eval(response.method); \t\t\t\tvar params = response.params; \t\t\t\ttry { \t\t\t\t\tmethod(params); \t\t\t\t} catch (ex) { \t\t\t\t\terror(&quot;in connector.socket.onmessage call method: &quot; + ex + &quot;, data=&quot; + data); \t\t\t\t} \t\t\t} \t\t};  <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u044e \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0443,<br \/>   \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0443\u044e \u0437\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0447\u0430\u0442\u0430 \u2014 \u0432 \u0434\u0432\u0443\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 (<a href=\"https:\/\/github.com\/janson13\/demo-jrspc-ws\/blob\/master\/jrspc-ws\/src\/main\/public\/demo-chat\/chat-controller.js\">chat-controller.js<\/a>):<\/p>\n<pre><code class=\"javascript\">\t\tself.sendMessage = function(command){ \t    \tvar message = {to: (self.sendPrivate ? self.privateTo : &quot;all&quot;), from: userPanel.user.login, text: self.newMessage, clientTime: new Date().getTime()}; \t     \tServer.call(&quot;chatService&quot;, &quot;dispatchMessage&quot;, message, \t    \tfunction(){\tself.newMessage = &quot;&quot;; self.$digest(); }, function(error){self.onError(error);}, command); \t    }  \t                \t    \/** called from server *\/ \t    self.onChatMessage = function (message){ \t \t    \tmessage.isPrivate = (message.to != &quot;all&quot;); \t    \tself.messages.push(message); \t    \tself.$digest();\t \t    \tchatConsole.scrollTop = chatConsole.clientHeight + chatConsole.scrollHeight;    \t \t    }  <\/code><\/pre>\n<p>   \u0438 \u043e\u0434\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435:<\/p>\n<pre><code class=\"java\">\t\t@Component \t    public class ChatService extends AbstractService{ \t        \t\t    @Autowired \t\t    private UserManager userManager; \t\t     \t\t    @Secured(&quot;User&quot;) \t\t    @Remote \t\t    public void dispatchMessage(ChatMessage message){  \t\t        message.setServerTime(new Date().getTime());   \t\t        String to = message.getTo(); \t\t        if(&quot;ALL&quot;.equalsIgnoreCase(to)){                    \t\t            Broadcaster.broadcastCommand(&quot;chatPanel.onChatMessage&quot;, message); \t\t        }else{             \t\t            User fromUser = getUser(); \t\t            message.setFrom(fromUser.getLogin()); \t\t            User toUser = userManager.findByLogin(to);     \t\t            if(toUser == null){throw new RuntimeException(&quot;User &quot;+to+&quot; not found!&quot;);}              \t\t            Broadcaster.sendCommandToUser(toUser.getId(), &quot;chatPanel.onChatMessage&quot;, message);         \t\t            Broadcaster.sendCommandToUser(fromUser.getId(), &quot;chatPanel.onChatMessage&quot;, message);      \t\t        }                 \t\t    }                        \t    }  <\/code><\/pre>\n<p>   \u0422\u0435\u0441\u0442\u044b \u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c, \u043f\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 1000 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0434\u043b\u044f ajax \u0438 websockets:<\/p>\n<p>   \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e: ajax (3474, 3380, 3377) ws (1299, 1113, 1054) <br \/>   \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e: ajax (1502, 1515, 1469) ws (616, 637, 632)<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u043a\u043e\u0434 \u0442\u0435\u0441\u0442\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\t\tfunction testController($scope){\t \t\t\tvar self = $scope;\t \t\t    \t\t    self.maxIterations = 1000; \t\t    self.testIterations = self.maxIterations; \t\t    self.testStart = 0; \t\t    self.testEnd = 0; \t\t         \t\t    self.testForSpeedSerial = function(command){ \t\t    \tif(self.testStart == 0){self.testStart = now();} \t\t    \tif(--self.testIterations &lt;= 0){ \t\t    \t\tvar duration = now() - self.testStart; \t\t    \t\talert(&quot;testForSpeedSerial duration=&quot;+duration);     \t\t    \t\tself.testStart = 0; \t\t    \t\tself.testIterations = self.maxIterations; \t\t    \t\treturn; \t\t    \t} \t\t    \tServer.call(&quot;userService&quot;, &quot;testForSpeed&quot;, &quot;&quot;, function(){ self.testForSpeedSerial(command); }, error, command);    \t \t\t    } \t\t     \t\t    self.testForSpeedParallelResponses = 0; \t\t     \t\t    self.testForSpeedParallel = function(command){\t \t\t    \tself.testStart = now();    \t \t\t    \tfor(var i = 0; i &lt; self.testIterations; i++){ \t\t    \t\tServer.call(&quot;userService&quot;, &quot;testForSpeed&quot;, &quot;&quot;,  \t\t    \t\t\t\tfunction(){ \t\t    \t\t\t       self.testForSpeedParallelResponses++ ;  \t\t    \t\t\t       if(self.testForSpeedParallelResponses &gt;= self.maxIterations){ \t\t    \t\t\t    \t      \tvar duration = now() - self.testStart; \t\t\t\t\t\t\t\t    \talert(&quot;testForSpeedParallel duration=&quot;+duration);    \t\t \t\t\t\t\t\t\t\t    \tself.testForSpeedParallelResponses = 0; \t\t    \t\t\t       } \t\t    \t\t\t\t}, error, command);  \t\t    \t}    \t \t\t    }  \t\t}     <\/code><\/pre>\n<p>   \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 testForSpeed: <\/p>\n<pre><code class=\"java\">     @Remote public void testForSpeed(){}  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412\u0441\u0435 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f \u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 \u0431\u0443\u0434\u0443 \u043f\u0440\u0438\u043d\u044f\u0442\u044b \u0441 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u043d\u043e\u0441\u0442\u044c\u044e. <\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/220015\/\"> http:\/\/habrahabr.ru\/post\/220015\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t\u0421\u043a\u0430\u0436\u0443 \u0441\u0440\u0430\u0437\u0443, \u0447\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u2014 <a href=\"http:\/\/habrahabr.ru\/post\/187822\/\">\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442<\/a>.<\/p>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043c\u044b &quot;<a href=\"http:\/\/habrahabr.ru\/post\/211937\/\">\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u044b\u0437\u043e\u0432 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0432 \u043e\u0434\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445<\/a>&quot;, \u0437\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u043d\u044b ajax \u043d\u0430 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u044b, <br \/>  \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0430(jrspc), \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0432\u044b\u0448\u0435\u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0439 \u0442\u0435\u043c\u0435. <\/p>\n<p>  \u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u2014 \u0431\u044b\u043b \u043e\u043f\u0438\u0441\u0430\u043d \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0432\u044b\u0437\u043e\u0432\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c ajax.<\/p>\n<p>  \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u2014 \u043e\u043f\u0438\u0441\u0430\u043d\u043e, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u0441 \u0437\u0430\u043c\u0435\u043d\u043e\u0439 ajax \u043d\u0430 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u044b,<br \/>  \u043d\u0435 \u043c\u0435\u043d\u044f\u044f \u043a\u043e\u0434 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <\/p>\n<p>  \u0422\u0430\u043a\u0430\u044f \u0437\u0430\u043c\u0435\u043d\u0430 \u0434\u0430\u0451\u0442 \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435(\u0442\u0435\u0441\u0442\u044b \u0432 \u043a\u043e\u043d\u0446\u0435), \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u044e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438, <br \/>  \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. <\/p>\n<p>  \u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 <a href=\"http:\/\/94.127.68.13\/jrspc-ws\/demo-chat\/\">\u0447\u0430\u0442-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/a>, \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c <a href=\"https:\/\/github.com\/janson13\/demo-jrspc-ws\">\u043d\u0430 \u0433\u0438\u0442\u0445\u0430\u0431\u0435<\/a>.<br \/>  \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e, \u044f \u043f\u043e\u043f\u044b\u0442\u0430\u044e\u0441\u044c \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. <br \/>  \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 tomcat 7.042.<br \/>  \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 https \u0438 wss (\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u043d\u0435\u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u044b\u0439), \u0438 \u043d\u0435 \u0432\u0435\u0434\u0451\u0442 \u043b\u043e\u0433\u043e\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-220015","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/220015","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=220015"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/220015\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=220015"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=220015"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=220015"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}