В прошлом посте я выложил библиотеку на 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.

Комментариев нет :
Отправить комментарий