«Веб-запросы» — это родные средства Pivot для связи с удаленными службами данных. Они предназначены в первую очередь для облегчения взаимодействия со службами REST на основе JSON. Однако они достаточно универсальны для поддержки связи с любым типом HTTP-сервиса, используя любой формат данных.
Например, данные, представленные приложением Stock Tracker, получены из Yahoo! Финансы в виде файла значений, разделенных запятыми (CSV):
"AAPL","APPLE INC",171.06,169.59,172.17,166.00,+2.88,12995693
"AMZN","AMAZON.COM INC",72.54,72.35,73.83,70.52,+1.10,2748930
"EBAY","EBAY INC",27.09,27.35,27.44,27.04,-0.02,3426369
Эти данные возвращаются путем отправки HTTP-запроса GET по адресу http://download.finance.yahoo.com/d/quotes.csv с соответствующим набором аргументов строки запроса. Например, приложение Stock Tracker передает следующие аргументы URL службы:
-
s — разделенный запятыми список биржевых символов, представляющих котировки для извлечения.
-
f — запрошенный формат для результирующего файла CSV; это строка символов, представляющая различные поля данных, возвращаемые запросом. Формат, используемый приложением Stock Tracker: «snl1ohgc1v»:
- с — символ
- n — название компании
- l1 — последнее значение
- o — начальная стоимость
- h — высокое значение
- г — низкое значение
- c1 — процент изменения
- v — громкость
Обратите внимание, что этот запрос на самом деле возвращает больше данных, чем может быть отображено в табличном представлении. Другие поля данных используются подробным представлением цитаты, которое более подробно обсуждается в разделе привязки данных.
Построение веб-запроса
Чтобы отобразить котировки акций для пользователя, Stock Tracker должен выполнить веб-запрос для получения данных из Yahoo! Финансовый веб-сервис, а затем заполните представление таблицы котировок акций результатами запроса. Запрос выполняется в методе refreshTable () , а таблица заполняется обработчиком обратного вызова, реализованным как анонимный внутренний класс, определенный в этом методе. Этот код определен в классе StockTracker .
Сначала создается веб-запрос:
getQuery = new GetQuery(SERVICE_HOSTNAME, SERVICE_PATH);
Затем значение аргумента «s» создается путем объединения значений в списке символов с запятыми и применяются аргументы запроса:
StringBuilder symbolsArgumentBuilder = new StringBuilder();
for (int i = 0, n = symbols.getLength(); i < n; i++) {
if (i > 0) {
symbolsArgumentBuilder.append(",");
}
symbolsArgumentBuilder.append(symbols.get(i));
}
String symbolsArgument = symbolsArgumentBuilder.toString();
getQuery.getArguments().put("s", symbolsArgument);
getQuery.getArguments().put("f", "snl1ohgc1v");
Полученный URL-адрес запроса будет похож на:
http://download.finance.yahoo.com/d/quotes.csv?s=aapl,amzn,ebay&f=snl1ohgc1v
Затем создается и настраивается экземпляр CSVSerializer:
CSVSerializer quoteSerializer = new CSVSerializer();
quoteSerializer.getKeys().add(StockQuote.SYMBOL_KEY);
quoteSerializer.getKeys().add(StockQuote.COMPANY_NAME_KEY);
quoteSerializer.getKeys().add(StockQuote.VALUE_KEY);
quoteSerializer.getKeys().add(StockQuote.OPENING_VALUE_KEY);
quoteSerializer.getKeys().add(StockQuote.HIGH_VALUE_KEY);
quoteSerializer.getKeys().add(StockQuote.LOW_VALUE_KEY);
quoteSerializer.getKeys().add(StockQuote.CHANGE_KEY);
quoteSerializer.getKeys().add(StockQuote.VOLUME_KEY);
По умолчанию класс GetQuery использует экземпляр pivot.core.serialization.JSONSerializer для десериализации данных, возвращаемых запросом GET. Тем не менее, данные цитаты из Yahoo! Финансы возвращаются в виде файла CSV; CSVSerializer — это реализация интерфейса pivot.core.serialization.Serializer, который анализирует поток данных CSV в последовательность пар имя / значение (в частности, экземпляр List <Dictionary <String, Object >>). Коллекция ключей CSVSerializer отображает столбцы в данных CSV на ключи в возвращенных экземплярах словаря.
По умолчанию CSVSerializer создает экземпляр HashMap <String, Object> для каждой строки, с которой он сталкивается в потоке CSV. Однако вызывающая сторона может указать имя другой реализации Dictionary, используя метод setItemClass () :
quoteSerializer.setItemClass(StockQuote.class);
Поскольку данные CSV нетипизированы, все значения по умолчанию возвращаются в виде строк. StockQuote — это пользовательская реализация интерфейса Dictionary, которая преобразует числовые данные столбца в значения типа Float, когда они анализируются сериализатором. Это позволяет избежать потери производительности при обходе данных дважды: один раз, чтобы прочитать их из потока CSV, и снова преобразовать их в соответствующий тип. Средства визуализации ячеек, которые мы присвоили столбцам в файле WTKX, обеспечивают правильное форматирование и представление данных.
Наконец, запрос выполняется:
getQuery.setSerializer(quoteSerializer);
getQuery.execute(new TaskAdapter<Object>(new TaskListener<Object>() {
...
}
Аргумент, передаваемый методу execute (), представляет собой TaskAdapter, заключенный в анонимную реализацию внутреннего класса TaskListener <Object>. TaskListener представляет собой интерфейс определяется pivot.util.concurrent пакета и служит в качестве обработчика обратного вызова для асинхронных операций , осуществляемых pivot.util.concurrent.Task класса, из которых GetQuery является подклассом. TaskAdapter определяется пакетом pivot.wtk и обеспечивает обратный вызов в потоке пользовательского интерфейса (в противном случае прослушиватель вызывается в контексте фонового потока).
TaskListener определяет два метода:
public void taskExecuted(Task<V> task);
public void executeFailed(Task<V> task);
Параметр шаблона V определяется классом Task и представляет (необязательное) возвращаемое значение операции. Первый метод вызывается, если задача завершается успешно, а второй вызывается, если задача не выполнена по какой-либо причине.
Обработчик успеха StockTracker определен следующим образом:
public void taskExecuted(Task<Object> task) {
if (task == getQuery) {
Sequence<Span> selectedRanges = stocksTableView.getSelectedRanges();
List<StockQuote> quotes = (List<StockQuote>)task.getResult();
stocksTableView.setTableData(quotes);
if (selectedRanges.getLength() > 0) {
stocksTableView.setSelectedRanges(selectedRanges);
} else {
if (quotes.getLength() > 0) {
stocksTableView.setSelectedIndex(0);
}
}
ResourceBundle resourceBundle =
ResourceBundle.getBundle(StockTracker.class.getName(), locale);
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.MEDIUM, locale);
String lastUpdateText = resourceBundle.getString("lastUpdate")
+ ": " + dateFormat.format(new Date());
lastUpdateLabel.setText(lastUpdateText);
getQuery = null;
}
}
Если источником события является выполняемая в данный момент задача, обработчик делает следующее:
-
Кэширует текущее состояние выбора представления таблицы котировок.
-
Получает результат запроса и приводит его к соответствующему типу (List <StockQuote>)
-
Устанавливает список в качестве данных модели для табличного представления
-
Восстанавливает любое состояние выбора (которое было бы потеряно при сбросе данных модели)
-
Обновляет значение метки «последнее обновление», чтобы отразить текущее время способом, соответствующим текущей локали
В случае сбоя обработчик просто записывает исключение на консоль:
public void executeFailed(Task<Object> task) {
if (task == getQuery) {
System.out.println(task.getFault());
getQuery = null;
}
}
В этом примере демонстрируется использование только GetQuery, но Pivot также обеспечивает поддержку операций HTTP POST, PUT и DELETE с использованием классов PostQuery, PutQuery и DeleteQuery соответственно. Это упрощает создание полноценного REST-клиента с использованием Pivot.