Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Использование кодировщиков и декодировщиков

Java API для веб-сокетов обеспечивает поддержку преобразования между сообщениями веб-сокетов и пользовательскими типами Java с использованием кодировщиков и декодировщиков. Кодировщик берёт объект Java и создаёт представление, которое может быть передано в виде сообщения веб-сокета. Например, кодировщики обычно создают JSON, XML или бинарные представления. Декодировщик выполняет обратную функцию. Он читает сообщение веб-сокета и создаёт объект Java.

Этот механизм упрощает приложения веб-сокетов, поскольку он отделяет бизнес-логику от сериализации и десериализации объектов.

Здесь рассматриваются следующие темы:

Реализация кодировщика для преобразования объектов Java в сообщения веб-сокетов

Процедура реализации и использования кодировщиков в конечных точках следующая.

  1. Реализуйте один из следующих интерфейсов:

    • Encoder.Text<T> для текстовых сообщений

    • Encoder.Binary<T> для бинарных сообщений

      Эти интерфейсы определяют метод encode. Реализуйте класс кодировщика для каждого пользовательского типа Java, который вы хотите отправить в виде сообщения веб-сокета.

  2. Добавьте имена ваших реализаций кодировщика в необязательный параметр encoders аннотации @ServerEndpoint.

  3. Используйте sendObject(Object data) метод интерфейсов RemoteEndpoint.Basic или RemoteEndpoint.Async для отправки ваших объектов в виде сообщений. Контейнер ищет кодировщик, соответствующий вашему типу, и использует его для преобразования объекта в сообщение веб-сокета.

Например, если у вас есть два типа Java (MessageA и MessageB), которые вы хотите отправить в виде текстовых сообщений, реализуйте Encoder.Text<MessageA> и Encoder.Text<MessageB> взаимодействующие следующим образом:

public class MessageATextEncoder implements Encoder.Text<MessageA> {
   @Override
   public void init(EndpointConfig ec) { }
   @Override
   public void destroy() { }
   @Override
   public String encode(MessageA msgA) throws EncodeException {
      // Чтение свойств msgA и конвертация в JSON...
      return msgAJsonString;
   }
}

Реализуйте Encoder.Text<MessageB> аналогичным образом. Затем добавьте параметр encoders в аннотацию @ServerEndpoint следующим образом:

@ServerEndpoint(
   value = "/myendpoint",
   encoders = { MessageATextEncoder.class, MessageBTextEncoder.class }
)
public class EncEndpoint { ... }

Теперь вы можете отправлять объекты MessageA и MessageB как сообщения веб-сокета, используя метод sendObject следующим образом:

MessageA msgA = new MessageA(...);
MessageB msgB = new MessageB(...);
session.getBasicRemote.sendObject(msgA);
session.getBasicRemote.sendObject(msgB);

Как и в этом примере, вы можете иметь более одного кодировщика для текстовых сообщений и более одного кодировщика для бинарных сообщений. Как и конечные точки, объекты кодировщика связаны с одним и только одним подключением веб-сокета, поэтому в любой момент времени только один поток выполняет код объекта кодировщика.

Реализация декодировщика для преобразования сообщений веб-сокетов в объекты Java

Процедура для реализации и использования декодировщиков в конечных точках следующая.

  1. Реализуйте один из следующих интерфейсов:

    • Decoder.Text<T> для текстовых сообщений

    • Decoder.Binary<T> для бинарных сообщений

      Эти интерфейсы определяют методы willDecode и decode.

      Примечание:

      В отличие от кодировщиков, можно указать не более одного декодировщика для бинарных сообщений и один декодировщик для текстовых сообщений.

  2. Добавьте имена ваших реализаций декодировщика в необязательный параметр decoders аннотации @ServerEndpoint.

  3. Используйте аннотацию @OnMessage в конечной точке, чтобы назначить метод, который принимает ваш пользовательский тип Java в качестве параметра. Когда конечная точка получает сообщение, которое может быть декодировано одним из указанных вами декодировщиков, контейнер вызывает метод, помеченный @OnMessage, который принимает ваш пользовательский тип Java в качестве параметра, если этот метод существует.

Например, если у вас есть два типа Java (MessageA и MessageB), которые вы хотите отправлять и получать как текстовые сообщения, определите их так, чтобы они расширяли общий класс (Message). Поскольку вы можете определить только один декодировщик для текстовых сообщений, реализуйте декодировщик для класса Message следующим образом:

public class MessageTextDecoder implements Decoder.Text<Message> {
   @Override
   public void init(EndpointConfig ec) { }
   @Override
   public void destroy() { }
   @Override
   public Message decode(String string) throws DecodeException {
      // Чтение сообщения...
      if ( /* сообщение является сообщением типа A */ )
         return new MessageA(...);
      else if ( /* сообщение является сообщением типа B */ )
         return new MessageB(...);
   }
   @Override
   public boolean willDecode(String string) {
      // Определение, может ли сообщение быть сконвертировано к объекты типов
      // MessageA или MessageB...
      return canDecode;
   }
}

Затем добавьте параметр decoder в аннотацию @ServerEndpoint следующим образом:

@ServerEndpoint(
   value = "/myendpoint",
   encoders = { MessageATextEncoder.class, MessageBTextEncoder.class },
   decoders = { MessageTextDecoder.class }
)
public class EncDecEndpoint { ... }

Теперь определите метод в классе конечных точек, который получает объекты MessageA и MessageB следующим образом:

@OnMessage
public void message(Session session, Message msg) {
   if (msg instanceof MessageA) {
      // Получено сообщения MessageA...
   } else if (msg instanceof MessageB) {
      // Получено сообщение MessageB...
   }
}

Как и конечные точки, объекты декодировщика связаны с одним и только одним подключением к веб-сокету, поэтому в любой момент времени только один поток выполняет код объекта декодировщика.


Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)