Мы уверены, что 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 (): почему бы не сгенерировать его больше?