Так, с REST API разобрались. Там есть ендпоинты, в которые можно швырять реквесты и получать ожидаемые респонсы, запихивая их в модели. А как же быть с WebSocket API, в основе которого лежит wss соединение. Клиент создает постоянное соединение с сервером и отправляет туда данные (тоже например в json формате) и получает ответы (необязательно), а также отправляет уведомления о том, что сообщение принято.
Ладно, как создать wss соединение с сервером? Подключим для начала через мавен библиотеку:
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp-ws</artifactId> <version>3.4.1</version> </dependency>
Потом создаем новый класс, который будет поддерживать соединение и отвечать на запросы:
public final class WebSocketClient implements WebSocketListener
В этом классе заимплементим метод, который запускает соединение:
private final ExecutorService writeExecutor = Executors.newSingleThreadExecutor(); private WebSocket sharedConnection; private int msgNumber = 900; public void run(String token) throws IOException, InterruptedException { String wssUrl = ConfigurationInstance.getInstance().getWssUrl(); // Получаем адрес wss api через конфигурацию нашу publicToken = token; OkHttpClient client = new OkHttpClient.Builder() .readTimeout(0, TimeUnit.MILLISECONDS) .build(); Log.console(\"Connecting to websocket...\"); Request request = new Request.Builder() // Добавляем актуальные хедеры для нашего апи .url(wssUrl) .addHeader(\"Authorization\", \"Bearer \" + publicToken) .addHeader(\"Sec-WebSocket-Protocol\", \"json\") .addHeader(\"User-Agent\", \"\") .addHeader(\"Accept-Language\", \"ru-RU\") .build(); WebSocketCall.create(client, request).enqueue(this); // Trigger shutdown of the dispatcher's executor so this process can exit cleanly. client.dispatcher().executorService().shutdown(); } @Override public void onOpen(final WebSocket webSocket, Response response) { writeExecutor.execute(new Runnable() { @Override public void run() { Log.console(\"Client '\" + publicToken + \"' ONLINE\"); sharedConnection = webSocket; } }); }
И файналли создаем метод который триггерится когда приходит сообщение с сервера. Здесь мы уже конструируем базовое общение с сервером. Например, если приходит сообщение, на которое нужно подтверждение о получении, то отправляем его. А если приходит сообщение ping, отвечаем pong, таким образом давая понять, что соединение не разорвано:
@Override public void onMessage(ResponseBody message) throws IOException { String wsServerMessage = message.string(); Log.console(\"< RECEIVED MESSAGE: \" + wsServerMessage); JsonParser parser = new JsonParser(); JsonElement element = parser.parse(wsServerMessage); JsonArray wsServerMessageArr = element.getAsJsonArray(); String messageType = wsServerMessageArr.get(0).toString(); String messageName = wsServerMessageArr.get(2).toString(); String receivedMsgNumber = wsServerMessageArr.get(1).toString(); if (Objects.equals(messageType, \"1\")) { // Сообщение типа 1 - нужно ответить что принял его JsonElement wsData = wsServerMessageArr.get(3); int answerType = 2; String ackMess = \"[\" + answerType + \",\" + msgNumber++ + \",\" + receivedMsgNumber + \"]\"; Log.console(\"> SENDING MESSAGE: \" + ackMess); sharedConnection.sendMessage(RequestBody.create(TEXT, ackMess)); // Отправляем } else if (Objects.equals(messageType, \"0\")) { // 0 Сообщение типа 0 - отвечать не надо if (Objects.equals(messageName, \"\\\"svc.ping\\\"\")) { // Но если это пинг, то пингануть в ответ int answerType = 0; String answerMessageName = \"svc.pong\"; String sendMsg = \"[\" + answerType + \",\" + msgNumber++ + \",\\\"\" + answerMessageName + \"\\\"]\"; Log.console(\"> SENDING MESSAGE: \" + sendMsg); sharedConnection.sendMessage(RequestBody.create(TEXT, sendMsg)); } } message.close(); }
Далее в этом же классе реализуем методы, которые будут отправлять определенные сообщения на сервер при получении от него каких-то данных. Тут уже всё зависит от вашего апи, какие активности нужно покрыть. Этого я уже показывать не буду, разобраться далее не сложно.
Стоит отметить, что описанное вами далее специфичное общение сервером не отменяет вышеперечисленного базового общения, т.е. если на какое-то сообщение с сервера нужен определенного формата ответ, это не отменяет того, что сначала на него нужно ответить подтверждением получения, а потом уже отправлять ответ. Также и сервер вам будет отвечать подтверждениями получения ваших сообщений, можно это тоже обрабатывать и как минимум писать в лог.
Для начала понимания материала хватит, дальше изи должно быть.
I’m using Postman to test an existing REST API. This API calls async functions on the server which return a response over a websocket using StompJS.