Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:JAVA. Серверные приложения
.pdf
Часть 2 Java Server Page 101
10.4.1. Директива include <% @ include%>
JavaBean — это прекрасный, легко распространяемый Java-компо-
нент, но иногда импортировать в каждую JSP-страницу новый экземпляр bean не имеет смысла, а необходима часть кода, уже имеющегося
где-то на другой странице. Включение созданного ресурса простой и достаточно эффективный способ создания распространяемых компонентов. Отпадает необходимость переписывать десятки раз одну и ту же
строку, и при этом не «раздувается» каждый создаваемый файл. Главное, на что необходимо обратить внимание при использовании директивы, <%@ include%>, заключается в том, что ресурсы, импортированные
с помощью этой директивы транслируются в исполняемый servlet. Все
будет включено в тело программы. Единственный атрибут file директивы <%@include%> указывает непосредственно на ресурс, включаемый
в JSP-страницу. Значением атрибута служит строковое определение
пути url включаемого ресурса:
<%@ include file="/somewhere/Index.html" %>.
Директива <% @include %> служит для включения в исходный
код внешних статических данных, текста или JSP-кода. Ресурсом является любой объект, текст или изображение. Но для включения динамических элементов существуют другие пути, используемые в JSP.
При включении файла, содержащего только JSP-операторы, он
транслируется как часть основной страницы в момент обработки запроса. Если включаемый файл содержит текст, HTML-теги, JSP-директивы, теги и скриплеты или код программы, написанный на языке
Java, то необходимо проверить на возможность пересечения исполняемого и включаемого кода, т. е. на использование одноименных переменных с различными типами. Если содержимое ресурса, включенного директивой <%@include%
>, изменилось, страницу необходимо пе-
ретранслировать:
<%@ include file=".somewhere/filename.jsp"%>
При всей своей незамысловатости данная директива очень полезна,
поскольку позволяет без дублирования кода включать необходимые ресурсы в генерируемую страницу:
<% if (request.getParameter("user"){ %>
<%@include file= "/hello.jsp" %>
<%} else {%>
<%@include file="index.html"%>
<%}%>
Альтернативой данному подходу включения статических данных яв-
ляется использование других JSP-конструкций описанных в тегах
<jsp:include> и< jsp:forward>, о них будет сказано ниже. Использование тега <jsp:include> ни в коем разе не замещает использование директивы <%@include%>, это две совсем разные вещи, предназначенные
для разных целей. О JSP тегах буде сказано ниже.

102 Часть 2 Java Server Page
Количество указанных директив <%@include%> в JSP-странице не
имеет никакого значения, директив может быть несколько, в то же
время одна JSP-страница может состоять только из одной директивы
<%@ include%>.
10.4.2 Директива page <%@ page %>
Поскольку JSP после трансляции представляет из себя исполняемый
байт-код и в большинстве случаев, кроме основного пакета java.lang,
приложение содержит объекты классов, импортированных из других
пакетов, то в коде приложения используется оператор import, не считая
конкретных случаев использования полного имени в указании возвращаемых типов и классов объектов. Более детальную информацию об использовании оператора import можно почерпнуть из руководства по
языку Java. Для выполнения операций импортирования в JSP существует специальная директива page. Кроме операций импортирования
классов директива <%@ page%> выполняет и ряд других важных задач, таких, как указание наследуемых интерфейсов, а также часть служебной, но очень важной информации о выполнении созданной JSP.
Директива <%@page%
> указывает параметры обработки страницы
JSP-движком. Также она является директивой по управлению системным процессом для данной страницы. Директиву <%@ page %> можно
использовать неоднократно в одной странице, при этом необходимо соблюдать осторожность использования некоторых атрибутов. В частности, использование наследуемых классов должно быть единым для всей
страницы. Указывать директиву <% @page %> можно единовременно
со всеми значениями атрибутов или же для каждого используемого атрибута указывать собственную версию директивы <% @page %>:
<%@page language = "java" %>
<%@ page import = "java.util.*,java.io.*,java.util.Hashtable" %>
<%@ page contentType = "TEXT/HTML" %>.
Данный метод указания директивы полезен только для описания наглядности использования разнообразных атрибутов директивы в различных местах программы. На созданный servlet разнесенные директивы никак не повлияют. Код будет сгенерирован один. Важно еще раз
упомянуть об осторожном использовании атрибутов, атрибуты не должны иметь различные значения на одной исполняемой JSP-странице.
В строковом эквиваленте вышеуказанные операторы после ключевого слова page были бы перечислены последовательно:
<%@ page language="java" import="java.util.*" contentType="text/html" %>.
Какой способ более наглядно демонстрирует использование директивы, решать программисту.
Директива <% @page %> имеет ряд следующих атрибутов:
<%@ page
•
language="java"
•
extends=" package.class "
•
import=" package.class"

Часть 2 Java Server Page 103
session ="true|false"
•
buffer="none|8kb| sizekb"
•
autoFlush="true|false"
•
isThreadSafe="true|false"
•
info="text"
•
errorPage="URL/error.jsp"
•
contentType="mimeType[character=characterSet]" | "text|html; char-
•
set=ISO-8859-1"]
isErrorPage="true|false"%>.
•
Количество атрибутов достаточно большое, и все они играют важную
роль в исполнении JSP-страницы на сервере. Как и в обычном Java-приложении, желательно указывать директивы, содержащие импортированные пакеты до использования классов, содержащихся в этих пакетах.
В отличие от предыдущей директивы, месторасположение которой зависит только от логики программы, оптимальным расположением директивы <%@ page%> можно считать начало документа перед использованием
первого в JSP скриплета. Расположение директивы в начале связано в
первую очередь с удобством чтения исходного кода, во вторую — с некоторыми обязательными правилами использования атрибутов.
Атрибут language. Атрибут language определяет язык, на котором
•
написан встраиваемый текст (на настоящий момент это только Java, поэтому этот атрибут не является обязательным). Средство
разработки WebSphere Studio и WEBSphere Application Server
компании IBM позволяет указывать в данном атрибуте любой другой скриптовый язык программирования. По умолчанию параметр
language имеет значение Java.
•
Атрибуты extends, import. Два следующих атрибута являются стандартными конструкциями языка Java. Первый — extends — указывает имя родительского класса, от которого порожден данный класс,
в нашем случае JSP. Можно заметить отсутствие, казалось бы, немаловажной детали в атрибутах, а именно указание интерфейсов,
что считается вполне нормальным для обычных программ, однако
JSP уже наследует интерфейс servlet, со всеми вытекающими отсюда последствиями. Можно использовать только одно значение extends на странице JSP. Данное требование касается не только JSPстраниц, но и всех Java-приложений. Класс наследуется только от
одного родительского класса. Атрибут import предназначен для импортирования внешних классов, используемых в скриптовом окружении. Импортированных классов может быть несколько, как и пакетов, содержащих классы. Атрибут может содержать полное имя
как отдельного класса, так и всего пакета в целом. Указание звездочки в имени пакета (стандартное решение при создании компилируемых Java-программ) влияет только на время создания servlet, но
никак не влияет на производительность приложения в целом. Атрибут import должен быть помещен до использования импортированных классов. Действует только при наличии у атрибута languge параметра "Java". Если возникает необходимость импортирования
большого количества классов в разные файлы, то можно создать отдельный JSP-файл с директивой %@page%
, имеющий все необходи-

104 Часть 2 Java Server Page
мые классы, и затем воспользоваться директивой <%@ include %>,
включив JSP-файл, содержащий классы в рабочий файл. Обязательно учитывать различие при указании операторов импортирования, в JSP слово import является параметром объекта, а строковое
значение в кавычках его значением, поэтому нельзя указывать в
конце оператора точку с запятой, как это принято в Java, а при указании нескольких импортированных пакетов или классов они разделяются запятой или для каждого класса указывается собственный
оператор import. В JSP отсутствует надобность импортировать следующие пакеты:
java.lang.*;
javax.servlet.*;
javax.servlet.jsp.*:
javax.servlet.http.*:
Пакет java.lang. является стандартным, родовым пактом и не импортируется никогда, остальные пакеты предназначены для создания временного приложения на основе используемой JSP и описаны в следующей части, посвященной непосредственно servlet.
Атрибут session. Указывает на возможность работы с предопреде-
•
ленной переменной session на данной странице; если значение session="false", то нельзя использовать объект session, а в теге
<jsp:useBean> нельзя указывать атрибут scope с значением session. По умолчанию значение всегда true, указывающие, что создается новая сессия или используется действующая.
•
Атрибут buffer. Определяет емкость буфера для объекта, формирующего ответ, представленного в виде символьного потока jspWriter. Если указано значение none, то выходящие данные не будут
буферизироваться, в противном случае выходные данные перед
отправкой клиенту помещаются во внутренний буфер заданной
емкости. Этот атрибут используется в паре с атрибутом autoFlush.
По умолчанию значение атрибута не менее 8 кб.
•
Атрибут autoFlush ="true". Принуждает к автоматическому обновлению буфера при его заполнении, значение "false" отменяет возможность автоматического обновления буфера, что может взывать
исключительную ситуацию, когда буфер будет полным. Нельзя использовать autoFlush, если атрибут buffer имеет значение none. По
умолчанию значение атрибута "true".
•
Servlet по своей природе является многопоточным приложением.
Использование атрибута isThreadSafe помогает управлять потоками. Управление потоками осуществляется атрибутом isThreadSafe,
по умолчанию значение "true" указывает на возможность работы
JSP в многопотоковом режиме, значение "false" отправляет ответы
на клиентские запросы в прямой последовательности, сначала первый, затем второй и т. д., в последовательности, в которой принимались запросы. При многопоточной обработке клиентских запросов может возникнуть переполнение временного пула созданными
экземплярами servlet. Для предотвращения такой ситуации можно

Часть 2 Java Server Page 105
использовать указанный атрибут со значением true, или же в
скриплете синхронизировать совместно используемые данные.
Если возникает необходимость проинформировать клиента, то
•
можно воспользоваться специальным атрибутом info указанной директивы. Данный атрибут представляет текстовую строку, которую затем можно обработать в методе Servlet.getServletInfo().
Замечательный атрибут errorPage. Указывает относительный путь,
•
куда JSP посылает сообщения о возникающих в момент исполнения исключительных ситуациях и где они будут обрабатываться.
Если путь не указан явно, то обработка исключительных ситуаций
происходит в самом вызывающем JSP-файле. В спецификации 1.0
обязательным является указание именно URL JSP-страницы.
В отличие от предшественника, атрибут isErrorPage- имеет логи-
•
ческие значения, если атрибут имеет значение true, то можно использовать объекты класса exception в JSP файле, т. е. данная
страница является страницей по обработке исключительных ситуаций, вызываемых другими страницами, по умолчанию данный атрибут установлен в значение false.
Установкой передаваемого типа приложения руководит атрибут
•
contentType он определяет, какой MIME тип используется для ответа на запрос клиента, а также используемый тип кодировки. По
умолчанию данным типом является text/html и кодировка ISO8859-1. Установка атрибута на другое значение позволит избежать
установки данных параметров, используя метод setContentType("text\html") встроенного объекта response.
Директива <%@ page %> достаточно интересна в качестве использования предопределенных параметров JSP-страницы. Гибкая настройка
с помощью атрибутов позволяет в дальнейшем избежать массу хлопот
по управлению JSP-страницей. Директива имеет достаточное количество мощных встроенных средств, легко настраивается и прекрасно подходит для управления всем приложением в целом. Не использование
директивы <%@page%> можно оправдать только одной причиной — использованием специальных JSP тегов.
10.4.3. Директива Taglib<%@ taglib %>
О JavaBean уже упоминалось достаточно много, скриплеты вроде бы
тоже расмотрены, остались другие типы программ, используемые в
JSP, так называемые теги. Теги в JSP тоже могут быть написаны на Java, но, в отличие от скриплетов являются законченными, оттранслированными программами, вставляемыми в JSP. Основное ограничение
стандартных HTML-тегов, их малое количество. Коммерческие Webбраузеры не предусмотрены для поддержки пользовательских тегов.
Однако ничто не мешает создавать теги на стороне сервера, способного
обрабатывать такие теги.
Версия JSP 1.1 содержит расширенную возможность работы с тегами. Кроме стандартных тегов в версии 1.1 предусмотрена возможность
создания тегов самим разработчиком, необходимые для этого классы
находятся в пакете javax.servlet.tegext.

106 Часть 2 Java Server Page
Директиву Taglib необходимо указать, если на странице предполагается использовать пользовательские теги. Пользовательские теги предназначены для выполнения работы, с которой не могут справиться
стандартные теги или, говоря проще, пользовательские теги решают
пользовательские задачи. Например, с помощью пользовательских тегов
можно организовать доступ к базе данных, отправить XML-документ
или организовать цикл. Все это можно решить и с помощью JavaBean
или скриплета, но здесь описывается только директива Taglib по работе
с пользовательскими тегами в JSP-странице, все остальное или уже
описывалось, или только будет описываться.
Для работы данной директивы необходимы две вещи — текстовый
файл, описывающий теги, и непосредственно сами теги.
Сама директива Taglib также состоит из двух параметров, имеющих
строковые значения, — первый определяет путь к библиотеке пользовательских тегов, другой — их префиксы. Директива имеет всего два
атрибута, но мощь пользовательских тегов, описанных в данных атрибутах, безгранична:
<%@ taglib uri= "somewhere/web/taglib" prefix=" tag prefix"%>.
Согласно директиве <%@ taglib%>, первый атрибут Uniform Resource Identifier (URI) указывает путь для поиска файла, описывающего
пользовательский тег — Tag Library Descriptor.
Обычно это простое
строковое значение, описанное в другом файле, описывающем всю аппликацию или просто строка, указывающая относительный путь к документу. Атрибут prefix содержит метку в библиотеке пользовательских тегов, по которой в дальнейшем JSP обращается к пользовательскому тегу.
Пользовательский тег подобен XML тегам и состоит из тега и самого
элемента. Пользовательский тег, как и обычный тег, должен иметь обязательно открывающийся и закрывающийся элементы.
<taglibname:myteg attrib1="values1"…..attribN="valuesN"> — открывающийся тег с атрибутами.
</taglibname:myteg> — закрывающийся тег.
В пользовательском теге отсутствуют скриптовые элементы JSP, такие, как знак процента (%), но обязательно указывается обратный слеш
(/), указывающий окончание тега. Директиву <% @ taglib %> нужно
обязательно использовать до инициализации пользовательского тега в
JSP-файле. Можно поместить несколько директив <%@ teglib %> в
JSP, но префиксы у каждого должны быть уникальными. Префикс не
должен содержать ключевых слов JSP, jspx, java, javax, servlet и не может быть пустым.
Использовать bean или создавать тег — основное решение, которое
необходимо принять при проектировании JSP-страницы. Bean всегда
вызывается JSP-страницей с сервера, в то время как тег выполняется
на самой JSP-странице в момент запроса ресурса клиентом. Исходя из
этого, можно предположить, что использовать — bean или же создавать
тег.

Часть 2 Java Server Page 107
10.4.4. Предопределенные переменные: session, application, config, page,
exception, pageContext
Для облегчения работы с важными объектами в спецификации 0.91
включены предопределенные переменные: request, response, out, in.
В спецификации 1.0 данный перечень дополнен следующими предопределенными переменными: session, application, config, page, exception, pageContext и удален объект in. Использование встроенных объектов облегчает обработку часто встречающихся операций. Это значит, что не
надо специально создавать новые объекты для работы с клиентскими
запросами. Для работы с предопределенными переменными не надо
инициализировать никаких объектов. Предопределенные переменные и
соответствующие методы просто вызываются в скриплете:
<%
response.getParameter("someParameter");
%>
Предопределенные переменные не надо декларировать. Не надо импортировать пакеты, содержащие классы, от которых порождены предопределенные переменные. Предопределенные переменные можно использовать в коде скриплета без каких-либо ограничений.
Встроенный объект request предназначен для получения информа-
•
ции о клиентском запросе. Имеет ряд полезных методов. Используя метод getMetod() данного объекта, можно узнать тип запроса
(GET, POST, HEAD, etc.). Встроенный объект request является
объектом класса javax.servlet.HttpServletRequest. Некоторые полезные методы объекта request: getParameter(), getParameterNames(), getParameterValues(). С помощью данных методов можно получить значения передаваемых параметров. Так как объект request наиболее часто встречается JSP-странице при обработке
клиентских запросов, то использование именно методов объекта
request представляет наибольший интерес. У объекта request существует множество полезных методов:
<%
out.println("<H4><B>Additional Request Information:</B></H4>");
out.println("<B>Request method:</B> " + request.getMethod() + "<BR>");
out.println("<B>Request URI:</B> " + request.getRequestURI() + "<BR>");
out.println("<B>Request protocol:</B> " + request.getProtocol() + "<BR>");
out.println("<B>Request scheme:</B> " + request.getScheme() + "<BR>");
out.println("<B>Servlet path:</B> " + request.getServletPath() + "<BR>");
out.println("<B>Servlet name:</B> " + request.getServerName() + "<BR>");
out.println("<B>Servlet port:</B> " + request.getServerPort() + "<BR>");
out.println("<B>Path info:</B> " + request.getPathInfo() + "<BR>");
out.println("<B>Path translated:</B> " + request.getPathTranslated() +
"<BR>");
out.println("<B>Characterencoding:</B>"+request.getCharacterEncoding()+
BR>");
out.println("<B>Query string:</B> " + request.getQueryString() + "<BR>");

108 Часть 2 Java Server Page
out.println("<B>Content length:</B> " + request.getContentLength() +
"<BR>");
out.println("<B>Content type:</B> " + request.getContentType() + "<BR>");
out.println("<B>Remote user:</B> " + request.getRemoteUser() + "<BR>");
out.println("<B>Remote address:</B> " + request.getRemoteAddr() + "<BR>");
out.println("<B>Remote host:</B> " + request.getRemoteHost() + "<BR>");
out.println("<B>Authorization scheme:</B> " + request.getAuthType() +
"<BR>");%>
Большая часть информации о роли выполняемого метода описана в
имени метода. Другую информацию можно получить непосредственно
из фирменного описания API по объектам servlet. Большинство аналогичных параметров можно получить, используя классы пакета java.net.
Предопределенная переменная response представляет объект ответ
•
(response) для клиента. Она не является выходящим потоком отображения данных в браузере клиента. Порожден от javax.servlet.HttpServletResponse. В отличие от объекта out, не предназначен
для вывода информации в браузер, а только дополняет выходной
поток данных служебной информацией. Используя методы setHeader(), containsHeader(), setIntHeader() и setDateHeader() объекта,
клиенту передаются данные в виде заголовков. Методы sendRedirect() и sendError() предназначены для перенаправления данных.
Для декодирования URL используются методы encodeUrl(), encodeURL(), encodeRedirectURL() и encodeRedirectUrl(). Ответ для
клиента представляет только видимую информацию, именно видимую информацию выводит в окне браузера преопределенный объект out. Объект response описывает общую форму сформированного клиентского ответа, содержащего только служебную информацию. Разница между объектами out и response, в том что первый
выводит информацию, а второй формирует эту информацию для
клиента. Не всегда ответ для клиента представляет видимую информацию, а сервер работает со служебной информацией.
•
Информационный встроенный объект pageContext — контекст
данной страницы JSP. Является объектом класса javax.servlet.jsp.PageContext. JSP производит новый класс, называемый PageContext, и вставляет в этот класс специфические серверные данные. Основная идея использования PageContext и его методов getAttributeNamesInScope(), getAttributesScope(), findAttribute(),
getAttribute() заключается в организации доступа к параметрам
данной страницы при помощи других объектов для совместной работы.
Самый «стандартный» объект, используемый в JSP out — объект
класса PrintWriter. Он используется для формирования сообщений
клиенту. Методы сlear(), clearBuffer(), flush(), getBufferSize(), getRemaining() позволяют работать с внутренним кэшем JSP-страницы для
формирования выходящего потока, выводом информации занимается
множество методов print() и println(). Два метода, практически идентичных, используют встроенный объект out для вывода информации в

Часть 2 Java Server Page 109
браузере клиента. Метод out.print() выводит одну текстовую строку, а
метод out.println() используется для вывода нескольких разделенных
строк.
Отражением клиентской сессии является объект session — объ-
•
ект, ассоциированный с объектом request. Вызывается автоматически при создании сессии, javax.servlet.http.HttpSession родительский класс. Используя методы getId(), getValue(), getValueNames(), putValue(), можно получит свойства сессии .Время
создания сессии узнается с помощью метода getCreationTime(),а
время последнего доступа можно получить, используя метод getLastAccessedTime()
О исполняемом окружении приложения расскажет объект application — он указывает приложение по обработке клиентского запроса. Используя объект javax.servlet.ServletContext можно получить внутренние
сведенья об исполняемом servlet. Имеет методы getMimeType(), getRealPath() для определения используемого mime тип приложения, а также получения пути, по которому находится приложение. Методы по
установке и получению атрибутов setAttribute() и getAttribute() getAttributeNames(), также полезны методы получения информации об исполняемом servlet getServerInfo() и getServlets().По умолчанию практически все JSP-страницы участвуют в сессии.
В JSP имеется встроенный объект, ассоциированный с клиентской
сессией — session. Сессия — хорошее место для хранения различного
рода информации используемой совместно различными JSP. Для идентификации конкретной сессии используется метка ID хранящаяся на
локальной машине клиента как cookie. Если браузер не поддерживает
работу с cookies,(обычно это ранние версии браузеров), то сессия использует специальные метод переписывания URL. К сожалению, в JSP
отсутствует поддержка переписывания URL. Для решения этой проблемы можно создать Java объект и назначить его уникальным идентификатором
<%
Foo foo = new Foo();
session.putValue("foo",foo); %>
Чтобы воспользоваться данным идентификатором, необходимо сделать экземпляр объекта доступным для всех страниц.
<%
Foo myFoo = (Foo) session.getValue("foo"); %>
Вызов метода session.getValue() возвращает ссылку на объект. Указание в директиве<%@ page session="false" %> значения false, указывает
на запрещение создания в сессии объектов. По умолчанию отсутствует
ограничение на количество используемых объектов в сессии. Однако помещение больших объектов значительно снижает производительность
системы. Большинство серверов ограничивают время жизни объектов в
сессии, использование же метода setMaxInvalidationInterval(), позволя-

110 Часть 2 Java Server Page
ет установить время жизни объектов самостоятельно. После удаления
сессии или ее окончания, объекты сессии также удаляются.
Инициализационные параметры можно получить, используя объ-
•
ект config- он происходит от javax.servlet.ServletConfig, представляет собой конфигурационный объект исполняемого servlet .Размещает ServletConfig объект на странице. Методы getInitParameter(),
getInitParameterNames() предназначены для получения параметров инициализации.
Стандартный объект, часто используемый в обычных Java приложениях exception — объект класса java.lang.Throwable, имеет очень полезные методы getMessage(), getLocalizedMessage(), printStackTrace() для
трассировки и отладки. В JSP существуют два варианта работы с исключительными ситуациями. Первый определяет местоположение обработчика ошибок на выполняемой странице,при этом используется атрибут isErrorPage со значением true.
<%@ page isErrorPage="true" %>.
Другой способ заключается в перенаправлении информации о возникшей ошибке на специальную страницу.
<%@ page isErrorPage="false" errorPage="errorHandler.jsp" %> и
тогда на странице указанной в атрибуте errorPage, должна быть указана первая директива. Данное использование директивы указывает что
страница не является обработчиком ошибок, а перенаправляет сведения
о них в другой JSP файл — errorHandler.jsp.
Объект page –java.lang.Object представляет данную страницу.
Описание объекта in версии 0.91 опущено, поскольку не представляет на данный момент практического интереса. 0.91 версия практически
полностью заменена более новой версией во всех приложениях использующих JSP..
Нельзя забывать, что встроенные JSP объекты это в первую очередь
Java классы со своим методами и свойствами. Для получения полного
перечня методов, присущих каждому встроенному объекту можно обратиться к документации по каждому классу, от которого порожден объект.
Предопределенные объекты предоставляют большое количество методов, помогающих получать и устанавливать системную информацию
для работы с внешним данными, хранящимися в во внешних файловых
системах или базах данных.
Использование bean имеет ряд преимуществ перед обычным скриплетом и объектом request. Но для большей гибкости приложения можно
использовать оба способа доступа к необходимым параметрам. Например, bean можно использовать для обращения к базе данных, втоже
время объект request можно использовать для обработки единичных
параметров информации. Кроме того, часть значений методов могут
быть доступны и через другие объекты. Все методы объекта request,
используемого в JSP, являются методами объекта, порожденного от
класса HtttpServletRequest.
Немаловажной деталью является область видимости предопределенных объектов. Все встроенные объекты видимы только в основном мето-
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
