Статьи

Клиентские приложения с Ajax Solr: JavaScript против сервлетов

Мы уверены, что Java-сервлеты являются наиболее продуктивным средством доставки веб-интерфейса? Давайте покопаемся в клиентском приложении, написанном на JavaScript, и узнаем.

Аякс Солр

Ajax Solr — это клиентская библиотека JavaScript, которая может получить доступ к Solr через его REST-подобный интерфейс. Solr — не база данных, а поисковый сервер; однако это основной источник данных для приложения на основе поиска. Результатом использования Ajax Solr для пользовательского интерфейса является буквально наличие в браузере API JDBC (или PDO), который может выполнять запросы и изменять отображаемые результаты на основе событий, сгенерированных пользователем.

Ajax Solr не зависит от используемой платформы javascript; по умолчанию он использует jQuery, который довольно популярен, но к нему нет никакой зависимости.

Уже есть отличный учебник по Ajax Solr, в котором объясняется, как создавать свои демонстрационные приложения с нуля, поэтому я не хочу повторять его здесь. Тем не менее, я включу некоторый код для практического понимания этой статьи и покажу, как легко запустить и запустить приложение Solr. Демонстрационное приложение о базе данных новостей, которые можно просматривать и разбирать на части любым способом, о котором вы только можете подумать. Учебник позволил мне за несколько часов построить визуализацию записей, их разбивку на страницы, некоторые фильтры, которые можно использовать в комбинации (граненый поиск) и выбранные с помощью облака тегов, а также текстовое поле поиска.

Сервлеты и JSP против виджетов и jQuery

Отказ от Lucene для Solr является одним из наиболее оптимальных вариантов, которые я выбрал, и интерфейс JavaScript также более отзывчив и динамичен, чем интерфейс Servlet / JSP (при условии, что в последнем не задействован Ajax). Я могу думать о многих преимуществах JavaScript по сравнению с генерацией пользовательского интерфейса в Java. Например, существует очень быстрая обратная связь по написанному вами коду, и отладка больше не является кошмаром благодаря таким инструментам, как Firebug; и никакой шаг компиляции не требуется.

Eclipse постоянно обновляет сборку, полную файлов .class, но вы должны фактически перезапустить приложение, если вы измените какой-то код; поскольку указанная папка веб-приложения Tomcat является оригинальной (по крайней мере, для файлов HTML и JS), при кодировании интерфейса JavaScript вы можете отредактировать файл, сохранить его и сразу же посмотреть, что изменилось, перезагрузив страницу в браузере.

Firebug также удивителен, поскольку он может анализировать переменные при помощи console.log () и console.dir (); если переменная является узлом DOM, таким как сгенерированная ссылка или элемент списка, она показывает его HTML-представление. И даже показывает дерево DOM как в виде объекта, так и в виде HTML: не оригинальный HTML, как это делает HttpUnit, а текущий после выполнения виджетов JavaScript.

Более того, JavaScript — это динамический язык, и он очень лаконичен (кажется, что вы действительно можете написать код JavaScript без IDE): сегодня Java жаловалась, что я не могу преобразовать Collection <Object> в Collection <String>, в то время как в JavaScript, если doc является результирующим документом, полученным из Ajax Solr, я обычно пишу doc.artist и doc.title для ссылки на его свойства (где artist и title являются полями схемы.) Генерация кода отсутствует.

Добавьте к этому простоту использования JavaScript при доступе через такую ​​среду, как jQuery, которая дополняет элементы DOM интуитивно понятными служебными методами, такими как element.html () и element.css (), для изменения содержимого и стиля тега.

Java прекрасно подходит для заполнения Solr документами в моем бэкэнде с помощью асинхронного процесса, но мне пришлось представить Цезарю вещи, которые принадлежат Цезарю, и принять интерфейс на основе JavaScript для более быстрой разработки и обратной связи. Веб-интерфейсам все время нужны отзывы и эксперименты, а в JavaScript единственная инфраструктура, с которой мне приходится иметь дело, находится в моем браузере. На стороне сервера, напротив, инфраструктура стабильна (некоторые наборы OSGi и демоны), в то время как если что-то идет не так, трудно сказать со стороны клиента: поэтому мне нужна проверенная платформа во время компиляции, которая заполняет журнал предупреждениями Время что-то не совсем верно.

тестирование

Даже когда я пишу Ajax-приложение, я не откажусь от тестов: в этом проекте у меня были тесты приемочного уровня, а не единичные, потому что моя логика тесно связана с презентацией. Если бы мне пришлось выполнить какую-то бизнес-задачу, например, вызвать другой веб-сервис, я бы также принял во внимание JsUnit . Тесты важны, потому что нет компилятора, чтобы обнаружить наши ошибки в приложениях JavaScript.

Таким образом, я использую тестовый набор Selenium, чтобы сканировать мой интерфейс с реальным браузером и убедиться, что он работает хорошо. Я не занимался тестовой разработкой, поскольку пользовательский интерфейс не может быть спроектирован только с помощью кода, но для этого нужна реальная визуальная обратная связь; однако методы Selenium могут быть очень слабо связаны со структурой страницы, так как вы на самом деле управляете браузером, а не DOMDocument:

selenium.open("/chansonnier/index.html");
wrapped.verifyTrue(selenium.isTextPresent("Beautiful Day"));
selenium.click("link=happiness");
wrapped.verifyTrue(selenium.isTextPresent("(x) emotion:happiness"));
wrapped.verifyTrue(selenium.isTextPresent("The heart is a bloom"));

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

Образцы кода

Пришло время показать настоящий код. Это мой полный загрузочный код для Ajax Solr:

  $(function () {
Manager = new AjaxSolr.Manager({
solrUrl: 'http://localhost:8983/solr/'
});
Manager.addWidget(new AjaxSolr.ResultWidget({
id: 'result',
target: '#result'
}));
Manager.addWidget(new AjaxSolr.PagerWidget({
id: 'pager',
target: '#pager',
prevLabel: '<',
nextLabel: '>',
innerWindow: 1,
renderHeader: function (perPage, offset, total) {
$('#pager-header').html($('<span/>').text('displaying ' + Math.min(total, offset + 1) + ' to ' + Math.min(total, offset + perPage) + ' of ' + total));
}
}));

var fields = [ 'emotion' ];
for (var i = 0, l = fields.length; i < l; i++) {
Manager.addWidget(new AjaxSolr.TagcloudWidget({
id: fields[i],
target: '#' + fields[i],
field: fields[i]
}));
}
Manager.addWidget(new AjaxSolr.CurrentSearchWidget({
id: 'currentsearch',
target: '#selection',
}));
Manager.addWidget(new AjaxSolr.TextWidget({
id: 'text',
target: '#search',
field: 'lyrics'
}));
Manager.init();
Manager.store.addByValue('q', '*:*');
Manager.store.addByValue('rows', 1);
var params = {
facet: true,
'facet.field': [ 'emotion' ],
'facet.limit': 20,
'facet.mincount': 1,
'f.topics.facet.limit': 50,
'json.nl': 'map'
};
for (var name in params) {
Manager.store.addByValue(name, params[name]);
}

Manager.doRequest();
});

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

  $(function () {
Manager = new AjaxSolr.Manager({
solrUrl: 'http://example.solrstuff.org/solrjs/'
});
Manager.addWidget(new AjaxSolr.ResultWidget({
id: 'result',
target: '#docs'
}));
Manager.init();
Manager.store.addByValue('q', '*:*');
Manager.doRequest();
});

В обоих случаях установочный код помещается в обработчик загрузки jQuery, который вы можете заменить на обработчик вашей библиотеки. Первый фрагмент кода устанавливает практически законченное приложение с облаками тегов, граненым поиском, полями поиска, нумерацией страниц и т. Д., А второй представляет собой простой список результатов.

Конечно, мы должны определить виджеты, чтобы иметь возможность добавлять их в менеджер. Обычно нам нужно только унаследовать от абстрактного класса и переопределить метод для предоставления специфичного для приложения кода. Например, вот ResultWidget:

AjaxSolr.ResultWidget = AjaxSolr.AbstractWidget.extend({
afterRequest: function () {
$(this.target).empty();
for (var i = 0, l = this.manager.response.response.docs.length; i < l; i++) {
var doc = this.manager.response.response.docs[i];
$(this.target).append(AjaxSolr.theme('result', doc));
var items = this.facetLinks('emotion', [doc.emotion]);
AjaxSolr.theme('list_items', '#links_' + doc.uuid, items);
}
$('.images a').lightBox();
},
// ...utility methods
});

Обработчик afterRequest () вызывается каждый раз, когда результат поиска регенерируется из-за нового условия, и извлекает элемент из DOM и заполняет его представлением различных документов (этот бит зависит от jQuery). В этом примере кода я использую AjaxSolr.theme для разделения генерации HTML и этой логики, но вы можете просто использовать jQuery в этом методе для создания списка или серии элементов div.

Вывод

Подводя итог, нет единого истинного языка для каждого типа развития. Java мощна в асинхронных и интенсивных задачах, а JavaScript — действительно хорошая платформа для веб-интерфейсов. Если вы работаете с приложением Ajax, вы уже генерируете его часть на клиенте при каждом вызове XMLHttpRequest.send (): почему бы не сгенерировать его больше?