В прошлом посте я выложил библиотеку на GWT, которая оборачивает sockJS, тем самым делая доступным протокол websocket для GWT. В этом посте я хочу предложить архитектуру, для GWT приложения, которое использует веб сокеты. Сразу же ссылка на проект на гитхабе
Приложение будет состоять из серверной и клиентской части. Клиент по кнопке будет отправлять два числа на сервер (например, 2 и 3), сервер будет возвращать сумму этих чисел, и выражение, по которому он эту сумму написал (2+3). Ну и дополнительно пусть возвращает текущее время.
Вообще фишка GWT в том, что одни и те же классы могут быть использованы так и на клиенте, так и на сервере, этого же хочется и для приложения с вебсокетами. Также хочется разделить серверную и клиентскую часть с возможностью заменить какую-либо не трогая остальное. Напрашивается следующая структура модулей:
Создается модуль DTO, в котором объявлены интерфейсы DTO объектов и выполнены их реализации. Этот модуль используют два других модуля: GWT модуль и WebSocket Server модуль. Здесь ссылка на демо-проект, сделанный по данной архитектуре.
Приложение будет состоять из серверной и клиентской части. Клиент по кнопке будет отправлять два числа на сервер (например, 2 и 3), сервер будет возвращать сумму этих чисел, и выражение, по которому он эту сумму написал (2+3). Ну и дополнительно пусть возвращает текущее время.
Вообще фишка GWT в том, что одни и те же классы могут быть использованы так и на клиенте, так и на сервере, этого же хочется и для приложения с вебсокетами. Также хочется разделить серверную и клиентскую часть с возможностью заменить какую-либо не трогая остальное. Напрашивается следующая структура модулей:
Создается модуль DTO, в котором объявлены интерфейсы DTO объектов и выполнены их реализации. Этот модуль используют два других модуля: GWT модуль и WebSocket Server модуль. Здесь ссылка на демо-проект, сделанный по данной архитектуре.
Dto модуль
Как я писал ранее для dto нужно объявлять и реализовывать интерфейсы. Это нужно для конвертации данных в json и обратно в условиях gwt-autobean и отсутствия рефлексии.
Информация, от клиента к серверу (те самые 2 числа):
Информация, от клиента к серверу (те самые 2 числа):
public interface ClientInfo { Integer getA(); void setA(Integer a); Integer getB(); void setB(Integer b); }От сервера к клиенту для сложности пусть летит объект в объекте. Внутренний объект будет содержать время:
public interface ServerAddInfo { Date getTime(); void setTime(Date time); }А внешний задачу, результат и объект со временем:
public interface ServerInfo { Integer getResult(); void setResult(Integer result); String getProblem(); void setProblem(String problem); ServerAddInfo getServerAddInfo(); void setServerAddInfo(ServerAddInfo serverAddInfo); }Реализовать интерфейсы нужно в этом же модуле и делается это без проблем.
Server модуль
Этот мануал рассказывает как за несколько минут сделать серверное websocket приложение. В моем случае суть приложения состоит в контроллере:
@Controller public class WebSocketController { @Autowired private SimpMessagingTemplate messagingTemplate; @MessageMapping("/say") public void say(ClientInfoImpl clientInfoImpl) { int a = clientInfoImpl.getA(); int b = clientInfoImpl.getB(); String problem = a + "+" + b; int result = a + b; sendResult(new ServerInfoImpl(problem, result, new ServerAddInfoImpl(new Date()))); } private void sendResult(ServerInfoImpl serverInfoImpl) { messagingTemplate.convertAndSend("/topic/info", serverInfoImpl); } }Нужно заметить, что сервер должен работать не с интерфейсами, а с реализациями. Это касается только методов, где происходит конвертация объектов в json. И еще раз хочу обратить внимание, что метод sendResult может быть вызван не только в ответ на сообщение от клиента, но и в любой момент.
Client модуль
Этот мануал
рассказывает как за несколько минут сделать клиентское websocket
приложение. Суть приложения заключается в создании WS компонента:
//create WS configuration WSConfiguration<ClientInfo, ServerInfo> wsConfiguration = new WSConfiguration<ClientInfo, ServerInfo>() .withUrl("http://127.0.0.1:8080/websocketservice") //ws URL .withSubscribeUrl("/topic/info") //URL to subscribe .withGClass(ServerInfo.class) //dto class for Getting Data .withSClass(ClientInfo.class) //dto class for Sending Data .withAutoBeanFactory(GWT.<DtoFactory>create(DtoFactory.class)); //factory //creating component final WSComponent<ClientInfo, ServerInfo> wsComponent = new WSComponent<>(wsConfiguration); //setting callback for income messages wsComponent.setCallback(new WSCallback<ServerInfo>() { @Override public void onMessage(ServerInfo serverInfo) { String msg = serverInfo.getProblem() + "=" + serverInfo.getResult(); msg += " " + serverInfo.getServerAddInfo().getTime(); Window.alert(msg); } });Интерфейсы dto передаются в конфигурацию. Отправка сообщения осуществляется таким образом:
wsComponent.send(new ClientInfoImpl(3,2), "/app/say");
Сборка
Я сделал так, чтобы клиентская и серверная часть собирались в разные war. Тогда они получаются независимыми друг от друга, а единственная связь между ними: зависимость от общего модуля dto.
Комментариев нет :
Отправить комментарий