Тарифы мобильных компаний

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

· Name – название тарифа.

· Operator name – название сотового оператора, которому принадлежит тариф.

· Payroll – абонентская плата в месяц (0 – n рублей).

· Сall prices (должно быть несколько) – цены на звонки: внутри сети
(0 – n рублей в минуту), вне сети (0 – n рублей в минуту), на стационарные телефоны (0 – n рублей в минуту).

· SMS price – цена за смс (0 – n рублей).

· Parameters (должно быть несколько) – наличие любимого номера
(0 – n), тарификация (12-секундная, минутная), плата за подключение
к тарифу (0 – n рублей).

Корневой элемент назвать Tariff.

Создать XML файл, отображающий заданную тему, привести примеры 4-5 тарифов. С помощью XSL преобразовать данный файл в формат НTML, при выводе отсортировать тарифы по абонентской плате.

Лекарственные препараты.

Лекарственные препараты имеют следующие характеристики.

· Name – название препарата.

· Price – цена за упаковку (0 – n рублей).

· Dosage – дозировка препарата (мг/день).

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

Корневой элемент назвать Medicine.

Создать XML файл, отображающий заданную тему, привести примеры 4-5 лекарств. С помощью XSL преобразовать данный файл в формат НTML , при выводе отсортировать лекарства по цене.

Компьютер.

Компьютерные комплектующие имеют следующие характеристики:

· Name – название комплектующего.

· Origin – страна производства.

· Price – цена (0 – n рублей).

· Type (должно быть несколько) – периферийное либо нет, энергопотребление (ватт), наличие кулера (есть либо нет), группа комплектующих (устройства ввода-вывода, мультимедийные), порты (COM, USB, LPT).

· Critical – критично ли наличие комплектующего для работы компьютера.

Корневой элемент назвать Device.

Создать XML файл, отображающий заданную тему, привести примеры 4-5 устройств. С помощью XSL преобразовать данный файл в формат XML, при выводе корневым элементом сделать Critical.

Огнестрельное оружие.

Огнестрельное оружие можно структурировать по следующей схеме:

· Model – название модели.

· Handy – одно- или двуручное.

· Origin – страна производства.

· TTC (должно быть несколько) – тактико-технические характеристики: дальнобойность (близкая [0 – 500м], средняя [500 – 1000 м], дальняя [1000 – n метров]), прицельная дальность (в метрах), наличие обоймы, наличие оптики.

· Material – материал изготовления.

Корневой элемент назвать Gun.

Создать XML файл, отображающий заданную тему, привести примеры 4-5 видов. С помощью XSL преобразовать данный файл в формат XML, при выводе корневым элементом сделать страну производства.

Холодное оружие.

Холодное оружие можно структурировать по следующей схеме:

· Type – тип (нож, кинжал, сабля и т.д.).

· Handy – одно или двуручное.

· Origin – страна производства.

· Visual (должно быть несколько) – визуальные характеристики: клинок (длина клинка [10 – n см], ширина клинка [10 – n мм]), материал (клинок [сталь, чугун, медь и т.д.]), рукоять (деревянная [если да, то указать тип дерева], пластик, металл), наличие кровостока (есть либо нет).

· Value – коллекционный либо нет.

Корневой элемент назвать Knife.

Создать XML файл, отображающий заданную тему, привести при­меры 4-5 видов. С помощью XSL преобразовать данный файл в формат HTML, при выводе отсортировать по длине клинка.

Военные самолеты.

Военные самолеты можно описать по следующей схеме:

· Model – название модели.

· Origin – страна производства.

· Chars (должно быть несколько) – характеристики, могут быть следующими: тип (самолет поддержки, сопровождения, истребитель, перехватчик, разведчик), кол-во мест (1 либо 2), боекомплект (есть либо нет [разведчик], если есть, то: ракеты [0 – 10]), наличие радара.

· Parameters – длина (в метрах), ширина (в метрах), высота (в метрах).

· Price – цена (в долларах).

Корневой элемент назвать Plane.

Создать XML файл, отображающий заданную тему, привести примеры 4-5 типов самолетов. С помощью XSL преобразовать данный файл в формат HTML, при выводе отсортировать по стоимости.

Конфеты.

· Name – название конфеты.

· Energy– калорийность (ккал).

· Type (должно быть несколько) – тип конфеты (карамель, ирис, шоколадная [с начинкой либо нет]).

· Ingredients (должно быть несколько) – ингредиенты: вода, сахар (в мг), фруктоза (в мг), тип шоколада (для шоколадных), ванилин (в мг)

· Value – пищевая ценность: белки (в гр.), жиры (в гр.) и углеводы (в гр.).

· Production – предприятие-изготовитель.

Корневой элемент назвать Candy.

Создать XML файл, отображающий заданную тему, привести примеры 4-5 конфет. С помощью XSL преобразовать данный файл в формат HTML, при выводе отсортировать по месту изготовления.

Пиво.

· Name – название пива.

· Type – тип пива (темное, светлое, лагерное, живое).

· Al – алкогольное либо нет.

· Manufacturer – фирма-производитель.

· Ingredients (должно быть несколько) – ингредиенты: вода, солод, хмель, сахар и т.д.

· Chars (должно быть несколько) – характеристики: кол-во оборотов (если алкогольное), прозрачность (в процентах), фильтрованное либо нет, пищевая ценность (ккал), способ разлива (объем и материал емкостей)

· Корневой элемент назвать Beer.

Создать XML-файл, отображающий заданную тему, привести примеры 4-5 сортов пива. С помощью XSL преобразовать данный файл в формат XML, при выводе корневым элементом сделать производителя.

Периодические издания.

· Title – название издания.

· Type – тип издания (газета, журнал, буклет).

· Monthly – ежемесячное либо нет.

· Chars (должно быть несколько) – характеристики: цветное (да либо нет), объем (n страниц), глянцевое (да [только для журналов и буклетов] либо нет [для газет]), имеет подписной индекс (только для газет и журналов).

Корневой элемент назвать Paper.

Создать XML файл, отображающий заданную тему, привести примеры 4-5 типов периодики. С помощью XSL преобразовать данный файл в формат XML, при выводе корневым элементом сделать тип (Type).

Интернет-страницы.

· Title – название страницы.

· Type – тип страницы (рекламный, страница новостей, портал, зеркало).

· Chars (должно быть несколько) – наличие электронного ящика (толь­ко для порталов, зеркал и страниц новостей), наличие новостей (только для страниц новостей), наличие архивов для выкачивания (только для зеркал), наличие голосования (есть[если есть, то анонимное либо с применением авторизации] либо нет), платный (информация, до-
ступная для выкачивания, бесплатна либо нет).

· Authorize – необходима либо нет авторизация.

Корневой элемент назвать Site.

Создать XML файл, отображающий заданную тему, привести примеры 4-5 типов периодики. С помощью XSL преобразовать данный файл в формат XML, при выводе корневым элементом сделать тип (Type).

Тестовые задания к главе 16

Вопрос 16.1.

Какой существует способ описания данных в XML? (выберите два)

1. XML использует DTD для описания данных

2. XML использует XSL для описания данных

3. XML использует XSD для описания данных

4. XML использует CSS для описания данных

Вопрос 16.2.

В каких строках XML документа есть ошибки? (выберите два)

1 <?xml version="1.0"?>

2 <folder>

3 <file><name><contents></contents></name></file>

4 <file><name/><contents></contents><name/></file>

5 <file><name/><contents></contents></name></file>

6 <file><name><contents/><name/></file>

7 </folder>

 

1. 1;

2. 2;

3. 3;

4. 4;

5. 5;

6. 6;

7. 7;

8. нет ошибок.

Вопрос 16.3.

Какое из данных имен не является корректным именем для XML элемента? (выберите 2)

1. <hello_dolly>;

2. <big bang>;

3. <xmldocument>;

4. <7up>;

5. только одно имя некорректно.

Вопрос 16.4.

Значения атрибутов XML всегда должны помещаться в …? (выберите два)

1. двойные кавычки “ ”;

2. апострофы ‘ ‘;

3. фигурные скобки { };

4. квадратные скобки [];

5. могут обходиться без ограничивающих символов.

Вопрос 16.5.

Какие виды событий нельзя обрабатывать с помощью SAX-анализатора?

1. события документа;

2. события загрузки DTD-описаний;

3. события при анализе DTD-описаний;

4. ошибки;

5. все перечисленные события можно обработать.

 


Часть 3.
ТЕХНОЛОГИИ РАЗРАБОТКИ
WEB-ПРИЛОЖЕНИЙ

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

Глава 17

ВВЕДЕНИЕ В СЕРВЛЕТЫ И JSP

Согласно заявлению Sun Microsystems, на настоящий момент более 90% корпоративных систем поддерживают платформу Java Enterprise Edition.

Первый сервлет

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

Все сервлеты реализуют общий интерфейс Servlet из пакета javax.servlet. Для обработки HTTP-запросов можно воспользоваться
в качестве базового класса абстрактным классом HttpServlet из пакета javax.servlet.http.

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

Первым вызывается метод init(). Он дает сервлету возможность инициализировать данные и подготовиться для обработки запросов. Чаще всего в этом методе программист помещает код, кэширующий данные фазы инициализации.

После этого сервлет можно считать запущенным, он находится в ожидании запросов от клиентов. Появившийся запрос обслуживается методом
service(HttpServletRequest req, HttpServletResponse res) сервлета, а все параметры запроса упаковываются в объект req класса HttpServletRequest, передаваемый в сервлет. Еще одним параметром этого метода является объект res класса HttpServletResponse, в который загружается информация для передачи клиенту. Для каждого нового клиента при обращении к сервлету создается независимый поток, в котором производится вызов метода service(). Метод service() предназначен для одновременной обработки множества запросов.

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

При разработке сервлетов в качестве базового класса в большинстве случаев используется не интерфейс Servlet, а классHttpServlet, отвечающий за обработку запросов HTTP. Этот класс уже имеет реализованный метод
service().

Метод service() класса HttpServlet служит диспетчером для других методов, каждый из которых обрабатывает методы доступа к ресурсам. В спецификации HTTP определены следующие методы: GET, HEAD, POST, PUT, DELETE, OPTIONS и TRACE. Наиболее часто употребляются методы GET и POST, с помощью которых на сервер передаются запросы, а также параметры для их выполнения.

При использовании метода GET (по умолчанию) параметры передаются как часть URL, значения могут выбираться из полей формы или передаваться непосредственно через URL. При этом запросы кэшируются и имеют ограничения на размер. При использовании метода POST (method=POST) параметры (поля формы) передаются в содержимом HTTP-запроса и упакованы согласно полю заголовка Content-Type.

По умолчанию в формате:

<имя>=<значение>&<имя>=<значение>&...

Однако форматы упаковки параметров могут быть самые разные, например в случае передачи файлов с использованием формы

enctype="multipart/form-data".

В задачу метода service() класса HttpServlet входит анализ полученного через запрос метода доступа к ресурсам и вызов метода, имя которого сходно с названием метода доступа к ресурсам, но перед именем добавляется префикс do: doGet() или doPost(). Кроме этих методов, могут использоваться методы doHead(), doPut(), doDelete(), doOptions() и doTrace(). Разработчик должен переопределить нужный метод, разместив в нем функциональную логику.

В следующем примере приведен готовый к выполнению шаблон сервлета:

// пример # 1 : простейший сервлет : MyServlet.java

packagechapt17;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class MyServlet extends HttpServlet {

public MyServlet() {

super();

}

public void init() throws ServletException {

}

protected void doGet(

HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.print("This is ");

out.print(this.getClass().getName());

out.print(", using the GET method");

}

protected void doPost(

HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.print("This is ");

out.print(this.getClass().getName());

out.print(", using the POST method");

}

public void destroy() {

super.destroy(); // Just puts "destroy" string in log

}

}

Практика включения HTML-кода в код сервлета не считается хорошей, так как эти действия “уводят” сервлет от его основной роли – контроллера приложения. Это приводит к разрастанию размеров сервлета, которое на определенном этапе становится неконтролируемым и реализует вследствие этого анти-шаблон “Волшебный сервлет”. Даже приведенный выше маленький сервлет имеет признаки анти-шаблона, так как содержит метод print(), используемый для формирования кода HTML. Сервлет должен использоваться только для реализации бизнес-логики приложения и обязан быть отделен как от непосредственного формирования ответа на запрос, так и от данных, необходимых для этого. Обычно для формирования ответа на запрос применяются возможности JSP, JSPX или JSF. Признаки наличия анти-шаблонов все же будут встречаться ниже, но это отступление сделано только с точки зрения компактности примеров.

Сервлет является компонентом Web-приложения, который будет называться FirstProject и размещен в папке /WEB-INF/сlasses проекта.

Запуск контейнера сервлетов и размещение проекта

Здесь и далее применяется контейнер сервлетов Apache Tomcat в качестве обработчика страниц JSP и сервлетов. Последняя версия может быть загружена
с сайта jakarta.apache.org.

При установке Tomcat предложит значение порта по умолчанию 8080, но во избежание конфликтов с иными Application Server рекомендуется присвоить другое значение, например 8082.

Ниже приведены необходимые действия по запуску сервлета из предыдущего примера с помощью контейнера сервлетов Tomcat 5.5.20, который установлен в каталоге /Apache Software Foundation/Tomcat5.5. В этом же каталоге размещаются следующие подкаталоги:

/bin – содержит файлы запуска контейнера сервлетов tomcat5.exe,
tomcat5w.exe и некоторые необходимые для этого библиотеки;

/common– содержит библиотеки служебных классов, в частности Servlet API;

/conf – содержит конфигурационные файлы, в частности конфигурационный файл контейнера сервлетов server.xml;

/logs – помещаются log-файлы;

/webapps – в этот каталог помещаются папки, содержащие сервлеты и другие компоненты приложения.

В каталог /webapps необходимо поместить папку /FirstProjectс вложенным в нее сервлетом MyServlet. Кроме того, папка /FirstProject должна содержать каталог /WEB-INF, в котором помещаются подкаталоги:

/classes – содержит класс сервлета chapt17.MyServlet.class;

/lib – содержит используемые внешние библиотеки (если они есть), упакованные в JAR-файлы (архивы java);

/src – содержит исходный файл сервлета MyServlet.java(опционально);

а также web.xml – дескриптор доставки приложения располагается в каталоге /WEB-INF.

В файле web.xml необходимо прописать имя и путь к сервлету. Кроме того, в дескрипторном файле можно определять параметры инициализации, MIME-типы, mapping сервлетов и JSP, стартовые страницы и страницы с сообщениями об ошибках, а также параметры для безопасной авторизации и аутентификации. Этот файл можно сконфигурировать так, что имя сервлета в браузере не будет совпадать с истинным именем сервлета. Например:

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>FirstProject</display-name>

<servlet>

<display-name>MyServletdisplay</display-name>

<servlet-name>MyServletname</servlet-name>

<servlet-class>chapt17.MyServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>MyServletname</servlet-name>

<url-pattern>/MyServlettest</url-pattern>

</servlet-mapping>

<session-config>

<session-timeout>30</session-timeout>

</session-config>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

<login-config>

<auth-method>BASIC</auth-method>

</login-config>

</web-app>

Здесь указано имя сервлета MyServletname, путь к откомпилированному классу сервлета MyServlet.class, а также URL-имя сервлета, по которому происходит его вызов MyServlettest.

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

1. Компиляцию сервлета с указанием в –cp пути к архиву

2. servlet-api.jar;

3. Полученный файл класса MyServlet.class поместить в папку /FirstProject/WEB-INF/classes/chapt18;

4. В папку /MyProject/WEB-INF поместить файл конфигурации web.xml;

5. Переместить папку /FirstProject в каталог /webappsконтейнера сервлетов Tomcat;

6. Стартовать Tomcat;

7. Запустить браузер и ввести адрес:

http://localhost:8082/FirstProject/MyServlettest

При обращении к сервлету из другого компьютера вместоlocalhost следует указать IP-адрес или имя компьютера.

8. Если вызывать сервлет из index.jsp, то тег FORM должен выглядеть следующим образом:

<FORM action="MyServlettest">

<INPUT type="submit" value="Execute">

</FORM>

Файл index.jsp помещается в папку /webapps/FirstProject
и в браузере набирается строка:

http://localhost:8082/FirstProject/index.jsp

Сервлет будет вызван из JSP-страницы по URL-имени MyServlettest,
и в результате в браузер будет выведено:

Рис. 17.1. Вывод сервлета после вызова метода doGet()

Первая JSP

Java Server Pages (JSP) обеспечивает разделение динамической и статической частей страницы, результатом чего является возможность изменения дизайна страницы, не затрагивая динамическое содержание. Это свойство используется при разработке и поддержке страниц, так как дизайнерам нет необходимости знать, как работать с динамическими данными.

Процессы, выполняемые с файлом JSP при первом вызове:

d) Браузер делает запрос к странице JSP.

e) JSP-engine анализирует содержание файла JSP.

d) JSP-engine создает временный сервлет с кодом, основанным на исходном тексте файла JSP, при этом контейнер транслирует операторы Java в метод _jspService(). Если нет ошибок компиляции, то этот метод вызывается для непосредственной обработки запроса. Полученный сервлет ответствен за исполнение статических элементов JSP, определенных во время разработки в дополнение к созданию динамических элементов.

e) Полученный код компилируется в файл*.class.

f) Вызываются методы init() и _jspService(), и сервлет логически исполняется.

d) Сервлет на основе JSP установлен. Комбинация статического HTML
и графики вместе с динамическими элементами, определенными в оригинале JSP, пересылаются браузеру через выходной поток объекта ответа ServletResponse.

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

Рис. 17.2. Рабочий цикл JSP

Если рассмотреть преобразование в сервлет простейшей JSP, отправляющей
в браузер приветствие:

<!--пример # 2 : простейшая страница JSP : simple.jsp -->

<html><head>

<title>Simple</title>

</head>

<body>

<jsp:text>Hello, Bender</jsp:text>

</body></html>

то в результате запуска в браузер будет выведено:

Рис. 17.3. Вывод после вызова index.jsp

А код сервлета будет получен следующий:

// пример # 3 : сгенерированный сервлет : simple_jsp.java

package org.apache.jsp;

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

 

public final class simple_jsp

extends org.apache.jasper.runtime.HttpJspBase

implements org.apache.jasper.runtime.JspSourceDependent{

private static java.util.List _jspx_dependants;

 

public Object getDependants() {

return _jspx_dependants;

}

public void _jspService(HttpServletRequest request,

HttpServletResponse response)

throws java.io.IOException, ServletException {

 

JspFactory _jspxFactory = null;

PageContext pageContext = null;

HttpSession session = null;

ServletContext application = null;

ServletConfig config = null;

JspWriter out = null;

Object page = this;

JspWriter _jspx_out = null;

PageContext _jspx_page_context = null;

try {

_jspxFactory = JspFactory.getDefaultFactory();

response.setContentType("text/html");

pageContext = _jspxFactory.getPageContext(this,

request, response, null, true, 8192, true);

_jspx_page_context = pageContext;

application = pageContext.getServletContext();

config = pageContext.getServletConfig();

session = pageContext.getSession();

out = pageContext.getOut();

_jspx_out = out;

 

out.write("<html><head>\r\n");

out.write("<title>Simple</title>\r\n");

out.write("</head>\r\n");

out.write("<body>\r\n");

out.write("Hello, Bender\r\n");

out.write("</body></html>");

} catch (Throwable t) {

if (!(t instanceof SkipPageException)){

out = _jspx_out;

if (out != null && out.getBufferSize() != 0)

out.clearBuffer();

if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);

}

} finally {

if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);

}

}

}

JSP-код заключается в специальные теги, которые указывают контейнеру, чтобы он использовал этот код для генерации сервлета или его части. Таким образом поддерживается документ, который одновременно содержит и статическую страницу, и теги Java, которые управляют этой страницей. Статические части HTML-страниц посылаются в виде строк в метод write(). Динамические части включаются прямо в код сервлета. С этого момента страница ведет себя как обычная HTML-страница с ассоциированным сервлетом.

Взаимодействие сервлета и JSP

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

Ниже приведен пример вызова сервлета из JSP с последующим вызовом другой JSP.

<!--пример # 4 : страница JSP с вызовом сервлета : index.jsp -->

<%@ page language="java" contentType="text/html; charset=ISO-8859-5" pageEncoding="ISO-8859-5"%>

<html><body>

<jsp:useBean id="gc" class="java.util.GregorianCalendar"/>

<jsp:getProperty name="gc" property="time"/>

<FORM action="serv" method="POST">

<INPUT type="submit" value="Вызвать сервлет">

</FORM>

</body></html>

В результате запуска проекта в браузер будет выведено:

Рис. 17.4. Запуск index.jsp

Кодировка для символов кириллицы задана с помощью директивы page. Аction-теги useBean и getProperty используются для создания объекта класса GregorianCalendar в области видимости JSP и вывода его значения. Сервлет ContServlet вызывается методом POST.

// пример # 5 : простой контроллер : СontServlet.java

package chapt17;

import java.io.IOException;

import java.util.Calendar;

import java.util.Locale;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class ContServlet

extends javax.servlet.http.HttpServlet {

 

protected void doPost(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

//добавление атрибута к запросу

request.setAttribute("loc", Locale.getDefault());

//добавление атрибута к сессии

request.getSession().setAttribute("calend",

Calendar.getInstance());

//получение объекта RequestDispatcher и вызов JSP

request.getRequestDispatcher("/main.jsp").forward(request,

Response);

}

}

Передачу информации между JSP и сервлетом можно осуществлять, в частности, с помощью добавления атрибутов к объектам HttpServletRequest, HttpSession, HttpServletContext. Вызов main.jsp из сервлета
в данном случае производится методом forward() интерфейса RequestDispatcher.

<!--пример # 6 : страница, вызванная сервлетом : main.jsp -->

<%@ page language="java"

contentType="text/html; charset=utf-8"

pageEncoding="utf-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core"

prefix="c"%>

<html><body>

<h3>Региональные установки и Время</h3>

<c:out value="Locale from request: ${loc}"/><br>

<c:out value="Time from Servlet: ${calend.time}"/>

</body></html>

После вызова сервлета и последующего вызова main.jsp будет выведено:

Рис. 17.5. Вывод информации страницей main.jsp

В данном коде директива taglib подключает JSP Standard Tag Library (JSTL), и становится возможным вызов тега <c:out>, а также использование Expression Language (EL) в виде ${loc}.

Конфигурационный файл web.xml для данной задачи должен содержать следующую информацию:

<servlet>

<display-name>Controller</display-name>

<servlet-name>controller</servlet-name>

<servlet-class>chapt17.ContServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>controller</servlet-name>

<url-pattern>/serv</url-pattern>

</servlet-mapping>

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

Задания к главе 17

Вариант А

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

8. Подсчет суммы случайным образом выбранных элементов массива.

9. Вывести полное название страны и языка.

10. Подсчитать время между выполнением сервлета и JSP в наносекундах.

11. Создать массив дат и вывести самую позднюю дату.

12. Задать температуру. Если она меньше нуля, вывести значение температуры синим цветом, если больше, то красным.

13. Создать приложение, выводящее фамилию разработчика, дату и время получения задания, а также дату и время его выполнения.

Вариант B

Задания варианта В главы 1 выполнить на основе сервлетов. Число n генерировать с помощью методов класса java.util.Random.

Тестовые задания к главе 17

Вопрос 17.1.

Укажите стандартный путь к сервлету сом.example.MyServlet, чтобы Web-приложение могло к нему обратиться.

1) /lib/MyServlet.class

2) /com/example/MyServlet.class

3) /WEB-INF/lib/MyServlet.class

4) classes/com/example/MyServlet.class

5) /servlets/com/example/MyServlet.сlass

6) /WEB-INF/classes/com/example/MyServlet.class

Вопрос 17.2.

Дано:

public void service(ServletRequest request,

ServletResponse response) {

ServletInputStream sis =

//1

}

Какой код инициализирует ссылку на байтовый поток в строке 1?

1) request.getWriter();

2) request.getReader();

3) request.getInputStream();

4) request.getResourceAsStream();

5) request.getResourceAsStream(ServletRequest. REQUEST);

Вопрос 17.3.

На странице JSP необходимо создать объект JavaBean для использования только на этой странице. Какие два атрибута jsp:useBean должны применяться для этого?

1) id

2) type

3) name

4) class

5) create

Вопрос 17.4.

Какой стиль комментариев используется в страницах JSP?

1) <!--this is a comment-->

2) <%// this is a comment %>

3) <%-- this is a comment --%>

4) <%/** this is a comment **/%>

Вопрос 17.5.

Определен метод doGet() интерфейса HttpServlet:

public void service(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

HttpSession s = request.getSession();

// insert code here

}

С помощью какого кода можно удалить атрибут из объекта сессии?

1) session.unbind("key");

2) session.remove("key");

3) session.removeAttribute("key");

4) session.unbindAttribute("key");

5) session.deleteAttribute("key");

Вопрос 17.6.

Какая из записей указывает правильное имя и расположение файла-дескриптора Web-приложения относительно его корневой директории?

1) /conf/web.xml

2) /WEB-INF/web.xml

3) /conf/server.xml

4) /META-INF/web.xml

5) /WEB-INF/rules.xml

6) /META-INF/server.xml

 

 
Глава 18

СЕРВЛЕТЫ

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

Преимуществом сервлетов перед CGI или ASP является быстродействие, переносимость на различные платформы, использование объектно-ориентированного языка высокого уровня Java, который расширяется большим числом классов и программных интерфейсов.

Сервлеты поддерживаются большинством Web-серверов и являются частью платформы J2EE. Сервлеты реализуют интерфейс Servlet, в котором, кроме рассмотренных выше методов service(), init(), destroy(), предусмотрена реализация еще двух методов:

ServletConfiggetServletConfig() – возвращает объект, содержащий параметры конфигурации сервлета;

StringgetServletInfo() – определение информации о назначении сервлета.

Интерфейс ServletContext

Интерфейс ServletContext объявляет методы, которые сервлет применяет для связи с контейнером сервлетов и позволяет получать информацию о среде выполнения, а также использовать ресурсы совместно с другими объектами приложения. Каждому сервлету ставится в соответствие единственный объект, реализующий ServletContext. Контекст выполнения сервлета дает средства для общения с сервером. В частности, можно получить информацию о MIME-типе файла, добавить/удалить атрибуты контекста или записать информацию в log-файл. Получить ссылку на объект ServletContext можно вызовом метода getServletContext().

Следующие методы позволяют получить из контекста сервлета базовую информацию:

String getMimeType(String filename) – определение MIME-типа файла или документа. По умолчанию MIME-типом для сервлетов является text/plain, но используется обычно text/html;

String getRealPath(String filename) – определение истинного маршрута файла относительно каталога, в котором сервер хранит документы;

String getServerInfo() – предоставляет информацию о самом сервере.

Ряд методов предназначен для управления атрибутами, с помощью которых передается информация между различными компонентами приложения (JSP, сервлетами):

Object getAttribute(String name) – получает значение атрибута по имени;

Enumeration getAttributeNames() – получает список имен атрибутов;

void setAttribute(String name, Object object) – добавляет атрибут и его значение в контекст;

void removeAttribute(String name) – удаляет атрибут из контекста;

ServletContext getContext(String uripath) – позволяет получить доступ к контексту других ресурсов данного контейнера сервлетов;

String getServletContextName()– возвращает имя сервлета, которому принадлежит данный объект интерфейса ServletContext.

Используя объект ServletContext, можно регистрировать события сервлета, сессии и запроса.

Интерфейс ServletConfig

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

Некоторые методы класса:

String getServletName() – определение имени сервлета;

Enumeration getInitParameterNames() – определение имен параметров инициализации сервлета из дескрипторного файда web.xml;

String getInitParameter(String name) – определение значения конкретного параметра по его имени.

Чтобы задать параметры инициализации сервлета MyServlet, необходимо в тег <servlet> его описания вложить тег <init-param> с описанием имени
и значения параметра в виде:

<servlet>

<servlet-name>MyServletname</servlet-name>

<servlet-class>chapt18.MyServlet</servlet-class>

<init-param>

<param-name>mail.smtphost</param-name>

<param-value>mail.bsu</param-value>

</init-param>

<init-param>

<param-name>mail.smtpport</param-name>

<param-value>25</param-value>

</init-param>

</servlet>

Тогда для доступа к параметрам инициализации сервлета и их дальнейшего использования можно применить следующую реализацию метода init() сервлета:

public void init() throws ServletException {

ServletConfig sc = getServletConfig();

 

// определение набора имен параметров инициализации

Enumeration e = sc.getInitParameterNames();

while(e.hasMoreElements()) {

// определение имени параметра инициализации

String name = (String)e.nextElement();

// определение значения параметра инициализации

String value = sc.getInitParameter(name);

//...

}

}

Такими же возможностями обладает и объект ServletContext, который содержит практически всю информацию о среде, в которой запущен и выполняется сервлет, например:

getServletContext().getInitParameter("mail.smtpport");

Интерфейсы ServletRequest и HttpServletRequest

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

String getCharacterEncoding() – определение символьной кодировки запроса;

String getContentType() – определение MIME-типа (Multipurpose Internet Mail Extension) пришедшего запроса;

String getProtocol() – определение названия и версии протокола;

String getServerName(), getServerPort() – определение имени сервера, принявшего запрос, и порта, на котором запрос был принят сервером соответственно;

String getRemoteAddr(), getRemoteHost() – определение IP-адреса клиента, от имени которого пришел запрос, и его имени соответственно;

String getRemoteUser() – определение имени пользователя, выполнившего запрос;

ServletInputStream getInputStream(), BufferedReader getReader() – получение ссылки на поток, ассоциированный с содержимым полученного запроса. Первый метод возвращает ссылку на байтовый поток ServletInputStream, а второй – на объект BufferedReader. В результате можно прочитать любой байт из полученного объекта-запроса. Если метод getReader() был вызван после вызова getInputStream() для этого запроса, то генерируется исключение IllegalStateException и наоборот.

При обращении к серверу, как правило, передаются параметры и их значения. Для разбора параметров и извлечения их значений применяются методы:

String getParameter(String name) – определение значения параметра по его имени или null, если параметр с таким именем не задан;

String[] getParameterValues(String name) – определение всех значений параметра по его имени;

Enumeration getParameterNames() – определение ссылки на список имен всех параметров через объект типа Enumeration.

Непосредственно в интерфейсе HttpServletRequest объявлен ряд методов, позволяющих манипулировать содержимым запросов:

void setAttribute(String name, Object ob) – установка значения атрибута компонента, являющегося внутренним параметром для передачи информации между компонентами приложения, например от сервлета к странице JSP или другому сервлету;

Enumeration getAttributeNames()– извлечение перечисления имен атрибутов;

Object getAttribute(String name)– извлечение значения переданного атрибута по имени;

Cookie[] getCookies() – извлечение массива cookie, полученного с запросом. Файл cookie – маленький файл, сохраняемый приложением на стороне клиента;

String getMethod() – определение имени метода доступа к ресурсам, на основе которого построен запрос;

String getQueryString() – извлечение строки HTTP-запроса.

В следующем примере рассматривается применение некоторых методов интерфейса HttpServletRequestдля получения данных о запросе, посылаемом методом GET и генерации ответа клиенту.

/* пример # 1 : извлечение информации из запроса и счетчик посещений : RequestServlet.java : RequestInfo.java : ClickOutput.java */

packagechapt18;

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.IOException;

import java.io.PrintWriter;

import java.io.UnsupportedEncodingException;

 

public class RequestServlet extends HttpServlet {

// счётчик подключений к сервлету

private int count = 0;

 

public void doGet(HttpServletRequest req,

HttpServletResponse resp)

throws ServletException {

performTask(req, resp);

}

public void doPost(HttpServletRequest req,

HttpServletResponse resp)

throws ServletException {

performTask(req, resp);

}

private void performTask(HttpServletRequest req,

HttpServletResponse resp)

throws ServletException {

try {

// установка MIME-типа содержания ответа

resp.setContentType("text/html; charset=Windows-1251");

 

// поток для данных ответа

PrintWriter out = resp.getWriter();

count = ClickOutput.printClick(out, count);

//обращение к классу бизнес-логики

if(count == 1)

RequestInfo.printToBrowser(out, req);

// закрытие потока

out.close();

} catch (UnsupportedEncodingException e) {

System.err.print("UnsupportedEncoding");

}catch (IOException e) {

System.err.print("IOErroR");

}

}

}

package chapt18;

import java.io.PrintWriter;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

 

public class RequestInfo {

static String br = "<br>";

 

public static void printToBrowser(

PrintWriter out, HttpServletRequest req) {

out.println("Method: " + req.getMethod());

out.print(br + "Request URI: " + req.getRequestURI());

out.print(br + "Protocol: " + req.getProtocol());

out.print(br + "PathInfo: " + req.getPathInfo());

out.print(br + "Remote Address: " + req.getRemoteAddr());

// извлечение имен заголовочной информации запроса

Enumeration e = req.getHeaderNames();

out.print(br + "Header INFO: ");

while (e.hasMoreElements()) {

String name = (String) e.nextElement();

String value = req.getHeader(name);

out.print(br + name + " = " + value);

}

}

}

package chapt18;

import java.io.PrintWriter;

 

public class ClickOutput {

public static int printClick(

PrintWriter out, int count) {

 

out.print(++count + " -е обращение." + "<br>");

return count;

}

}

Приведенный выше сервлет вызывается нажатием кнопки “Выполнить” формы из документа index.jsp по адресу URL – RequestServlet.

<!-- пример # 2 : стартовая страница вызова сервлета : index.jsp-->

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-5"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional //EN">

<html><head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-5">

<title>Info about Request </title>

</head><body>

<FORM action="RequestServlet" method="GET">

<INPUT type="submit" value="Выполнить">

</FORM>

</body></html>

В результате выполнения в браузер будет выведено:

Е обращение.

Method: GET

Request URI: /FirstProject/RequestServlet

Protocol: HTTP/1.1

PathInfo: null

Remote Address: 127.0.0.1

Header INFO:

accept = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
referer = http://localhost:8080/FirstProject/index.jsp
accept-language = ru
content-type = application/x-www-form-urlencoded
accept-encoding = gzip, deflate
user-agent = Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
host = localhost:8080
content-length = 0
connection = Keep-Alive
cache-control = no-cache
cookie = JSESSIONID=91014EB2B2208BCA18AE898424B71CEF

Сервлет RequestServletследует попробовать вызывать с различных компьютеров локальной сети или вызвать несколько раз сервлет из нескольких браузеров, запущенных на одном компьютере.

Когда клиент переходит по адресу URL, который обрабатывается сервлетом, контейнер сервлета перехватывает запрос и вызывает метод doGet() или doPost(). Эти методы вызываются после конфигурации объектов, наследующих интерфейсы HttpServletRequest, HttpServletResponse. Задача методов doGet() и doPost() – взаимодействие с HTTP-запросом клиента и создание HTTP-ответа, основанного на данных запроса. Метод getWriter() объекта-ответа возвращает поток PrintWriter, который используется для записи символьных данных ответа.

Интерфейсы ServletResponse и HttpServletResponse

Генерируемые сервлетами данные пересылаются серверу-контейнеру с помощью объектов, реализующих интерфейс ServletResponse, а сервер, в свою очередь, пересылает ответ клиенту, инициировавшему запрос.

Можно получить ссылки на потоки вывода одним из двух методов:

ServletOutputStream getOutputStream() – извлечение ссылки на поток ServletOutputStream для передачи бинарной информации;

PrintWriter getWriter() – извлечение ссылки на поток типа PrintWriter для передачи символьной информации;

Если метод getOutputStream() уже был вызван для этого ответа, то генерируется IllegalStateException. Обратное также верно.

В интерфейсе HttpServletResponse, наследующем интерфейс ServletResponse, есть еще несколько полезных методов:

void setContentType(String type) – установка MIME-типа генерируемых документов;

void addCookie(Cookie c) – добавление cookie к объекту ответа для последующей пересылки на клиентский компьютер;

void sendError(int sc, String msg) – сообщение о возникших ошибках, где sc – код ошибки, msg – текстовое сообщение;

void setDateHeader(String name, long date) – добавление даты в заголовок ответа;

void setHeader(String name, String value) – добавление параметров в заголовок ответа. Если параметр с таким именем уже существует, то он будет заменен.

Обработка запроса

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

Приведенная на рисунке 18.1 форма является результатом отображения JSP-страницы index.jsp, находящейся в папке /webapps/FirstProject3.

В форме имеется текстовое поле с именем name и значением по умолчанию «Название проекта». Значение поля можно изменить непосредственно на странице.

Рис. 18.1. JSP-форма

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

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

В форме задан метод POST, при помощи которого происходит передача данных формы в виде отдельных заголовков. Если не задавать этот метод, то по умолчанию будет использоваться метод GET, и данные формы будут передаваться через универсальный запрос (URL), в который к адресу будут добавлены значения соответствующих элементов.

<!-- пример # 3 : стартовая страница : index.jsp-->

<%@ page language="java" contentType=

"text/html; charset=utf-8" pageEncoding="utf-8"%>

<html><body>

<FORM action="testform" method=POST>

<H3>Название проекта:

<INPUT type="text" name="Имя проекта" value="-задать!-">

Технологии:

<TABLE BORDER=5> <tr>

<td>JSPX</td><td><INPUT type="radio"

name="Технология"

value="JSP в формате XML"></td>

<td>JSTL</td><td><INPUT type="radio"

name="Технология"

value="Библиотека тегов JSTL"></td>

</tr></TABLE>

Язык программирования:

<TABLE BORDER=5> <tr>

<td>Java 6<INPUT type="radio"

name="Язык"

value="Java SE 6"></td>

<td>Java 5<INPUT type="radio"

name="Язык"

value="Java 1.5.0" checked></td>

</tr></TABLE></H3>

<INPUT type="submit" value="Принять"> <BR>

</FORM>

</body></html>

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

/* пример # 4 : обработка запроса клиента : FormRequest.java :

ParameterOutput.java */

package chapt18;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class FormRequest extends HttpServlet {

protected void doPost(HttpServletRequest req,

HttpServletResponse resp)

throws ServletException {

performTask(req, resp);

}

private void performTask(HttpServletRequest req,

HttpServletResponse resp) {