Скажу сразу, стандартная реализация такого взаимодействия существует .
Однако, поскольку данная статья является продолжением темы «Легкий вызов методов удаленного обслуживания в одностраничных приложениях» , здесь будет альтернативная схема взаимодействия, необходимая для замены ajax на вебсокеты, в контексте подхода (jrspc), описанного в теме выше.
В первой статье был описан механизм вызова методов сервиса с помощью ajax. В данной статье описано, как можно реализовать этот механизм, заменив ajax на вебсокеты, не меняя при этом код бизнес-логики приложения.
Такая замена обеспечивает более быстрое соединение (тесты в конце), экономию памяти сервера и добавляет возможность вызова клиентских методов с сервера.
Для демонстрации небольшой приложение для чата , с исходным кодом на GitHub .
На примере анализа которых я попытаюсь объяснить, как реализованы клиентская и серверная части такого взаимодействия.
Приложение работает на сервере Tomcat 7.042. Поддерживает https и wss (непроверенный сертификат) и не ведет логи на сервере.
Серверная часть
Основным вопросом, который возник при организации взаимодействия вебсокета с приложением Spring, был вопрос о том, как обеспечить вызов компонентов Spring из его областей видимости, привязанных к http-сессии, из объекта StreamInbound, возвращаемого методом класса createWebSocketInbound. Вебсокетсервлет , который не привязан к сессии? Чтобы обеспечить необходимый функционал для вызова методов серверного компонента, нам нужно каким-то образом получить доступ к рабочему ApplicationContext из потомка StreamInbound. Если мы попытаемся автоматизировать ApplicationContext, чтобы использовать его для получения нужных нам компонентов в наследника WebSocketServlet или StreamInbound, нас ждет разочарование, поскольку он не будет инициализирован, что абсолютно законно.Чтобы получить доступ к компонентам из контекстов Spring, которые связаны с сеансом http из обработчика веб-сокета, нам нужно создать объект, который будет сессионным bean-компонентом Spring и который будет храниться в статическом объекте класса хранилища, который может к которому будет обращаться, будет преемником StreamInbound. Этот объект сеанса (назовем его ClientManager) создается во время установления http-соединения.
Соответственно, клиент, прежде чем начать взаимодействовать с сервером через вебсокет, должен сделать один http-запрос на рукопожатие, в результате которого он должен получить id своего ClientManager. Результат этого запроса можно передать в клиентский код двумя способами — вставить clientManagerId в сгенерированную страницу, либо через ajax-запрос со статической страницы (здесь реализован вариант через ajax).
Этот запрос обрабатывается в методе InitializeClientManager контроллера сеанса:
ClientManagersStorage — хранилище наших сессионных менеджеров клиентов, в котором есть методы проверки менеджера на нуль, создания нового, добавления в хранилище, поиска и удаления.@Controller @Scope("session") public class ClientManagerController { @Autowired private ClientManager clientManager; @RequestMapping(value = "/init", method = RequestMethod.POST) @ResponseBody private String initializeClientManager(HttpSession session) { JSONObject result = new JSONObject(); try{ boolean loged = ClientManagersStorage.checkClientManager(clientManager, session) ; result.put("loged", loged); result.put("clientManagerId", clientManager.getId()); }catch(Throwable th){ result.put("error", th.toString()); } return result.toString(); }
public class ClientManagersStorage {
final static private Map<String, ClientManager> clientManagers = new ConcurrentHashMap <String, ClientManager>();
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;
}
.
}
(вопрос управления жизненным циклом сессии будет рассмотрен чуть ниже)
Как видите, менеджеры хранятся в статической карте, с использованием ключа, который является их хэш-кодом, и когда пользователь перезагружает страницу, ему назначается тот же самый менеджер.
Идентификатор этого менеджера передается клиенту в переменной ответа clientManagerId. После того как клиент получил идентификатор своего менеджера, он может открыть соединение через веб-сокет, передав свой clientManagerId в единственном параметре запроса на соединение.
Запрос на открытие этого соединения обрабатывается в методе createWebSocketInbound класса WebSocketConnectorServlet, реализации абстрактного WebSocketServlet. @Override
Теги: #spring #websockets #jrspc-ws #Разработка сайтов #JavaScript #java
-
Обучение Сертификации Sql Server
19 Oct, 24 -
Обратные Ссылки И Важность Seo В Аризоне
19 Oct, 24 -
Банки Развития И Etf, Инвестирующие В Них
19 Oct, 24 -
Печать Pdf-Документа В Виде Буклета
19 Oct, 24 -
(Fo) Xmarks
19 Oct, 24 -
Воссоздание Подтаблицы В Таблице В Angularjs
19 Oct, 24