<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.linuxformat.ru/wiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF89%3AJava_EE</id>
		<title>LXF89:Java EE - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF89%3AJava_EE"/>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;action=history"/>
		<updated>2026-05-13T02:53:32Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.19.20+dfsg-0+deb7u3</generator>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;diff=6352&amp;oldid=prev</id>
		<title>Dionysius: /* Что нам потребуется? */</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;diff=6352&amp;oldid=prev"/>
				<updated>2008-12-30T17:29:53Z</updated>
		
		<summary type="html">&lt;p&gt;‎&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Что нам потребуется?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr valign='top'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Предыдущая&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Версия 17:29, 30 декабря 2008&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 60:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 60:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Библиотека Jetty (http://www.mortbay.org/). В принципе, это полноценный web-сервер, который может очень и очень многое. Нам будет полезна его особенность, позволяющая встроить web-сервер в наше приложение.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;* Библиотека Jetty (http://www.mortbay.org/). В принципе, это полноценный web-сервер, который может очень и очень многое. Нам будет полезна его особенность, позволяющая встроить web-сервер в наше приложение.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Все необходимые библиотеки есть на прилагаемом компакт-диске.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Все необходимые библиотеки &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;[[Media:AddressBook.tar.bz2|и исходный код примера]] &lt;/ins&gt;есть на прилагаемом компакт-диске.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;=== Что мы будем делать? ===&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;=== Что мы будем делать? ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Dionysius</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;diff=5142&amp;oldid=prev</id>
		<title>Haanp в 18:04, 12 октября 2008</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;diff=5142&amp;oldid=prev"/>
				<updated>2008-10-12T18:04:31Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr valign='top'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Предыдущая&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Версия 18:04, 12 октября 2008&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 331:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 331:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Телефон: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=\&amp;quot;text\&amp;quot; name=\&amp;quot;number\&amp;quot; value=\&amp;quot;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Телефон: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=\&amp;quot;text\&amp;quot; name=\&amp;quot;number\&amp;quot; value=\&amp;quot;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; aNumber + &amp;quot;\&amp;quot;/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; aNumber + &amp;quot;\&amp;quot;/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Примечания: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=\&amp;quot;text\&amp;quot; name=\ &amp;quot;comment\&amp;quot; value=\&amp;quot;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Примечания: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=\&amp;quot;text\&amp;quot; name=\&amp;quot;comment\&amp;quot; value=\&amp;quot;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; aComment + &amp;quot;\&amp;quot;/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; aComment + &amp;quot;\&amp;quot;/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td colspan=\&amp;quot;2\&amp;quot; align=\&amp;quot;center\&amp;quot;&amp;gt;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td colspan=\&amp;quot;2\&amp;quot; align=\&amp;quot;center\&amp;quot;&amp;gt;&amp;quot; +&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Haanp</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;diff=2535&amp;oldid=prev</id>
		<title>Lockal: цикл + кавычки</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;diff=2535&amp;oldid=prev"/>
				<updated>2008-03-17T17:37:20Z</updated>
		
		<summary type="html">&lt;p&gt;цикл + кавычки&lt;/p&gt;
&lt;a href=&quot;http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;amp;diff=2535&amp;amp;oldid=2263&quot;&gt;Внесённые изменения&lt;/a&gt;</summary>
		<author><name>Lockal</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;diff=2263&amp;oldid=prev</id>
		<title>Interlace: Новая: '''Новая серия!''' Учимся писать серверные приложения на Java  == Адресная книга == ''ЧАСТЬ 1: Театр, как извес...</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF89:Java_EE&amp;diff=2263&amp;oldid=prev"/>
				<updated>2008-03-16T18:26:48Z</updated>
		
		<summary type="html">&lt;p&gt;Новая: &amp;#039;&amp;#039;&amp;#039;Новая серия!&amp;#039;&amp;#039;&amp;#039; Учимся писать серверные приложения на Java  == Адресная книга == &amp;#039;&amp;#039;ЧАСТЬ 1: Театр, как извес...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;'''Новая серия!''' Учимся писать серверные приложения на Java&lt;br /&gt;
&lt;br /&gt;
== Адресная книга ==&lt;br /&gt;
''ЧАСТЬ 1: Театр, как известно, начинается с вешалки, а приложения уровня предприятий – с адресной книги: надо же где-то хранить сведения о клиентах. '''Александр Бабаев''' готов познакомить вас с азбукой Java EE.''&lt;br /&gt;
&lt;br /&gt;
{{Врезка&lt;br /&gt;
|Заголовок=Наш эксперт&lt;br /&gt;
|Содержание=&lt;br /&gt;
'''Александр Бабаев'''&amp;lt;br&amp;gt;Разработчик открытой мультиблог-системы jDnevnik – победитель конкурсов IBM WAS CE Contest 2006 и конкурса проектов для разработчиков на Java - Java конкурс 2005.&lt;br /&gt;
|Ширина=150px}}&lt;br /&gt;
&lt;br /&gt;
Один из самых распространенных языков программирования для Интернета на настоящий момент – это PHP. Этот язык изначально задумывался для создания домашних страничек, небольших сайтов – и там работает замечательно.&lt;br /&gt;
&lt;br /&gt;
В отличие от PHP, Java (та ее часть, которая помогает разрабатывать серверные приложения) сразу создавалась для крупных приложений уровня предприятия (так называемых Enterprise Applications). Поэтому в Java есть множество механизмов, которые помогают быстро строить очень крупные приложения. Очень крупные – это десятки тысяч транзакций в минуту. Сложных транзакций.&lt;br /&gt;
&lt;br /&gt;
Обо всех возможностях этой технологии не рассказать ни в рамках одной статьи, ни даже в десятке. Но основные блоки JEE (Java Enterprise Edition), которые полезны не только в крупных приложениях, но и в средних и небольших, мы изучим обязательно. А на основании этого опыта можно будет двигаться дальше, читать книги, разрабатывать сложные системы.&lt;br /&gt;
&lt;br /&gt;
=== Сервлеты ===&lt;br /&gt;
[[Изображение:Img_89_82_1.jpg|thumb|right|450px|'''Рис. 1.''' Процесс обработки запроса]]&lt;br /&gt;
Для начала решим, что же такое сервлет (servlet)? Этим термином принято называть серверное приложение, но чем отличается серверное приложение от клиентского? Клиентское ПО формирует запросы и отсылает их серверному, а задача серверной части – обработать запрос и вернуть на него ответ ('''рис. 1''').&lt;br /&gt;
&lt;br /&gt;
На стороне клиента присутствуют только действия, которые выполняются браузером (показ формы на HTML-странице, формирование стандартизованного запроса).&lt;br /&gt;
&lt;br /&gt;
Серверная сторона в Java обычно состоит из контейнера, который содержит один или несколько сервлетов. Контейнер получает запрос, решает, какому сервлету он предназначен, и запускает на выполнение этот сервлет. Формально происходит примерно следующее:&lt;br /&gt;
&lt;br /&gt;
* Пришедший от клиента запрос анализируется сервлет-контейнером, который создает на его основе специальный объект '''javax.servlet.ServletRequest'''.&lt;br /&gt;
* Контейнер решает (как – обычно описывается в специальном конфигурационном файле), какому сервлету предназначен запрос, и передает ему созданный на предыдущем шаге объект '''javax.servlet.ServletRequest''', а также объект '''javax.servlet.ServletResponse''' – шаблон ответа, в который сервлет пишет все, что нужно возвратить клиенту.&lt;br /&gt;
* Сервлет обрабатывает запрос, заполняет объект '''javax.servlet.ServletResponse''' и после этого завершает работу.&lt;br /&gt;
* Контейнер получает заполненный объект '''javax.servlet.ServletResponse''', после чего преобразует его в стандартизованное сообщение и передает клиенту.&lt;br /&gt;
&lt;br /&gt;
=== Что нам потребуется? ===&lt;br /&gt;
{{Врезка&lt;br /&gt;
|Заголовок=Коротко о HTTP&lt;br /&gt;
|Содержание=&lt;br /&gt;
Протокол HTTP был предложен Тимом Бернерсом-Ли, работавшим тогда в CERN, в марте 1990 года как механизм для доступа к документам в Интернете и облегчения навигации посредством использования гипертекста. В HTTP разделяются понятия «запрос» и «ответ», то есть то, как браузер запрашивает страницу и то, чем сервер на это отвечает. И запрос, и ответ состоят из заголовка и тела. В запросе присутствует еще и строка запроса. Заголовок описывает передаваемые данные, внутри тела передается обычно результат (страница HTML или файл). Существует несколько типов запросов, но наиболее распространены два:&lt;br /&gt;
* '''GET''' Запрашивает содержимое указанного ресурса.&lt;br /&gt;
* '''POST''' Передает пользовательские данные (например, из формы HTML) заданному ресурсу. Данные включаются в тело запроса.&lt;br /&gt;
&lt;br /&gt;
Вот пример (не точный) простого HTTP-диалога:&amp;lt;br&amp;gt;&lt;br /&gt;
'''Запрос'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
GET /site/index.html HTTP/1.1&lt;br /&gt;
Host: ru.wikipedia.org&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''Ответ'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HTTP/1.0 200 OK&lt;br /&gt;
Server: Apache&lt;br /&gt;
Content-Type: text/html; charset=utf-8&lt;br /&gt;
Content-Length: 2121&lt;br /&gt;
(Дальше идет 2121 байт текста странички index.html)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|Ширина=45%}}&lt;br /&gt;
Мы предполагаем, что читатель знаком с тем, что такое HTML, и пробовал делать «странички на PHP» или чем-то аналогичном. Если словосочетания «GET-запрос», «POST-запрос» являются для вас китайской грамотой – прочтите врезку «Коротко об HTTP» (и запаситесь терпением). Подробнее про протокол HTTP можно прочитать в RFC2616, например тут: http://www.w3.org/Protocols/rfc2616/rfc2616.html.&lt;br /&gt;
&lt;br /&gt;
Для работы нам понадобятся следующие инструменты:&lt;br /&gt;
* JDK 5 (или JDK 6) – если вы выполняли все задания предыдущей серии уроков Java, нужный дистрибутив, скорее всего, уже имеется в вашей системе (вы ведь выполняли задания, не так ли?). JDK можно бесплатно загрузить с сайта http://java.sun.com или установить из репозиториев вашего дистрибутива Linux. После установки JDK необходимо убедиться, что пути к каталогу '''$JDK/bin''' прописаны в переменной окружения PATH, а каталоги, в которых располагаются библиотеки классов, перечислены в CLASSPATH.&lt;br /&gt;
* Ваш любимый текстовый редактор.&lt;br /&gt;
* Библиотека Jetty (http://www.mortbay.org/). В принципе, это полноценный web-сервер, который может очень и очень многое. Нам будет полезна его особенность, позволяющая встроить web-сервер в наше приложение.&lt;br /&gt;
&lt;br /&gt;
Все необходимые библиотеки есть на прилагаемом компакт-диске.&lt;br /&gt;
&lt;br /&gt;
=== Что мы будем делать? ===&lt;br /&gt;
Для примера мы возьмем и напишем корпоративную адресную книгу, в которой будем сохранять телефоны сотрудников, причем каждый сможет добавить телефоны нужных людей, и все смогут просмотреть сохраненные телефоны. Итак, начнем.&lt;br /&gt;
&lt;br /&gt;
Создадим иерархию каталогов для проекта, например, такую:&lt;br /&gt;
* '''~/Programming/AddressBook/.'''&lt;br /&gt;
* '''build''' – каталог для скомпилированных классов.&lt;br /&gt;
* '''src''' – исходные тексты.&lt;br /&gt;
* '''libs''' – каталог для библиотек.&lt;br /&gt;
&lt;br /&gt;
Заполним каталоги. Для начала возьмите Jetty, распакуйте архив, найдите в нем файлы '''jetty-6.1.0rc3.jar'''; '''jetty-util-6.1.0rc3.jar'''; '''servlet-api-2.5.jar''' и поместите их в каталог '''libs''' (можно взять и другую версию,&lt;br /&gt;
правда, с известной долей осторожности – иногда меняются API, тогда наша программа просто не скомпилируется).&lt;br /&gt;
&lt;br /&gt;
Теперь настало время придумать, как будет работать наша телефонная книга. Разумно будет создать четыре основных страницы:&lt;br /&gt;
* Главная – на ней будут ссылки помещены на остальные страницы приложения.&lt;br /&gt;
* Страница добавления нового контакта.&lt;br /&gt;
* Страница редактирования контакта.&lt;br /&gt;
* Страница поиска/просмотра контактов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Классов в нашем приложении будет всего три:&lt;br /&gt;
* '''AddressBook.''' Главный класс, который запускается и «висит» в памяти, обрабатывая запросы пользователей. Обычно эту роль выполняет уже упомянутый сервлет-контейнер (роль которого может выполнять, например, Apache Tomcat), но мы избавились от него, использовав Jetty.&lt;br /&gt;
* '''AddressBookHandler.''' Класс-обработчик запросов пользователей. Именно этот класс и называется сервлетом. Он обычно подключается к сервлет-контейнеру через специфический конфигурационный файл, но мы избавились и от этого – спасибо, Jetty!&lt;br /&gt;
* '''Contact.''' Класс, который содержит поля контакта. Эти поля будут выводиться на странице и редактироваться. Его код очень простой:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 1.''' Контакт&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import java.io.*;&lt;br /&gt;
public class Contact implements Serializable {&lt;br /&gt;
    private String _name = “”;&lt;br /&gt;
    private String _number = “”;&lt;br /&gt;
    private String _comment = “”;&lt;br /&gt;
    public String getName() { return _name; }&lt;br /&gt;
    public String getNumber() { return _number; }&lt;br /&gt;
    public String getComment() { return _comment; }&lt;br /&gt;
    public void setData(String aName, String aNumber, String aComment) {&lt;br /&gt;
        _name = aName;&lt;br /&gt;
        _number = aNumber;&lt;br /&gt;
        _comment = aComment;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Основной класс/класс запуска приложения (AddressBook) ===&lt;br /&gt;
Этот класс содержит метод '''main''', инициализирует Jetty и подключает сервлет ('''AddressBookHandler''', '''листинг 2''').&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 2.''' Класс запуска приложения&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import org.mortbay.jetty.*;&lt;br /&gt;
import org.mortbay.jetty.nio.*;&lt;br /&gt;
&lt;br /&gt;
import java.util.*;&lt;br /&gt;
import java.io.*;&lt;br /&gt;
&lt;br /&gt;
public class AddressBook {&lt;br /&gt;
    private void start() throws Exception {&lt;br /&gt;
        try {&lt;br /&gt;
            _contactsByName = (SortedMap&amp;lt;String, Contact&amp;gt;) new XStream().&lt;br /&gt;
                fromXML(new FileReader(“contacts.xml”));&lt;br /&gt;
        } catch (Exception e) { }&lt;br /&gt;
&lt;br /&gt;
        Server _jettyServer = new Server();&lt;br /&gt;
        Connector connector = new SelectChannelConnector();&lt;br /&gt;
        connector.setPort(8081);&lt;br /&gt;
        _jettyServer.setConnectors(new Connector[]{connector});&lt;br /&gt;
        _jettyServer.setStopAtShutdown(true);&lt;br /&gt;
        Handler handler = new AddressBookHandler(this);&lt;br /&gt;
        _jettyServer.setHandler(handler);&lt;br /&gt;
        _jettyServer.start();&lt;br /&gt;
    }&lt;br /&gt;
    public static void main(String[] args) throws Exception {&lt;br /&gt;
        new AddressBook().start();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также этот класс содержит саму адресную книгу:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 3.''' Адресная книга&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private SortedMap&amp;lt;String, Contact&amp;gt; _contactsByName = new TreeMap&amp;lt;String,Contact&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
public SortedMap&amp;lt;String, Contact&amp;gt; getContactsByName() {&lt;br /&gt;
    return _contactsByName;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Contact getContactByNumber(String aNumber) {&lt;br /&gt;
    for (Map.Entry&amp;lt;String, Contact&amp;gt; entry : _contactsByName.entrySet()) {&lt;br /&gt;
        if (entry.getValue().getNumber().equals(aNumber)) {&lt;br /&gt;
            return entry.getValue();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return null;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
и методы, которые позволяют добавлять/удалять/редактировать контакты:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 4.''' Работа с контактами&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void addContact(String aName, String aNumber, String aComment)&lt;br /&gt;
throws IOException {&lt;br /&gt;
    Contact contact = new Contact();&lt;br /&gt;
    contact.setData(aName, aNumber, aComment);&lt;br /&gt;
    _contactsByName.put(aName, contact);&lt;br /&gt;
    saveContactsInformation();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void removeContactByNumber(String aNumber) throws IOException {&lt;br /&gt;
    Contact contact = getContactByNumber(aNumber);&lt;br /&gt;
    if (contact != null) {&lt;br /&gt;
        _contactsByName.remove(contact.getName());&lt;br /&gt;
        saveContactsInformation();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void editContact(String aEditNumber, String aName, String aNumber, String aComment)&lt;br /&gt;
throws IOException {&lt;br /&gt;
    Contact contact = getContactByNumber(aEditNumber);&lt;br /&gt;
    if (contact != null) {&lt;br /&gt;
        contact.setData(aName, aNumber, aComment);&lt;br /&gt;
        saveContactsInformation();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
private void saveContactsInformation() throws IOException {&lt;br /&gt;
    new XStream().toXML(_contactsByName, new FileWriter(“contacts.xml”));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Класс-обработчик (AddressBookHandler) ===&lt;br /&gt;
Обработка событий пользователя концентрируется в одном методе ('''public void handle(…)''') класса '''AddressBookHandler'''. Самые главные параметры этого метода – второй '''aHttpServletRequest''' и третий '''aHttpServletResponse'''. '''Request''' – это запрос. В нем хранятся все данные, которые передал нам браузер пользователя. А '''Response''' – это объект, в который нужно записать все, что требуется передать пользователю. Например, на любой запрос пользователя можно отвечать страницей с гордым заголовком «адресная книга» ('''листинг 5'''):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 5.''' Код обработчика&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import org.mortbay.jetty.handler.*;&lt;br /&gt;
import org.mortbay.jetty.*;&lt;br /&gt;
&lt;br /&gt;
import javax.servlet.*;&lt;br /&gt;
import javax.servlet.http.*;&lt;br /&gt;
import java.io.*;&lt;br /&gt;
import java.util.*;&lt;br /&gt;
&lt;br /&gt;
public class AddressBookHandler extends AbstractHandler {&lt;br /&gt;
    private AddressBook _addressBook = null;&lt;br /&gt;
&lt;br /&gt;
    public AddressBookHandler(AddressBook aAddressBook) {&lt;br /&gt;
        _addressBook = aAddressBook;&lt;br /&gt;
    }&lt;br /&gt;
    public void handle(String aTarget, HttpServletRequest aRequest,&lt;br /&gt;
            HttpServletResponse aResponse, int aDispatchMode)&lt;br /&gt;
            throws IOException, ServletException {&lt;br /&gt;
&lt;br /&gt;
        ((Request) aRequest).setHandled(true);&lt;br /&gt;
        aRequest.setCharacterEncoding(“utf-8”);&lt;br /&gt;
        aResponse.setCharacterEncoding(“utf-8”);&lt;br /&gt;
        aResponse.addHeader(“Content-type”, “text/html; charset=utf-8”);&lt;br /&gt;
        PrintWriter writer = aResponse.getWriter();&lt;br /&gt;
        writer.write(“&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;” +&lt;br /&gt;
            “&amp;lt;title&amp;gt;Адресная книга&amp;lt;/title&amp;gt;” +&lt;br /&gt;
            “&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Адресная книга&amp;lt;/h1&amp;gt;”);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Откомпилируйте полученный код:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/Programming/AddressBook/src&lt;br /&gt;
javac –encoding utf-8 -cp ../libs/jetty-6.1.0rc3.jar:../libs/jetty-util-6.1.0rc3.&lt;br /&gt;
jar:../libs/servlet-api-2.5.jar -d ../build *.java&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И запустите (не забыв подключить все требуемые библиотеки):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/Programming/AddressBook/build&lt;br /&gt;
java -cp ../libs/jetty-6.1.0rc3.jar:../libs/jetty-util-6.1.0rc3.jar:../libs/servletapi-&lt;br /&gt;
2.5.jar:. AddressBook&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Терминал выводит несколько строчек и «зависает». Все правильно, сервер запустился. Запускать наше приложение будем пока именно так, чтобы его можно было легко выключить ('''Ctrl+C'''). Теперь откройте браузер и наберите в адресной строке: '''&amp;lt;nowiki&amp;gt;http://localhost:8081&amp;lt;/nowiki&amp;gt;'''. Вот он, наш заголовок!&lt;br /&gt;
&lt;br /&gt;
Вернемся к обработчику и попробуем уяснить, как различать запросы пользователей. Для этого в обработчике есть две возможности. Самая простая – посмотреть на первый параметр ('''aTarget'''), который содержит «файл» запроса (например в URL’е «http://www.linuxformat.ru/index.html» '''aTarget''' будет «'''/index.html'''»); посложнее – анализировать сам объект запроса. Воспользуемся первым вариантом, дописав в конец метода '''handle''' (прямо перед закрывающей скобкой) следующее:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 6.''' Более сложный обработчик с разбором адреса&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (“/”.equals(aTarget)) {&lt;br /&gt;
    writer.write(“&amp;lt;a href=\”/add\”&amp;gt;Добавить запись&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;”);&lt;br /&gt;
    writer.write(“&amp;lt;a href=\”/view\”&amp;gt;Просмотреть записи&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;”);&lt;br /&gt;
} else {&lt;br /&gt;
    writer.write(“&amp;lt;a href=\”/\”&amp;gt;На главную&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;”);&lt;br /&gt;
&lt;br /&gt;
    if (“/add”.equals(aTarget)) {&lt;br /&gt;
        writer.write(“&amp;lt;h2&amp;gt;Добавление записи&amp;lt;/h2&amp;gt;”);&lt;br /&gt;
    } else if (“/view”.equals(aTarget)) {&lt;br /&gt;
        writer.write(“&amp;lt;h2&amp;gt;Просмотр записей&amp;lt;/h2&amp;gt;”);&lt;br /&gt;
    } else if (“/edit”.equals(aTarget)) {&lt;br /&gt;
        writer.write(“&amp;lt;h2&amp;gt;Редактирование записи&amp;lt;/h2&amp;gt;”);&lt;br /&gt;
    } else if (“/remove”.equals(aTarget)) {&lt;br /&gt;
        writer.write(“&amp;lt;h2&amp;gt;Удаление записи&amp;lt;/h2&amp;gt;”);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
writer.write(“&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;”);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Попробуйте снова откомпилировать и запустить приложение, предварительно остановив предыдущую версию сервера. Обновите страницу в браузере – и побегайте по только что созданным страницам нашего сайта (корневая, она же «'''/'''», «'''/add'''», «'''/edit'''», «'''/remove'''»).&lt;br /&gt;
&lt;br /&gt;
Теперь в соответствующих ветках '''if''' можно написать обработчики страничек. Для упрощения вынесем эти обработчики в отдельные методы ('''листинг 7'''):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 7.''' Добавляем обработчики отдельных действий&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
    if (“/add”.equals(aTarget)) {&lt;br /&gt;
        writer.write(“&amp;lt;h2&amp;gt;Добавление записи&amp;lt;/h2&amp;gt;”);&lt;br /&gt;
        handleAdd(aRequest, writer);&lt;br /&gt;
    } else if (“/view”.equals(aTarget)) {&lt;br /&gt;
        writer.write(“&amp;lt;h2&amp;gt;Просмотр записей&amp;lt;/h2&amp;gt;”);&lt;br /&gt;
        handleView(writer);&lt;br /&gt;
    } else if (“/edit”.equals(aTarget)) {&lt;br /&gt;
        writer.write(“&amp;lt;h2&amp;gt;Редактирование записи&amp;lt;/h2&amp;gt;”);&lt;br /&gt;
        handleEdit(aRequest, writer);&lt;br /&gt;
    } else if (“/remove”.equals(aTarget)) {&lt;br /&gt;
        writer.write(“&amp;lt;h2&amp;gt;Удаление записи&amp;lt;/h2&amp;gt;”);&lt;br /&gt;
        handleRemove(aRequest, writer);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Осталось понять, как именно обрабатывать соответствующие страницы. Рассмотрим, для примера, метод '''handleAdd()''' – остальные можно написать по аналогии:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 8.''' Обработчик добавления записи&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
    private void handleAdd(HttpServletRequest aRequest, PrintWriter aWriter)&lt;br /&gt;
    throws IOException {&lt;br /&gt;
        if (aRequest.getParameter(“name”) != null) {&lt;br /&gt;
            _addressBook.addContact(aRequest.getParameter(“name”),&lt;br /&gt;
                aRequest.getParameter(“number”), aRequest.getParameter(“comment”));&lt;br /&gt;
            outputMessage(aWriter, “Контакт добавлен”);&lt;br /&gt;
        }&lt;br /&gt;
        outputForm(aWriter, aRequest, “”, “”, “”);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В приведенном обработчике есть вызов метода '''aRequest.getParameter(“name”)'''. Этот метод выдает значение параметра, который передает браузер из формы ('''&amp;lt;input type=”text” name=”name”/&amp;gt;'''). Причем сервлету все равно, каким методом (GET/POST) был передан параметр. Конкретно для обработки добавления контакта в коде проверяется, равен ли результат вызова '''null'''. Если так – значит, форма «не выполнялась», и добавлять нечего. В противном случае мы считываем три параметра (имя, телефон и комментарий), сохраняем контакт и выводим форму (вдруг пользователь захочет добавить еще один контакт?).&lt;br /&gt;
&lt;br /&gt;
Методы '''outputForm''' и '''outputMessage''' ('''листинг 9''') выводят форму (либо пустую, либо заполненную данными, которые нужно редактировать) и сообщение (чтобы пользователь понимал, что действие произошло, и как оно завершилось):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Листинг 9.''' Обработчик добавления записи&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
private void outputForm(PrintWriter aWriter, HttpServletRequest aRequest,&lt;br /&gt;
        String aName, String aNumber, String aComment) {&lt;br /&gt;
    aWriter.write(&lt;br /&gt;
        “&amp;lt;form action=\”/edit\” method=\”post\”&amp;gt;” +&lt;br /&gt;
        “&amp;lt;input type=\”hidden\” name=\”edited\” value=\”” +&lt;br /&gt;
            aRequest.getParameter(“number”) + “\”/&amp;gt;” + “&amp;lt;table&amp;gt;” +&lt;br /&gt;
        “&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Имя: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=\”text\” name=\”name\” value=\”” +&lt;br /&gt;
            aName + “\”/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;” +&lt;br /&gt;
        “&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Телефон: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=\”text\” name=\”number\” value=\”” +&lt;br /&gt;
            aNumber + “\”/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;” +&lt;br /&gt;
        “&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Примечания: &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=\”text\” name=\ ”comment\” value=\”” +&lt;br /&gt;
            aComment + “\”/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;” +&lt;br /&gt;
        “&amp;lt;tr&amp;gt;&amp;lt;td colspan=\”2\” align=\”center\”&amp;gt;” +&lt;br /&gt;
            “&amp;lt;input type=\”submit\” name=\”Отправить\”/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;” +&lt;br /&gt;
        “&amp;lt;/table&amp;gt;&amp;lt;/form&amp;gt;”);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private void outputMessage(PrintWriter aWriter, String aMessage) {&lt;br /&gt;
        aWriter.write(“&amp;lt;span style=\”color: green;\”&amp;gt;” + aMessage + “&amp;lt;/span&amp;gt;”);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы проверить работу нового обработчика, закомментируйте вызовы методов, которые еще не написаны (или напишите «заглушки» в виде пустых методов). Теперь можно снова остановить сервер, скомпилировать программу и запустить ее на выполнение. Если все набрано правильно, ошибок не последует, и можно будет просматривать табличку с контактами, добавлять их, редактировать и удалять. Наша адресная книга готова к работе!&lt;br /&gt;
&lt;br /&gt;
На этом уроке вы создали свое первое JEE-приложение. Конечно, за кадром осталось множество возможностей – начиная с использования сессий, контроля корректности параметров, и заканчивая отделением дизайна от логики работы сервлета – но наша программа уже вполне работоспособна. И, конечно, история не заканчивается. В следующих статьях будет продолжение, посвященное развитию приложения в соответствии с усложнением запросов компании к адресной книге.&lt;/div&gt;</summary>
		<author><name>Interlace</name></author>	</entry>

	</feed>