Перейти к содержанию

Разработка web-приложения на основе технологии Java

Материал из Викиучебника — открытых книг для открытого мира

Java и web-разработка

[править]

Сбор данных для web-приложения

[править]

Парсинг

[править]

Парсинг – это автоматический сбор информации с какого-либо источника.

Цель парсинга – сбор данных со страниц ресурсов с дальнейшей обработкой и преобразованием.

Работа парсинга заключается в сопоставлении строки естественного языка или языка программирования с формальными правилами. Приведем пример. Представьте себя радистом на войне. Вы получаете зашифрованное сообщение. У вас есть правила дешифровки. Вы начинаете разгадывать послание согласно этому методу. Вы смотрите вначале на символ из полученного сообщения. Потом на свою таблицу с его значением. Например, цифре «1» соответствует буква «Я». Вы сопоставляете все символы и получаете то сообщение, которое можно прочитать. Парсинг работает точно так же. Есть некоторый шаблон сообщения, написанный на формальном языке. С ним сравнивается какая-то строка.

  Программа, дающая возможность компьютеру «читать» – сравнивать предложенные слова с имеющимися во Всемирной сети, называется парсером.

Независимо от того на каком формальном языке программирования написан парсер, алгоритм его действия остается одинаковым:

  1. Сбор информации с одного или нескольких источников. В соответствии с заданными настройками программа обходит заданные источники информации в Сети. Поскольку чаще всего этими источниками являются веб-страницы, парсер обрабатывает их исходный HTML-код.
  2. Получение и преобразование информации. Данные, которые были собраны на первом этапе, обрабатываются средствами парсера — чаще всего с использованием регулярных выражений. При необходимости на данной стадии информация может преобразовываться в нужный формат.
  3. Генерация результатов. Итоговый этап, после которого программа выдает результат в заданном виде. Данные выводятся или записываются в удобной для пользователя форме.

В интернете часто встречаются выражения, из которых следует, будто парсер (поисковый робот, бот) путешествует по Всемирной сети. Но зачастую эта программа никогда не покидает компьютера, на котором она инсталлирована. Этим парсер коренным образом отличается от компьютерного вируса – автономной программы, способной к размножению, хотя по сути своей работы он похож на троян. Ведь он получает данные, иногда конфиденциального характера, не спрашивая желания их владельца.

Разберемся зачем нужен парсинг. Сбор информации в интернете – трудоемкая, рутинная, отнимающая много времени работа. Парсеры, способные в течение суток перебрать большую часть веб-ресурсов в поисках нужной информации, автоматизируют ее. Без программ парсинга владельцам интернет-магазинов, которым требуются сотни однотипных описаний товаров, технических характеристик и другого контента, не являющегося интеллектуальной собственностью, было бы трудно вручную заполнять характеристики товаров.

Возможностью «спарсить» чужой контент для наполнения своего сайта пользуются многие веб-мастера и администраторы сайтов. Это оправдано, если требуется часто изменять контент для представления текущих новостей или другой, быстро меняющейся информации. Парсинг – «палочка-выручалочка» для организаторов спам-рассылок по электронной почте или каналам мобильной связи. Для этого им надо запустить «бота» путешествовать по социальным сетям и собирать «телефоны, адреса, явки». Ну и хозяева некоторых, особенно недавно организованных веб-ресурсов, любят наполнить свой сайт чужим контентом. Правда, они рискуют, поскольку поисковые системы быстро находят и банят любителей копипаста.

Теперь разберемся со сложностями парсинга, а точнее с этическими и техническими сложностями. Вопрос о том, является ли парсинг воровством контента, активно обсуждается во Всемирной сети. Большинство оппонентов считают, что заимствование части контента, не являющегося интеллектуальной собственностью, например, технических описаний, допустимо. Ссылка на первоисточник контента рассматривается как способ частичной легитимации. В то же время, наглое копирование, включая грамматические ошибки, осуждается интернет-сообществом, а поисковыми системами рассматривается как повод для блокировки ресурса.

Кроме этических проблем парсер способен создать и технические. Он автомат, робот, но его вход на сайт фиксируется, а входящий и исходящий трафики учитываются. Количество подключений к веб-ресурсу в секунду устанавливает создатель программы. Делать этот параметр очень большим нельзя, поскольку сервер может не переварить потока входящего трафика. При частоте 200–250 подключений в секунду работа парсера рассматривается как аналогичная DOS-атаке. Интернет-ресурс, к которому проявлено такое внимание, блокируется до выяснения обстоятельств.




Java библиотека jsoup

[править]

Jsoup — это библиотека Java для работы с реальным HTML. Она обеспечивает очень удобный API (программный интерфейс приложения) для извлечения и манипулирования данными. Jsoup реализует WHATWG HTML5 спецификацию, и разбирает HTML в ту же объектную модель документа, как это делают современные браузер вроде Chrome и Firefox. Вот некоторые из полезных функций Jsoup библиотеки:

  1. Jsoup может очистить и разобрать HTML из URL, файла или строки.
  2. Jsoup может найти и извлечь данные используя обход объектной модели документа или CSS селекторы.
  3. Jsoup позволяет манипулировать HTML элементами, атрибутами и текстом.
  4. Jsoup обеспечивает очистку предоставленной пользователем информации по white-list, для предотвращения XSS атак.
  5. Также Jsoup выдает "аккуратный" HTML.

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




Сервлеты

[править]

Технология сервлетов

[править]

Сервлет – это Java-программа, которая в качестве своего суперкласса использует класс HttpServlet. Сервлет используется для того, чтобы расширить возможности существующего сервера, в частности веб-сервера.

  Технология сервлетов является фундаментом разработки web-приложений с помощью языка программирования Java. Это одна из наиболее важных технологий Java, и она лежит в основе другой популярной технологии Java для разработки web-приложений: серверных страниц Java с которыми мы познакомимся на следующих уроках (JSP, JavaServer Pages). 

В начале своего развития Интернет состоял только из статического содержимого, создаваемого с помощью языка разметки гипертекста (Hypertext Markup Language, HTML). В то время любой, кто мог создать страницу HTML, считался специалистом по Интернету. Это, однако, продолжалось недолго.

Динамическое содержимое стало доступно в web благодаря технологии интерфейса общего шлюза (Common Gateway Interface, CGI). CGI позволяет web-серверу вызывать внешнюю программу и передавать ей данные запроса HTTP для его обработки. Ответ внешней программы передается затем web-cepвepy, который пересылает его клиентскому браузеру. Программы CGI могут быть написаны на любом языке, который способен вызывать web-cepвep. Со временем самым популярным языком для написания программ CGI стал Perl.

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

Постепенно новые технологии заменяют технологию CGI в разработке web-приложений. Мир был свидетелем появления следующих технологий:

  • ColdFusion. Предоставляет подобные HTML пользовательские теги, которые можно применять для выполнения ряда операций, главным образом для запроса базы данных. В свое время ColdFusion была основной технологией программирования web-приложений.
  • Серверный JavaScript (SSJS). Является расширением языка JavaScript — языка сценариев, который все еще широко используется в клиентском web-программировании. Применяя технологию LiveWire компании Netscape, SSJS может обращаться к классам Java, размещенным на сервере.
  • РНР. Интересная технология с открытым исходным кодом, которая развилась за последние годы. Облегчает разработку web-приложений, предоставляя собственное управление сеансами. Содержит встроенные функции, такие как пересылка файлов. Число программистов, использующих РНР, резко выросло в последние годы.
  • Сервлеты. Технология сервлетов была предложена компанией Sun Microsystems в 1996 г.
  • Серверные страницы Java (JSP). Являются расширением технологии сервлетов.
  • Активные серверные страницы (ASP). ASP компании Microsoft используют технологии сценариев, которые работают на платформах Windows. Предпринимались попытки переноса этой технологии на другие операционные системы. Windows ASP работают с web-сервером IIS (Internet Information Server). Эта технология будет заменена активными серверными страницами .NET.
  • Активные серверные страницы .NET (ASP.NET). Эта технология является частью инициативы .NET компании Microsoft. Интересно то, что платформа. NЕТ использует среду Common Language Runtime (единая система выполнения программ), которая похожа на виртуальную машину Java и предоставляет обширную библиотеку классов, доступную всем языкам .NET и страницам ASP.NET. ASP.NET вводит несколько новых технологий, включая управление состоянием, которое не зависит от файлов cookie и перезаписи URL.

Сервлеты и JSP имеют следующие преимущества:

  • Производительность. Сервлеты превосходят CGI по производительности, поскольку отсутствует создание процесса для каждого клиентского запроса. Закончив обработку запроса, сервлет остается резидентным в памяти, ожидая другой запрос.
  • Переносимость. Аналогично другим технологиям Java сервлетные приложения являются переносимыми. Можно перемещать их в другие операционные системы без особых проблем.
  • Быстрый цикл разработки. Будучи технологией Java, сервлеты имеют доступ к богатой библиотеке Java, которая помогает ускорить процесс разработки.
  • Надежность. Сервлеты управляются виртуальной машиной Java. Поэтому не приходится беспокоиться об утечке памяти или о сборке мусора, что помогает писать надежные приложения.
  • Широкая доступность. Java — широко распространенная технология. Многочисленные поставщики разрабатывают технологии на основе Java. Одним из достоинств этого является то, что можно легко найти и купить компоненты, удовлетворяющие конкретным потребностям, что сохраняет драгоценное время разработки.

Архитектура сервлетных приложений

Сервлет является классом Java, который может быть динамически загружен и выполнен специальным web-сервером. Этот поддерживающий сервлеты web-сервер называется контейнером сервлетов (servlet container). В начальный период развития технологии сервлетов он назывался процессором сервлетов (servlet engine). Сервлеты взаимодействую с клиентами по модели запрос-ответ на базе HTTP. Поскольку технология сервлетов работает поверх HTTP, контейнер сервлетов должен поддерживать HTTP как протокол для передачи запросов клиента и ответов сервера. Однако контейнер сервлетов может поддерживать и другие протоколы, такие как HTTPS (HTTP поверх SSL) для защищенных транзакций.

Как работает сервлет

Сервлет загружается контейнером сервлетов при первом запросе сервлета. Затем сервлету передается запрос пользователя, сервлет обрабатывает его и возвращает ответ контейнеру сервлетов, который в свою очередь посылает ответ пользователю. После этого сервлет остается в памяти, ожидая другие запросы, — он не будет выгружаться из памяти, если только контейнер сервлетов не почувствует недостаток в памяти. Однако каждый раз, когда запрашивается сервлет, контейнер сервлетов сравнивает метку времени загруженного сервлета с файлом класса сервлета. Если метка времени файла класса оказывается более поздней, сервлет перезагружается в памяти. Таким образом, не требуется перезапускать контейнер сервлетов всякий раз при обновлении сервлетов.

Контейнер сервлетов Tomcat и шаги создания сервлетов

[править]

Сегодня доступно несколько контейнеров сервлетов. Наиболее популярным и признаваемым как официальный контейнер сервлетов/JSP является Tomcat. Разработанный первоначально компанией Sun Microsystems, исходный код Tomcat был передан Apache Software Foundation в октябре 1999 г. В своем новом доме Tomcat был включен в проект Jakarta. Apache, Sun и другие компании с помощью добровольцев со всего мира превратили Tomcat в эталонную реализацию контейнера сервлетов мирового уровня. Через два месяца после передачи была выпущена версия Tomcat 3.0. Затем было несколько промежуточных версий Tomcat, и на данный момент уже существует версия 9.0.

Контейнер сервлетов 9.0 (Catalina) основывается на совершенно новой архитектуре. Он был разработан заново с целью достижения максимальной гибкости и производительности. Версия 9.0 реализует спецификации Servlet 4.0.

Tomcat сам по себе является web-сервером. Это означает, что Tomcat можно использовать для обслуживания HTTP-запросов сервлетов, а также статических файлов (HTML, файлов изображений и т. д.). На практике, однако, Tomcat обычно применяется как модуль с другим более мощным web-сервером, таким как web- сервер Apache или сервер Microsoft, поскольку это ускоряет обработку запро¬сов без сервлетов и без JSP. Только запросы сервлетов или JSP передаются Tomcat.

Чтобы написать сервлет, требуется как минимум версия 1.2 набора разра¬ботчика Java (JDK, Java Development Kit). Эталонные реализации сервлетов и JSP не включены в J2SE, но они имеются в Tomcat. Tomcat написан полностью на Java.

Шесть шагов создания сервлетов

После установки и конфигурирования Tomcat следует привести его в рабочее состояние. По сути, чтобы написать и запустить сервлет, необходимо выполнить следующие шаги:

  1. Создать в Tomcat структуру каталогов для приложения
  2. Написать исходный код сервлета. Необходимо импортировать в свой файл исходного кода пакеты javax.servlet и javax.servlet.http.
  3. Откомпилировать исходный код.
  4. Создать дескриптор развертывания.
  5. Запустить Tomcat.
  6. Вызвать сервлет в web-браузере.

Жизненный цикл сервлетов

[править]

Сервлеты разрабатываются с помощью пакета javax.servlet, который содержит семь интерфейсов, три класса и два исключения.

  Для знакомства со всеми членами этого пакета обратитесь к официальной документации Java, где представлена полная справочная информация. 
  

Пакет содержит семь интерфейсов:

  1. Request Dispatcher
  2. Servlet
  3. ServletConfig
  4. ServletContext
  5. ServletRequest
  6. ServletResponse
  7. SingleThreadModel

Три класса:

  1. GenericServlet
  2. ServletInputStream
  3. ServletOutputStream

И классы исключений:

  1. ServletException
  2. Unavailable Exception

Жизненный цикл сервлетов

Интерфейс Servlet в пакете javax.servlet является основой программирования сервлетов. Servlet — центральная абстракция технологии сервлетов Java. Каждый создаваемый сервлет должен явно или неявно реализовать интерфейс javax.servlet.Servlet. Жизненный цикл сервлета определяется тремя его методами: init, service и destroy.

Метод init()

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

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

Метод имеет следующую сигнатуру:

public void init(ServletConfig config) throws ServletException

Метод init является важным также потому, что контейнер сервлетов передает объект ServletConfig, который содержит конфигурационные значения, объявленные в файле web.xml для этого приложения.

Этот метод может порождать исключение ServletException. Контейнер сервлетов не может запустить сервлет в работу, если метод init порождает исключение ServletException или метод не возвращает управление в течение периода времени, определенного web-сервером.

  Примечание: ServerException является самым важным исключением при программировании сервлетов. Многие методы в пакетах javax.servlet и javax.servlet.http порождают это исключение при возникновении в сервлете проблем.

Метод service()

Метод service вызывается контейнером сервлетов после метода init, чтобы позволить сервлету ответить на запрос.

Сервлеты обычно выполняются внутри многопоточных контейнеров сервлетов, которые могут обрабатывать множество запросов одновременно. Поэтому необходимо помнить о синхронизации доступа к любым общим ресурсам, таким как файлы, сетевые соединения и переменные класса и экземпляра сервлета. Например, если открыть файл и выполнить запись в этот файл в сервлете, то нужно учитывать, что другой поток того же сервлета может открыть тот же файл.

Метод имеет следующую сигнатуру:

public void service (ServletRequest request, ServletResponse response) throws ServletException, java. io. IOException

Контейнер сервлетов передает объекты ServletRequest и ServletResponse. Объект ServletRequest содержит запрос клиента, а объект ServletResponse содержит ответ сервлета. Эти два объекта позволяют писать код, который определяет, как сервлет обслуживает клиентский запрос.

Метод service генерирует исключение ServletException, если возникает исключение, которое влияет на нормальную работу сервлета. Метод service может также порождать исключение java.io. IOException, если во время выполнения метода возникает исключительная ситуация при вводе или выводе.

Метод service предназначен для того, чтобы можно было написать код, который заставляет сервлет функционировать требуемым образом.

Метод destroy()

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

Этот метод вызывается только после того, как все потоки выполнения в методе service сервлета заканчиваются, или после того, как завершится период ожидания. После вызова метода destroy контейнер сервлетов не будет снова вызывать метод service этого сервлета.

Метод destroy дает сервлету возможность очистить все использовавшиеся ресурсы (например: память, дескрипторы файлов, потоки выполнения), и гарантирует, что любое устойчивое состояние синхронизировано с текущим состоянием сервлета в памяти.

Сигнатура этого метода:

public void destroy()

Демонстрация жизненного цикла сервлетов

public class PrimitiveServlet extends HttpServlet {
   public void init(ServletConfig config) throws ServletException { 
       System.out.println("init");
   }
   
   public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { 
       System.out.println("service");
   }
   public void destroy(){
       System.out.println("destroy");
   }
   public String getServletlnfo() { 
       return null;
   }
   public ServletConfig getServletConfig() { 
   return null;
   }
}

При первом вызове сервлета на консоль выводятся следующие две строки:

 Init
 Service

Это говорит, что был вызван метод init, а затем метод service. Однако при последующих запросах вызывается только метод service. Сервлет выводит на консоль строку:

 service

Это доказывает, что метод init вызывается только один раз.

Что делают в листинге getServletlnfo и getServletConfig? Ничего. В классе PrimitiveServlet они присутствуют лишь с целью удовлетворения спецификации, согласно которой класс должен предоставить реализации для всех методов в интерфейсе, который он реализует.

В методе getServletlnfo можно вернуть любую строку, например название компании, имя автора или другую необходимую информацию. Кто-то из про¬граммистов может расширить ваш класс сервлета, и он захочет узнать, какую полезную информацию предоставляет создатель сервлета.




Запросы и ответы

[править]

Запросы и ответы составляют суть web-приложения. В сервлетном приложении пользователь с помощью web-браузера посылает запрос контейнеру сервлетов, а контейнер сервлетов передает запрос сервлету.

В сервлетной парадигме запрос пользователя представляется объектом ServletRequest, пересылаемым контейнером сервлетов в качестве первого аргумента метода service. Вторым аргументом метода service является объект ServletResponse, который представляет ответ пользователю.

Интерфейс ServletRequest

Интерфейс ServletRequest определяет объект, используемый для инкапсуляции информации о запросе пользователя, включая пары имя/значение параметров, атрибуты и входной поток.

Интерфейс ServletRequest предоставляет важные методы, которые обеспечивают доступ к информации о пользователе. Например, метод getParameterNames возвращает Enumeration, содержащее имена параметров текущего запроса. Для получения значения каждого параметра служит метод getParameter интерфейса ServletRequest.

Методы getRemoteAddress и getRemoteHost можно применять для извлечения идентификационных данных компьютера пользователя. Первый метод возвращает строку, представляющую IP-адрес компьютера, который используется клиентом. Второй метод возвращает строку, содержащую квалифицированное имя хоста компьютера.

Листинги ниже демонстрируют объект ServletRequest в действии. Пример состоит из сервлета с именем RequestDemoServlet и формы HTML, содержащейся в файле indех.html, который необходимо поместить в каталог приложения.

Листинг index.html:

<html>
   <head>
       <title>Запрос</title>
       <meta charset="windows-1251">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
   </head>
   <body>
       <form action="servlet/RequestDemoServlet" method="POST">
           Author: <input type="text" name="Autor">
           <input type="submit" name="Submit">
           <input type="reset" value="Reset">
       </form>
   </body>
</html>

Листинг RequestDemoServlet:

public class RequestDemoServlet implements Servlet {
    public void init(ServletConfig config) throws ServletException {
    }
   public void destroy() { 
   }
   public void service(ServletRequest request, ServletResponse response)
       throws ServletException, IOException {
       System.out.println("Server Port: " + request.getServerPort()); 
       System.out.println("Server Name: " + request.getServerName()); 
       System.out.println("Protocol: " + request.getProtocol()); 
       System.out.println("Character Encoding: " + request. getCharacterEncoding());
       System.out.println("Content Type: " + request.getContentType());
       System.out.println("Content Length: " + request.getContentLength()); 
       System.out.println("Remote Address: " + request.getRemoteAddr()); 
       System.out.println("Remote Host: " + request.getRemoteHost()); 
       System.out.println("Scheme: " + request.getScheme());
       Enumeration parameters = request.getParameterNames();
        while (parameters.hasMoreElements()) { 
       String parameterName = (String) parameters.nextElement(); 
       System.out.println("Parameter Name: " + parameterName); 
       System.out.println("Parameter Value: "+request.getParameter(parameterName));
       }
       Enumeration attributes = request.getAttributeNames(); 
       while (attributes.hasMoreElements()) {
        String attribute = (String) attributes.nextElement();
        System.out.println("Attribute name: " + attribute); 
       System.out.println("Attribute value: "+request.getAttribute(attribute));
       }
       }
   public String getServletlnfo() { 
       return null;
   }
   public ServletConfig getServletConfig() { 
       return null;
   }
   @Override
   public String getServletInfo() {
       throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   }   
}

Чтобы выполнить пример, запросите сначала файл index.html.

После отправки формы на экране должен появиться список имен атрибутов и значений.

Интерфейс ServletResponse

Интерфейс ServletResponse представляет ответ пользователю. Наиболее важным методом этого интерфейса является getWriter. Он позволяет получить объект java.io.PrintWriter, который можно применять для записи тегов HTML и другого текста для пользователя.

Листинги представляют файл HTML с именем index.html и сервлет, метод service которого переопределяется кодом, который выводит некоторые теги HTML пользователю. Этот сервлет является модификацией примера в предыдущих листингах, извлекающего различную информацию о пользователе. Вместо вывода информации на консоль, метод service посылает ее назад пользователю.

Листинг index.html

<html>
   <head>
       <title>Запрос</title>
       <meta charset="windows-1251">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
   </head>
   <body>
       <form action="servlet/ResponseDemoServlet" method="POST">
           Author: <input type="text" name="Autor">
           <input type="submit" name="Submit">
           <input type="reset" value="Reset">
       </form>
   </body>
</html>

Листинг ResponseDemoServlet:

public class ResponseDemoServlet extends HttpServlet {
   public void init(ServletConfig config) throws ServletException { 
   }
   public void destroy() { 
   }
   public void service(ServletRequest request, ServletResponse response) 
   throws ServletException, IOException { 
       PrintWriter out = response.getWriter();
       out.println("<HTML>"); 
       out.println("<HEAD>");
       out. println("<TITLE>");
       out.println("ServletResponse");
       out. println("</TITLE>"); 
       out.println("</HEAD>");
       out.println("<BODY>");
       out.println("Demonstrating the ServletResponse object"); 
       out.println("
"); out.println("
Server Port: " + request.getServerPort()); out.println("
Protocol: " + request.getProtocol()); out.println("
Character Encoding: " + request.getCharacterEncoding()); out.println("
Content Type: " + request.getContentType()); out.println("
Content Length: " + request.getContentLength()); out.println("
Remote Address: " + request.getRemoteAddr()); out.println("
Remote Host: " + request.getRemoteHost()); out.println("
Scheme: " + request.getScheme()); Enumeration parameters = request.getParameterNames(); while (parameters.hasMoreElements()) { String parameterName = (String) parameters.nextElement(); out.println("
Parameter Name: " + parameterName); out.println("
Parameter Value: " + request.getParameter(parameterName)); } Enumeration attributes = request.getAttributeNames(); while (attributes.hasMoreElements()) { String attribute = (String) attributes.nextElement(); out.println("
Attribute name: " + attribute); out.println("
Attribute value: " + request.getAttribute(attribute)); } out.println("</BODY>"); out.println("</HTMl>"); } public String getServletlnfo() { return null; } public ServletConfig getServletConfig() { return null; } }

Запустите приложение, в форме введите любое значение в качестве значения автора.




Класс HttpServlet

[править]

Выше говорилось о том, как создавать сервлеты, выполнять их с помощью пакета javax.servlet. Однако при программировании сервлетов обычно работают с пакетом javax.servlet.http. Классы и интерфейсы этого пакета являются производными от классов и интерфейсов пакета javax.servlet. Члены javax.servlet.http богаче и удобнее в использовании. В этом пакете класс HttpServlet, представляющий сервлет, расширяет javax.servlet.GenericServIet и вносит большое число соб¬ственных методов. Пакет javax.servlet.http имеет интерфейсы HttpServletRequest и HttpServletResponse, которые эквивалентны интерфейсам javax.servlet.Request и javax.servlet. Response соответственно. HttpServletResponse расширяет интер¬фейс javax.servlet.ServletResponse, a HttpServlet Request является производным от и нтерфейса javax.servlet.Servlet Response.

Имеются дополнительные классы, которые недоступны в пакете javax.servlet. Например, можно использовать класс с именем Cookie (это небольшие текстовые файлы, в которые браузер записывает данные с посещенных вами сайтов) для работы с файлами cookie. Кроме того, класс HttpServlet предоставляет методы для работы с сеан¬сами пользователей.

Теперь рассмотрим класс HttpServlet, который обычно расширяется при разработке сервлетов.

Класс HttpServlet расширяет класс javax.servlet.GenericServlet. Класс HttpSenvlet добавляет ряд интересных методов. Наиболее важными являются шесть методов doxxx. Это методы doPost, doPut, doGet, doDelete, doOptions и doTrace. Каждый из них вызывается при использовании соответствующего метода запроса HTTP. Например, метод doGet вызывается, когда сервлет получает запрос HTTP, который был послан с помощью метода GET.

Из шести методов doxxx наиболее часто используются методы doPost и doGet. Метод doPost вызывается, когда браузер посылает запрос HTTP с помощью метода POST. Метод POST может использоваться формой HTML. Рассмотрим следующую форму HTML на клиентской стороне:

<html>
   <head>
       <title>TODO supply a title</title>
       <meta charset="windows-1251">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
   </head>
   <body>
       <form action="Register" method="POST">
           

<input type="text" name="firstName"> <input type="text" name="lastName"> <input type="submit" name="Submit"> </form> </body> </html>

Когда пользователь нажимает кнопку Submit, чтобы отправить форму, бра¬узер посылает серверу запрос HTTP с помощью метода POST. Web-сервер пе¬редает этот запрос сервлету Register, и вызывается метод cepвлета doPost. Пара имя/значение параметра формы посылается в теле запроса. Например, если в приведенной выше форме ввести Ann в качестве значения firstName и Go в качестве значения lastName, то в теле запроса будет содержаться:

firstName=Ann lastName=Go

Форма HTML может также использовать метод GET; однако POST приме¬няется с формами HTML значительно чаще.

Метод doGet вызывается, когда запрос HTTP посылается с помощью мето¬да GET. GET является методом, используемым в HTTP по умолчанию. При вводе URL, например www.yahoo.com, запрос посылается на Yahoo! с помо¬щью метода GET. Если метод GET применяется в форме, пара имя/значение параметра добавляется к URL. Поэтому, если в форме имеются два параметра с именами firstName и lastName и пользователь вводит Ann и Go соответствен¬но, то U RL сервлета будет таким:

http://yourdomain/myApp/Register?firstName=Ann&lastName=Go

При получении метода GET сервлет вызовет свой метод doGet.

  Примечание: может возникнуть вопрос, как сервлет узнает, какой метод doxxx вызывать. Ответ можно найти в исходном коде класса HttpServlet. Этот класс наследует метод service из интерфейса javax.servlet.Servlet, который вызывается контейнером сервлетов. Напомним, что его сигнатура имеет вид: public void service(ServletRequest request, ServletResponse response) throws ServletException, lOException Этот метод использует HttpRequest для запроса и HttpResponse для ответа и передает оба как аргументы второму методу service, который имеет сигнатуру: protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, lOException

Интерфейс HttpServletRequest имеет метод с именем getMethod, который возвращает String, содержащую метод HTTP, используемый клиентским запросом. Зная метод HTTP, метод service вызывает соответствующий метод doxxx.

Сервлет в листинге ниже применяет методы doGet и doPost.

public class NewServlet extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
ServletException, IOException { 
       response.setContentType("text/html");
       PrintWriter out = response.getWriter(); 
       out. println("<HTML>"); 
       out. println("<HEAD>");
       out.println("<title>The GET method</title>"); 
       out.println("</HEAD>"); 
       out.println( "<B0DY>");
       out.println( "The servlet has received a GET. " +"Now, click the button below."); 
       out.println("
"); out.println("<FORM method='POST'>"); out.println("<INPUT TYPE=SUBMIT VALUE=Submit>"); out.println("</FORM>"); out.println("</BODY>"); out.println("</HTML>"); } public void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<HTML>"); out.println("<HEAD>"); out.println("<TITLE>The POST method</TITLE>"); out.println("</HEAD>"); out.println("<BODY>"); out.println("The servlet has received a POST. Thank you."); out.println("</BODY>"); out.println("</HTML>"); } }

Когда сервлет вызывается в первый раз из web-браузера путем ввода URL cepвлета в поле Address или Location, в качестве метода запроса используется GET. На серверной стороне вызывается метод doGet. Сервлет посылает строку «The servlet has received a GET. Now, click the button below». («Сервлет получил GET. Теперь нажмите кнопку, расположенную ниже».) плюс форму HTML.

Посылаемая браузеру форма применяет метод POST. Когда пользователь нажимает кнопку, чтобы отправить форму, серверу передается запрос POST. Сервлет вызывает метод doPost, посылая браузеру String, содержащую «The servlet has received a POST. Thank you» («Сервлет получил POST Спасибо»).




Интерфейс HttpServerRequest

[править]

Помимо нескольких специфических для протокола методов, содержащихся в классе HttpServlet, пакетjavax.servlet.http предоставляет также развитые интер¬фейсы запроса и ответа: HttpServletRequest и HttpServletResponse. Сегодня мы познакомимся с интерфейсом запроса HttpServletRequest с помощью ряда примеров.

Получение заголовков запроса HTTP из HttpServletRequest

Запрос HTTP, который браузер клиента посылает серверу, включает в себя заголовок запроса HTTP с важной информацией, такой как cookie и referer. Доступ к заголовкам можно получить с помощью объекта HttpServletRequest, передаваемого методу doxxx.

Следующий пример демонстрирует, как можно использовать интерфейс HttpServletRequest для получения всех имен заголовков и для отправки пар имя/ значение заголовков в браузер.

public class RegisterServlet extends HttpServlet { 
   public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
ServletException, IOException {
       response.setContentType("text/html");
       PrintWriter out = response.getWriter();
       Enumeration enumeration = request.getHeaderNames();
       while (enumeration.hasMoreElements()){
           String header = (String) enumeration.nextElement();
               out.println(header + ": " + request.getHeader(header) + "
"); } }}

RegisterServlet в листинге использует методы getHeaderNames и getHeader. Сначала вызывается getHeaderNames для получения Enumeration, содержащего все имена заголовков, находящиеся в клиентском запросе. Значение каждого заголовка извлекается с помощью метода getHeader, которому передается имя заголовка.

Выходные данные кода зависят от клиентского окружения, в частности от используемого браузера и операционной системы клиентской машины. Например, некоторые браузеры могут посылать серверу файлы cookie. На наличие заголовка referer запроса HTTP влияет то, как пользователь запрашивает сервлет: вводит URL в поле Address/Location или щелкает мышью на гиперссылке.

Получение строки запроса из HttpServletRequest Следующим важным методом является getQueryString, который использу¬ется для извлечения строки запроса HTTP. Строка запроса размещается в U RL справа от пути доступа к сер влету.

Если в форме HTML используется метод GET, то пара имя/значение пара¬метра добавляется к URL. Код в следующем листинге является сервлетом с именем HttpRequestDemoServlet, который выводит на экран значение строки запроса и форму.

public class HttpRequestDemoServlet1 extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
ServletException, IOException{
       response.setContentType("text/html"); 
       PrintWriter out = response.getWriter(); 
       out.println("<html>"); 
       out.println("<head>");
       out.println("<title>Obtaining the Query String</title>"); 
       out.println("</head>"); 
       out.println("<body>");
       out.println("The request's parameters are:
"); out.println("<form METHOD='GET'>"); out.println("
First Name: <INPUT ТУРЕ='ТЕХТ' NAME='FirstName'>"); out.println("
Last Name: <INPUT TYPE='TEXT' NAME='LastName'>"); out.println("
<INPUT TYPE='SUBMIT' VALUE='Submit'>"); out.println("</form>"); out.println ("</body>"); out.println("</html>"); } }

Когда пользователь вводит URL сервлета в веб-браузере и сервлет вызывается в первый раз, строка запроса содержит null.

После ввода каких-то значений в форму HTML и отправки формы страница выводится заново (см. рис. ниже). Обратите внимание, что теперь имеется добавленная к URL строка. Строка запроса содержит пары имя/значение параметров, разделенные знаком амперсанда (&).

Получение параметров из HttpServletRequest

Выше было показано, как получить строку запроса, содержащую значение. Следовательно, можно получить пары имя/значение параметров формы или другие значения предыдущей страницы. Однако применение метода getQueryString для получения пар имя/значение параметров формы нежелательно, так как в этом случае придется самостоятельно выполнять анализ стро¬ки. Можно использовать другие методы HttpServletRequest для получения имен и значений параметров: методы getParameterNames и getParameter.

Метод getParameterNames возвращает Enumeration, содержащее имена па¬раметров. Однако во многих случаях имена параметров уже известны, и этот метод использовать не нужно. Для получения значения параметра служит ме¬тод getParameter, принимающий имя параметра в качестве аргумента. Следующий пример демонстрирует, как можно использовать методы getParameterNames и getParameter для вывода всех имен и значений парамет¬ров формы HTML c предыдущей страницы.

public class HttpRequestDemoServlet1 extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
ServletException, IOException{
       response.setContentType("text/html"); 
       PrintWriter out = response.getWriter(); 
       out.println("<html>"); 
       out.println("<head>");
       out.println("<title>Obtaining the Query String</title>"); 
       out.println("</head>"); 
       out.println("<body>");
       out.println("The request's parameters are:
"); Enumeration enumeration = request.getParameterNames(); while (enumeration.hasMoreElements()){ String parameterName = (String) enumeration.nextElement(); out.println(parameterName + ": " + request.getParameter(parameterName) + "
" ); } out.println("<form METHOD='GET'>"); out.println("
First Name: <INPUT ТУРЕ='ТЕХТ' NAME='FirstName'>"); out.println("
Last Name: <INPUT TYPE='TEXT' NAME='LastName'>"); out.println("
<INPUT TYPE='SUBMIT' VALUE='Submit'>"); out.println("</form>"); out.println ("</body>"); out.println("</html>"); } }

При первом вызове сервлет не имеет никаких параметров предыдущего зап¬роса, поэтому не выводится никаких пар имя/значение:

При последующих запросах пользователь должен ввести значения обоих параметров: firstName и lastName:

Обработка многозадачных параметров Нередко требуется использовать в форме параметры с одинаковыми именами, например, в случае применения элементов управления флажком, которые могут принимать несколько значений, или при наличии элемента управления HTML с множественным выбором. В подобных ситуациях нельзя использовать метод getParameter, так как он будет выдавать только первое значение. Вместо этого применяется метод getParameterValues.

Метод getParameterValues имеет один аргумент: имя параметра. Он возвращает массив строк, содержащий все значения этого параметра. Если параметр с данным именем не найден, метод getParameterValues вернет null.

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

public class NewServlet extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
ServletException, IOException {
       response.setContentType( "text/html"); 
       PrintWriter out = response.getWriter(); 
       out.println("<html>"); 
       out.println("<head>");
       out.println("<TITLE>Obtaining Multi-Value Parameters</TITLE>"); 
       out.println("</head>"); 
       out.println("<body>"); 
       out.println("
"); out.println("
Select your favorite music:"); out.println("
<form method='POST'>"); out.println("
<INPUT TYPE='checkbox' " +"NAME='favoriteMusic' VALUE=Rock>Rock"); out.println("
<INPUT TYPE='checkbox' " +"NAME='favoriteMusic' VALUE=Jazz>Jazz"); out.println("
<INPUT TYPE='checkbox' " +"NAME='favoriteMusic' VALUE=Classical>Classical"); out.println("
<INPUT TYPE='checkbox' " +"NAME='favoriteMusic' VALUE=Country>Country"); out.println( "
<INPUT TYPE='SUBMIT' VALUE='Submit'>"); out.println("</form>"); out.println("</body>"); out.println("</html>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String[] values = request.getParameterValues("favoriteMusic"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); if (values != null ) { int length = values.length; out.println("You have selected: "); for (int i=0; i<length; i++) { out.println("
" + values[i]); } }} }

При первом вызове сервлета вызывается метод doGet, который посылает форму. Форма имеет четыре элемента управления флажком с одним именем: favoriteMusic. Однако значения флажков различны.

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




Интерфейс HttpServerResponse

[править]

Интерфейс HttpServletResponse предоставляет несколько зависящих от протокола методов, недоступных в интерфейсе javax.servlet.ServletResponse. Интер¬фейс HttpServletResponse расширяет интерфейс javax.servlet.Servlet Response. В примерах, на прошлом уроке, использовались два метода HttpServletResponse при отправке выходных данных в браузер: setContentType и getWriter.

response.setContentType("text/html");
PrintWriter out = response.getWriter();

Имеются и другие методы. Метод addCookie посылает браузеру cookie. Для обработки URL, посылаемых браузеру, также используются специальные методы.

Еще одним интересным методом интерфейса HttpServletResponse является метод sendHeader. Он позволяет добавить поле имя/значение в заголовок ответа.

Можно также использовать метод sendRedirect для перенаправления пользователя на другую страницу. Когда вызывается этот метод, web-cepвер посылает специальное сообщение браузеру для запроса другой страницы. Поэтому всегда осуществляется взаимодействие с клиентской стороной, прежде чем извлекается другая страница. Этот метод применяется в следующем примере.

Следующий листинг показывает страницу Login, которая предлагает пользователю ввести имя пользователя и пароль. Если оба значения правильны, пользователь перенаправляется на страницу Welcome. В противном случае пользователь увидит ту же самую страницу Login.

При первом вызове сервлета вызывается метод doGet. Метод doGet выводит форму. Пользователь может ввести имя пользователя и пароль и отправить форму. Отметим, что форма применяет метод POST, что означает, что на серверной стороне вызывается метод doPost и имя пользователя, и пароль сравниваются с предопределенными значениями. Если имя и пароль совпадают, пользователь перенаправляется на страницу Welcome. В противном случае метод doPost снова выводит форму Login вместе с сообщением об ошибке.

public class NewServlet extends HttpServlet {
private void sendLoginForm(HttpServletResponse response, boolean withErrorMessage) 
throws 
ServletException, IOException { 
   response.setContentType("text/html");
   PrintWriter out = response.getWriter(); 
   out.println("<html>"); 
   out.println("<head>"); 
   out.println("<TITLE>Login</TITLE>"); 
   out.println("</head>"); 
   out.println("<body>");
   if (withErrorMessage){
       out.println("Login failed. Please try again.
"); } out.println("
"); out.println("
Please enter your user name and password."); out.println("
<form method='POST'>"); out.println("
User Name: <INPUT TYPE='TEXT' NAME='userName'>"); out.println("
Password: <INPUT TYPE='PASSWORD' NAME='password'>"); out.println("
<INPUT TYPE='SUBMIT' VALUE='Submit'>"); out.println("</form>"); out.println("</body>"); out. println("</html>"); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { sendLoginForm(response, false); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userName = request.getParameter("userName"); String password = request.getParameter("password"); if (userName!=null && password!=null && userName.equals("jamesb") && password.equals( "007")) { response.sendRedirect("http://domain/app/WelcomePage");}
       else {
           sendLoginForm(response, true);
       }
   }}
Примечание: перенаправлении на ресурс, находящийся в том же приложении, не требуется определять полный URL, т. е. в предыдущем примере можно написать response.sendRedirect(«/app/WelcomePage»). Однако по соображениям эффективности метод sendRedirect обычно не используется для перенаправления пользователя на другой ресурс в том же приложении. В этих целях применяется другой метод.

В коде листинга присутствует закрытый (private) метод с именем sendLoginForm, который получает объект HttpServletResponse и логическое значение, указывающее, будет ли вместе с формой посылаться сообщение об ошибке. Метод sendLoginForm вызывается из методов doGet и doPost. Когда он вызывается из метода doGet, сообщение об ошибке не задается, так как это первый запрос страницы пользователем. Поэтому флаг withErrorMessge установлен в false. При вызове из метода doPost флаг принимает значение true, по¬скольку метод send Login Form вызывается из метода doPost только в том случае, если имя пользователя и пароль не соответствуют заданным.




Отправка специальных символов

[править]

Несколько символов имеют в HTML специальное назначение. Например, сим¬вол «меньше» (<) используется как открывающий символ тега HTML, а символ «больше» (>) является закрывающим символом тега HTML.

При отправке этих символов для отображения в браузере необходимо зако¬дировать их, чтобы они выводились правильно. Например, рассмотрим код листинга ниже. Метод doGet из SpecialCharacterServlet предназначен для отправки строки, которая будет выводиться браузером как следующий текст:

public class SpecialCharacterServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
ServletException, IOException {
   response.setContentType("text/html");
   PrintWriter out = response.getWriter(); 
   out.println("<HTHL>"); 
   out.println("<HEAD>");
   out.println("<TITLE>HTML Tutorial - Changing Line</TITLE>"); 
   out.println("</HEAD>"); 
   out.println("<BODY>");
   out.println("In HTML, you use <ВR> to change line.");
   out.println("</B0DY>"); 
   out.println("</HTML>");
}

Однако этот код создает проблему.

Поскольку <ВR> означает в HTML перевод строки, текст выводится неправильно. <ВR> интерпретируется как команда разбиения исходной строки на две, и выходные данные выводятся в двух строках. Если требуется вывести на экран специальный символ, его необходимо закодировать. Символ «меньше» (<) кодируется как «&lt», а символ «больше» (>) как «&gt». Другими специальными символами являются амперсанд (&) и двойная кавычка ("). Амперсанд (&) заменяется кодом «&аmp;», а двойная кавычка (") — «&quоt;». Кроме того, два и более пробелов всегда выводятся как один пробел, если не преобразовать каждый отдельный пробел в «&nbsр;».

Преобразование каждого вхождения специального символа является скучной работой. Имеется функция, которая делает это автоматически. Она называется encodeHtmlTag. Если строка String, посылаемая браузеру, содержит специальный символ, передайте ее на преобразование функции encodeHtmlTag.

Следующий листинг демонстрирует сервлет, который использует метод encodeHtmlTag для кодирования любой строки String со специальными символами:

public class SpecialCharacterServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
ServletException, IOException {
   response.setContentType("text/html");
   PrintWriter out = response.getWriter(); 
   out.println("<HTHL>"); 
   out.println("<HEAD>");
   out.println("<TITLE>HTML Tutorial - Changing Line</TITLE>"); 
   out.println("</HEAD>"); 
   out.println("<BODY>");
   out.println(encodeHtmlTag("In HTML, you use <ВR> to change line."));
   out.println("</B0DY>"); 
   out.println("</HTML>");
}
    public static String encodeHtmlTag(String tag) { 
       if (tag==null) 
       return null;
       int length = tag.length();
       StringBuffer encodedTag = new StringBuffer(2 * length);
       for (int i=0; i<length; i++) { 
       char c = tag.charAt(i); 
       if (c== '<' )
           encodedTag.append("&lt");  
       else if (c=='>')
           encodedTag.append("&gt"); 
       else if (c=='&') 
           encodedTag.append("&аmp;"); 
       else if (c=='"')
           encodedTag.append("&quоt;"); 
       else if (c==' ') 
           encodedTag.append("&nbsр;");
        else
           encodedTag.append(c);
       }
       return encodedTag.toString();
       }
       }

Отправка кода ошибки

HttpServletResponse позволяет также посылать предопределенные сообщения об ошибках. Интерфейс определяет ряд public static final целых чисел, которые начинаются с SC_. Например, SC_FORBIDDEN будет транслироваться в НТТР-ошибку 403.

Вместе с кодом ошибки можно послать индивидуальное сообщение об ошибке. При неудачной регистрации, вместо повторного вывода на экран страницы Login, можно послать НТТР-ошибку 403 и сообщение:

response.sendError (response.SC_F0RBIDDEN, "Login failed.');




Технология JavaServer Pages

[править]

JavaServer Pages

[править]

Серверные страницы Java (JavaServer Pages, JSP) представляют собой еще одну технологию Java для разработки web-приложений. JSP были выпущены в то время, когда технология сервлетов завоевала популярность как одна из лучших доступных web-технологий. Однако JSP не заменяют сервлеты. Фактически JSP являются расширением технологии сервлетов, и общая практика состоит в использовании сервлетов и страниц JSP в одном web-приложении.

Создание JSP является настолько простым, что можно писать приложения JSP, не имея больших знаний о базовом API. Однако высококлассный web-программист Java обязан знать как JSP, так и сервлеты. Даже если применяются только страницы JSP в web-приложениях Java, понимание технологии сервлетов по-прежнему очень важно. JSP используют те же методы, что применяются при программировании сервлетов. Например, в JSP работают с запросами HTTP и ответами HTTP, с параметрами запроса, атрибутами запроса, со средством управления сеансом, cookie, перезаписью URL и т.д.

Недостатки сервлетов

История Java-программирования на стороне сервера началась с сервлетов. Компания Sun представила сервлеты в 1996 г. как небольшие приложения на основе Java для добавления динамического содержимого в web-приложения. С ростом популярности Java сервлеты стали одной из самых распространенных технологий Интернета. Однако программисты сервлетов знают, сколь обременительным является программирование с помощью сервлетов, особенно, когда необходимо послать длинную страницу HTML, которая содержит мало кода. Рассмотрим в качестве примера листинг ниже. Этот код является фрагментом приложения на основе сервлетов, который выводит имена и значения всех параметров в запросе HTTP.

public class MyDearServlet extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response) 
   throws ServletException, IOException {
       doPost(request, response);
       }
       //Обработка запроса HTTP POST 
   public void doPost(HttpServletRequest request, HttpServletResponse response) 
   throws ServletException, IOException{
       response.setContentType("text/html");
       PrintWriter out = response.getWriter();
       out.println("<html>");
       out.println("<HEAD><TITLE>Using Servlets</TITLE></HEAD>");
       out.println("<body bgcolor='#123123'>");
       //Получение имен параметров
       Enumeration parameters = request.getParameterNames();
       String param = null;
       while (parameters.hasMoreElements()) {
           param = (String) parameters. nextElement();
           out.println(param +":"+ request.getParameter(param) +"
"); } out.println("</body>"); out.println("</html>"); out.close(); } //Конец метода doPost } //Конец класса

Почти половина содержимого, посланного методом doPost, является статическим HTML. Однако каждый тег HTML должен быть помещен в String и передан с помощью метода println объекта PrintWriter. Это скучная работа. Хуже того, страница HTML может быть значительно больше.

Другим недостатком использования сервлетов является то, что любое изменение будет требовать вмешательства программиста сервлета. Даже незначительная графическая модификация, например изменение значения атрибута BGCOLOR тега <BODY> с #DADADA на #FFFFFF, потребует работы программиста (который в этом случае будет действовать под управлением более сведущего в графике web-дизайнера).

Компания Sun увидела эту проблему и вскоре разработала ее решение. Результатом явилась технология JSP. Согласно web-сайту Sun, «технология JSP является расширением технологии сервлетов, созданным для поддержки разработки страниц HTML и XML». Применение JSP значительно облегчает комбинирование фиксированных или статических шаблонных данных с динамическим содержимым.

  Необходимо подчеркнуть, что «технология JSP является расширением технологии сервлетов». Это означает, что JSP не заменяет сервлеты как технологию написания серверных Интернет приложений. Фактически JSP были созданы на основе сервлетов и требуют, чтобы работала технология сервлетов.

JSP исправляет недостатки технологии сервлетов, например, позволяя программисту вставлять в код статическое содержимое. При работе с шаблоном страницы HTML, написанным дизайнером Web, программист может добавить код на страницу HTML и сохранить ее как файл .jsp. Если впоследствии дизайнеру Web понадобится изменить цвет фона тела HTML, он сможет сделать это без привлечения программиста, открыв файл .jsp и отредактировав его.

<%@page import="java.util.Enumeration"%>
<%@page contentType="text/html" pageEncoding="windows-1251"%>
<!DOCTYPE html>
<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
       <title>JSP Page</title>
   </head>
   <body bgcjljr=#DADADA>
       <%
//Получение имен параметров
       Enumeration parameters = request.getParameterNames();
       String param = null;
       while (parameters.hasMoreElements()) {
       param = (String) parameters.nextElement(); 
       out. println(param +":"	+ request. getParameter(param) +"
"); } out.close();  %> </body> </html>

Можно видеть, что теги <HTML> не затрагиваются. Чтобы добавить динамическое содержимое, нужно лишь поместить код между тегами <%...%>.

Еще раз подчеркнем, что JSP не являются заменой сервлетов. Скорее, технология JSP и сервлеты совместно предоставляют привлекательное решение для программирования и создания сценариев Web, предлагая независимость от платформы, улучшенную производительность, разделение логики и представления, легкость администрирования, расширяемость на уровень предприятия и, самое важное, легкость в использовании.




Создание первой серверной страницы. Принцип работы JSP

[править]

Сегодня мы напишем простую страницу JSP и выполним ее. Для выполнения приложений JSP используем Tomcat 8. Если Tomcat 8 установлен и сконфигурирован для сервлетных приложений, то больше ничего делать не надо.

  Примечание: В контексте JSP, Tomcat часто называют «контейнером JSP». Однако Tomcat используется также для выполнения сервлетов, поэтому его называют еще контейнером сервлетов/JSP.

JSP существенно упрощает работу с сервлетами. Для выполнения своей страницы JSP необходимо только сконфигурировать контейнер JSP (Tomcat) и написать страницу JSP. Конфигурирование выполняется лишь однажды в самом начале. Не требуется никакой компиляции.

Создание файла JSP

В NetBeans файл создается следующим образом, в созданном веб-проекте кликните правой кнопкой мыши на папку каталога «веб-страницы» → новый → JSP.

Страница JSP содержит вперемешку теги HTML и код Java. Теги HTML выполняют задачу представления, а код создает содержимое. В своей наиболее простой форме страница JSP может включать в себя только HTML, как показано в листинге ниже:

<%@page contentType="text/html" pageEncoding="windows-1251"%>
<!DOCTYPE html>
<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
       <title>JSP Page</title>
   </head>
   <body>
       jsp это легко
   </body>
</html>


Конечно, код в листингe выше не является полезным, но он иллюстрирует тот факт, что страница JSP вовсе не обязана иметь код. Если страница статичес¬кая, нет необходимости помещать ее в файл JSP, так как файлы JSP обрабаты¬ваются медленнее, чем файлы HTML. Использовать файл JSP для тегов HTML можно в том случае, если предполагается добавить в него в будущем код Java. Это избавит от проблемы изменения ссылок на эту страницу.

При помещении кода Java в файл JSP код вставляется между тегами <% ... %>. Например, листинг ниже является примером соединения кода Java и HTML в файле JSP.

<%@page contentType="text/html" pageEncoding="windows-1251"%>
<!DOCTYPE html>
<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
       <title>JSP Page</title>
   </head>
   <body>
       <%
       out.println("jsp это легко");   
       %>
   </body>
</html>

Как мы видим код листинга использует код Java для отправки текста. Функции out.println служит для отправки String web-браузеру.

  Отметим также, что вывод страницы JSP является простым текстом, состоящим из тегов HTML. Никакой код страницы не посылается браузеру.

Другой пример представлен в листинге ниже. Этот фрагмент кода выводит строку «Добро пожаловать. Время сервера:» и время сервера:

<%@page contentType="text/html" pageEncoding="windows-1251"%>
<!DOCTYPE html>
<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
       <title>JSP Page</title>
   </head>
   <body bgcjljr=#DADADA>
       <%
//Получение имен параметров
       Enumeration parameters = request.getParameterNames();
       String param = null;
       while (parameters.hasMoreElements()) {
       param = (String) parameters.nextElement(); 
       out. println(param +":"	+ request. getParameter(param) +"
"); } out.close();  %> </body> </html>

Принцип работы JSP

Внутри контейнера JSP имеется специальный сервлет, называемый компиля¬тором страниц. Контейнер сервлетов сконфигурирован для переадресации этому компилятору всех запросов HTTP с URL, которые соответствуют фай¬ловому расширению .jsp. Компилятор страниц превращает контейнер сервле¬тов в контейнер JSP. Если страница .jsp вызывается в первый раз, компилятор страниц производит синтаксический разбор и компилирует страницу .jsp в класс сервлета. Если компиляция успешна, класс сервлета jsp загружается в память. При последующих вызовах класс сервлета для этой страницы .jsp уже находится в памяти; однако он может обновляться. Поэтому сервлет компи¬ляции страниц всегда будет сравнивать отметки времени сервлета jsp и стра¬ницы jsp. Если страница .jsp имеет более позднюю отметку времени, то требует¬ся перекомпиляция. При таком процессе после развертывания страницы JSP компилируются только один раз.

Можно предположить, что после развертывания первый запрос пользовате¬лем страницы .jsp будет обрабатываться медленно, поскольку необходимо вре¬мя на компиляцию файла .jsp в сервлет jsp. Во избежание этого механизм JSP позволяет предварительно откомпилировать страницы .jsp до получения како¬го-либо запроса. Либо можно развернуть приложение JSP как архивный файл в форме компилированного сервлета.




Скриплеты. Директивы

[править]

Внешний признак скриптлета — обрамляющие скриптлет символы <%= и %>. Мы уже встречались с JSP-вставками в HTML-файл, когда на предыдущем уроке при помощи символов <% и %> осуществляет вставку выражения в поток HTML-кода. Не всегда, оказывается, удобно вставлять Java-выражения в HTML-текст. Для создания блоков программ Java в HTML-странице удобно пользоваться скриптлетами. Скриптлет сам по себе не должен генерировать HTML-код, хотя, конечно, он может это делать.

Скриптлет — это кусок Java-программы, встроенной в HTML-страницу. Создадим JSP файл и вставим в него скриптлет, который будет выводить некоторый текст:

<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
       <title>JSP Page</title>
   </head>
   <body>
       Just simplest jsp test
       Current time is 
       <%= new java.util.Date()%>
       <%
        Date date=new java.util.Date();
       %>
       Привет! Сегодня <%= date%>
   </body> 
</html> 

Скриплеты и HTML

В предыдущем примере мы использовали метод «out» для того, чтобы выводить HTML-текст. При программировании JSP вряд ли всегда будет удобно выводить HTML-текст средствами потока вывода «out». Допустим, нам нужно вывести результат поиска по базе данных. Это удобно сделать в виде HTML-таблицы. Для этого вовсе не обязательно использовать out. Более удобное решение показано в следующем листинге:

<%@page contentType="text/html" pageEncoding="windows-1251"%>
<!DOCTYPE html>
<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
       <title>JSP Page</title>
       Генерация таблицы
   </head>
   <body>
       <tаble border=2 wigth="70%">
           <%
               for (int i=0;i<10;i++){
           %>

Число <%= i+1%> <%}%>

    </body>
 </html>

Директивы JSP

Директивы JSP используются для вставки существующих фрагментов кода в текущий текст, они напоминают директивы препроцессора. Директивы помещаются между знаками, <%@ и %>. Мы уже использовали директивы в предыдущих примерах:

 <%@page contentType="text/html" pageEncoding="windows-1251"%>

Кроме вставки уже существующих фрагментов кола директивы могут быть использованы для импортирования файлов:

 <%@ include file="jsp.jsp" %>

Декларации в JSP

В JSP существует специальный ярлык, внутри которого описываются новые типы данных. Объявления типов и описания методов производятся между знаками <%! и %>. Например, описание методов может быть следующим:

<%@page import="java.util.Date"%>
<%@page contentType="text/html" pageEncoding="windows-1251"%>
<!DOCTYPE html>
<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
       <title>JSP Page</title>
   </head>
   <body>
       <%!
   Date theDate = new Date();
   Date getDate()
   {
   System.out.println("In getDate || method"); 
   return theDate;
   }
   %>
   Hello! The time is now <%= getDate() %>
   </body>
</html>




Обработка форм с использованием компонента Beans

[править]

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

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

Требования к проектированию компонентов JavaBeans

Требования к проектированию компонентов JavaBeans определяют свойства класса и методы public, дающие доступ к свойствам. Свойство компонента JavaBeans может быть:

  1. для чтения/записи, только для чтения, только для записи
  2. простым (содержащим одно значение) или индексным (представляющим массив значений)

Не существует требования, чтобы свойство реализовывалось переменной экземпляра. Свойство просто должно быть доступно через методы public, следующие определенным правилам:

  1. Для каждого читаемого свойства компонент должен иметь метод в виде PropertyClass getProperty() {...}
  2. Для каждого записываемого свойства компонент должен иметь метод в виде setProperty(PropertyClass pc){...}

Кроме методов свойств компонент JavaBeans должен определить конструктор без параметров.

Методы getters setters

Компонент JavaBean должен удовлетворять определенным соглашениям о наименовании методов и экспортируемых событий. Одним из важных понятий технологии JavaBeans является внешний интерфейс properties (свойства). Property JavaBean – это методы getters и setters, обеспечивающие доступ к информации о внутреннем состоянии компонента JavaBean. Для обращения к компонентам JavaBeans на странице JSP необходимо использовать следующее описание тега в разделе head :

  <jsp:useBean id="BeanID" [scope="page | request | session | application"] 

class="BeanClass" />

Идентификатор BeanID определяет имя компонента JavaBean, являющееся уникальным в области видимости, определенной атрибутом scope. По умолчанию принимается область видимости scope="page", т.е. текущая страница JSP.

Обязательный атрибут класса компонента "class" может быть описан следующим способом:

 class="имя класса" [type="полное имя суперкласса"]

Свойства JavaBean - jsp:setProperty jsp:getProperty

Свойство JavaBean компонента устанавливается тегом jsp:setProperty. Пример :

  <jsp:setProperty name="myBean" property="Имя свойства" value="Строка или выражение JSP" />

Для чтения свойства компонента JavaBean с именем myBean используется тег jsp:getProperty :

  <jsp:getProperty name="myBean" property="Имя свойства" />

Использование JavaBeans

Рассмотрим простой пример, в котором на странице JSP будет выведено приветствие и введённые данные пользователя в HTML форму. Первым делом создаем HTML форму и записываем файл как «index.jsp»

<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
       <title>JSP Page</title>
   </head>
   <body>
       Заполните форму
       <form name="Name Action Form" action="response.jsp">
           Введите имя:
           <input type="text" name="name" value="" />
Введите фамилию: <input type="text" name="lastname" value="" />
Введите возраст: <input type="text" name="age" value="" />
<input type="submit" value="OK" /> </form> </body> </html>

В форме задали три имени для различных элементов: name, lastname, age. Создаем класс NameHandler:

public class NameHandler {
private String name;
private String lastname;
private String age;
public NameHandler (){
   name = null;
   lastname=null;
   age=null;
}
   public String getName() {
       return name;
   }
   public void setName(String name) {
       this.name = name;
   }
   
   public String getLastname() {
       return lastname;
   }
   
   public void setLastname(String lastname) {
       this.lastname = lastname;
   }
   
   public String getAge() {
       return age;
   }
   
   public void setAge(String age) {
       this.age = age;
   }   
}

В этом классе описаны get и set для каждого элемента формы на основе имени этого элемента.

После этого переходим к созданию JSP-файла «response»:

<html>
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
       <title>JSP Page</title>
   </head>
   <body>
       <jsp:useBean id="mybean" scope="session" class="org.mypackage.hello.NameHandler" 
/>
       <jsp:setProperty name="mybean" property="*" />
       Привет, пользователь!
       Ваше имя:<jsp:getProperty name="mybean" property="name" />
Ваша фамилия:<%= mybean.getLastname()%>
Ваш возраст:<%= mybean.getAge()%> </body> </html>

Запускаем приложение, вводим форму необходимые данные нажимаем кнопку «ок».




JavaScript API Яндекс карты

[править]

Яндекс карты

[править]

JavaScript API Яндекс карты

[править]

JavaScript API — это программная библиотека для работы с картами в браузерах, а также в приложениях.




JSON и оптимальное добавление множества меток

[править]

JSON (JavaScript Object Notation) - простой формат обмена данными, удобный для чтения и написания как человеком, так и компьютером. Он основан на подмножестве языка программирования JavaScript. JSON - текстовый формат, полностью независимый от языка реализации, но он использует соглашения, знакомые программистам C-подобных языков, таких как C, C++, C#, Java, JavaScript, Perl, Python и многих других. Эти свойства делают JSON идеальным языком обмена данными.

JSON основан на двух структурах данных:

  1. Коллекция пар ключ/значение. В разных языках, эта концепция реализована как объект, запись, структура, словарь, хэш, именованный список или ассоциативный массив.
  2. Упорядоченный список значений. В большинстве языков это реализовано как массив, вектор, список или последовательность.

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

В нотации JSON это выглядит так:

Объект - неупорядоченный набор пар ключ/значение. Объект начинается с {(открывающей фигурной скобки) и заканчивается} (закрывающей фигурной скобкой). Каждое имя сопровождается: (двоеточием), пары ключ/значение разделяются, (запятой).

Массив - упорядоченная коллекция значений. Массив начинается с [(открывающей квадратной скобки) и заканчивается] (закрывающей квадратной скобкой). Значения разделены, (запятой).

Значение может быть строкой в двойных кавычках, числом, true, false, null, объектом или массивом. Эти структуры могут быть вложенными.

Строка- коллекция нуля или больше символов Unicode, заключенная в двойные кавычки, используя \ (обратную косую черту) в качестве символа экранирования. Символ представляется как односимвольная строка. Похожий синтаксис используется в C и Java. Число представляется так же, как в C или Java, кроме того, что используется толко десятичная система счисления. Благодаря JSON оптимально добавлять на Яндекс карту множество меток.

ObjectManager

Менеджер объектов. Позволяет оптимально отображать, кластеризовать и управлять видимостью объектов. Обратите внимание, что у объектов, отрисованных на карте через данный менеджер, нельзя включать режимы редактирования и перетаскивания.




Глоссарий

[править]

Библиотека Java — это сборник классов.

Веб-браузер - прикладное программное обеспечение для просмотра веб-страниц, содержания веб-документов, компьютерных файлов и их каталогов; управления веб-приложениями; а также для решения других задач.

Веб-сервер - сервер, принимающий HTTP-запросы от клиентов, обычно веб-браузеров, и выдающий им HTTP-ответы, как правило, вместе с HTML-страницей, изображением, файлом, медиа-потоком или другими данными.

Веб-приложение - клиент-серверное приложение, в котором клиент взаимодействует с сервером при помощи браузера, а за сервер отвечает веб-сервер.

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

Директива (указание) - по использованию похож на термин «команда», так как также используется для описания некоторых конструкций языка программирования (то есть указаний компилятору или ассемблеру особенностей обработки при компиляции).

Интернет - Всемирная информационная компьютерная сеть, связывающая между собой как пользователей компьютерных сетей, так и пользователей индивидуальных компьютеров для обмена информацией.

Интерфейс - функциональность, которую некоторый программный компонент предоставляет другим программным компонентам

Класс Java — это шаблон для создания объекта. Класс определяет структуру объекта и его методы, образующие функциональный интерфейс.

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

Листинг - текст компьютерной программы на каком-либо языке программирования.

Метод Java — это законченная последовательность действий (инструкций), направленных на решение отдельной задачи.

Объект java – экземпляр Java класса.

Пакет Java - механизм, позволяющий организовать Java классы в пространстве имен.

Парсер – это программа дающая возможность компьютеру «читать» – сравнивать предложенные слова с имеющимися во Всемирной сети

Парсинг – это автоматический сбор информации с какого-либо источника.

Поток - абстракция, используемая для чтения или записи файлов

Сервер - программный компонент вычислительной системы, выполняющий сервисные (обслуживающие) функции по запросу клиента, предоставляя ему доступ к определённым ресурсам или услугам.

Сервлет – это Java-программа, которая в качестве своего суперкласса использует класс HttpServlet.

Сигнатура - характеристическая часть определения функции в программировании.

Скрипты (сценарии)— это отдельные последовательности действий, созданные для автоматического выполнения задачи.

Файл - именованная область данных на носителе информации.

Язык программирования - формальный язык, предназначенный для записи компьютерных программ.

API (application programming interface, программный интерфейс приложения) — описание способов набор классов, процедур, функций, структур или констант), которыми одна компьютерная программа может взаимодействовать с другой программой.

Аpache Tomcat - контейнер сервлетов с открытым исходным кодом, разрабатываемый Apache Software Foundation.

Cookie - небольшой фрагмент данных, отправленный веб-сервером и хранимый на компьютере пользователя.

CSS (Cascading Style Sheets — каскадные таблицы стилей) — формальный язык описания внешнего вида документа, написанного с использованием языка разметки.

HTML (HyperText Markup Language — «язык гипертекстовой разметки») — стандартизированный язык разметки документов во Всемирной паутине.

HTTP (HyperText Transfer Protocol — «протокол передачи гипертекста») — протокол прикладного уровня передачи данных изначально — в виде гипертекстовых документов в формате «HTML», в настоящий момент используется для передачи произвольных данных.

Java - сильно типизированный объектно-ориентированный язык программирования, разработанный компанией Sun Microsystems (в последующем приобретённой компанией Oracle).

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

JavaScript API — это программная библиотека для работы с картами в браузерах, а также в приложениях.

JavaServer Pages (серверные страницы Java) – технология для разработки веб-приложений

JavaBeans — классы в языке Java, написанные по определённым правилам. Они используются для объединения нескольких объектов в один для удобной передачи данных.

JSON (JavaScript Object Notation) - простой формат обмена данными, удобный для чтения и написания как человеком, так и компьютером. Он основан на подмножестве языка программирования JavaScript.

Jsoup — это библиотека Java для работы с реальным HTML

ObjectManager - менеджер объектов. Позволяет оптимально отображать, кластеризовать и управлять видимостью объектов

Refere - в протоколе HTTP один из заголовков запроса клиента

While list - это практика явного разрешения некоторым идентифицированным объектам доступа к определенной привилегии, услуге, мобильности, доступу или распознаванию.

XML (eXtensible Markup Language) — расширяемый язык разметки.

XSS - тип атаки на веб-системы, заключающийся во внедрении в выдаваемую веб-системой страницу вредоносного кода (который будет выполнен на компьютере пользователя при открытии им этой страницы) и взаимодействии этого кода с веб-сервером злоумышленника.