[Вопросы для собеседования](README.md) # Servlets, JSP, JSTL + [Что такое _«сервлет»_?](#Что-такое-сервлет) + [В чем заключаются преимущества технологии сервлетов над CGI (Common Gateway Interface)?](#В-чем-заключаются-преимущества-технологии-сервлетов-над-cgi-common-gateway-interface) + [Какова структура веб-проекта?](#Какова-структура-веб-проекта) + [Что такое _«контейнер сервлетов»_?](#Что-такое-контейнер-сервлетов) + [Зачем нужны сервера приложений, если есть контейнеры сервлетов?](#Зачем-нужны-сервера-приложений-если-есть-контейнеры-сервлетов) + [Как контейнер сервлетов управляет жизненным циклом сервлета, когда и какие методы вызываются?](#Как-контейнер-сервлетов-управляет-жизненным-циклом-сервлета-когда-и-какие-методы-вызываются) + [Что такое _«дескриптор развертывания»_?](#Что-такое-дескриптор-развертывания) + [Какие действия необходимо проделать при создании сервлетов?](#Какие-действия-необходимо-проделать-при-создании-сервлетов) + [В каком случае требуется переопределять метод `service()`?](#В-каком-случае-требуется-переопределять-метод-service) + [Есть ли смысл определять для сервлета конструктор? Каким образом лучше инициализировать данные?](#Есть-ли-смысл-определять-для-сервлета-конструктор-Каким-образом-лучше-инициализировать-данные) + [Почему необходимо переопределить только `init()` метод без аргументов?](#Почему-необходимо-переопределить-только-init-метод-без-аргументов) + [Какие наиболее распространенные задачи выполняются в контейнере сервлетов?](#Какие-наиболее-распространенные-задачи-выполняются-в-контейнере-сервлетов) + [Что вы знаете о _сервлетных фильтрах_?](#Что-вы-знаете-о-сервлетных-фильтрах) + [Зачем в сервлетах используются различные _listener_?](#Зачем-в-сервлетах-используются-различные-listener) + [Когда стоит использовать фильтры сервлетов, а когда слушателей?](#Когда-стоит-использовать-фильтры-сервлетов-а-когда-слушателей) + [Как реализовать запуск сервлета одновременно с запуском приложения?](#Как-реализовать-запуск-сервлета-одновременно-с-запуском-приложения) + [Как обработать в приложении исключения, выброшенные другим сервлетом?](#Как-обработать-в-приложении-исключения-выброшенные-другим-сервлетом) + [Что представляет собой `ServletConfig`?](#Что-представляет-собой-servletconfig) + [Что представляет собой `ServletContext`?](#Что-представляет-собой-servletcontext) + [В чем отличия `ServletContext` и `ServletConfig`?](#В-чем-отличия-servletcontext-и-servletconfig) + [Для чего нужен интерфейс `ServletResponse`?](#Для-чего-нужен-интерфейс-servletresponse) + [Для чего нужен интерфейс `ServletRequest`?](#Для-чего-нужен-интерфейс-servletrequest) + [Что такое `Request Dispatcher`?](#Что-такое-request-dispatcher) + [Как из одного сервлета вызвать другой сервлет?](#Как-из-одного-сервлета-вызвать-другой-сервлет) + [Чем отличается `sendRedirect()` от `forward()`?](#Чем-отличается-sendredirect-от-forward) + [Для чего используются атрибуты сервлетов и как происходит работа с ними?](#Для-чего-используются-атрибуты-сервлетов-и-как-происходит-работа-с-ними) + [Каким образом можно допустить в сервлете deadlock?](#Каким-образом-можно-допустить-в-сервлете-deadlock) + [Как получить реальное расположение сервлета на сервере?](#Как-получить-реальное-расположение-сервлета-на-сервере) + [Как получить информацию о сервере из сервлета?](#Как-получить-информацию-о-сервере-из-сервлета) + [Как получить IP адрес клиента на сервере?](#Как-получить-ip-адрес-клиента-на-сервере) + [Какие классы-обертки для сервлетов вы знаете?](#Какие-классы-обертки-для-сервлетов-вы-знаете) + [В чем отличия `GenericServlet` и `HttpServlet`?](#В-чем-отличия-genericservlet-и-httpservlet) + [Почему `HttpServlet` класс объявлен как абстрактный?](#Почему-httpservlet-класс-объявлен-как-абстрактный) + [Какие основные методы присутствуют в классе `HttpServlet`?](#Какие-основные-методы-присутствуют-в-классе-httpservlet) + [Стоит ли волноваться о многопоточной безопасности работая с сервлетами?](#Стоит-ли-волноваться-о-многопоточной-безопасности-работая-с-сервлетами) + [Какой метод HTTP не является неизменяемым?](#Какой-метод-http-не-является-неизменяемым) + [Какие есть методы отправки данных с клиента на сервер?](#Какие-есть-методы-отправки-данных-с-клиента-на-сервер) + [В чем разница между методами `GET` и `POST`?](#В-чем-разница-между-методами-get-и-post) + [В чем разница между `PrintWriter` и `ServletOutputStream`?](#В-чем-разница-между-printwriter-и-servletoutputstream) + [Можно ли одновременно использовать в сервлете `PrintWriter` и `ServletOutputStream`?](#Можно-ли-одновременно-использовать-в-сервлете-printwriter-и-servletoutputstream) + [Расскажите об интерфейсе `SingleThreadModel`.](#Расскажите-об-интерфейсе-singlethreadmodel) + [Что означает _URL encoding_? Как это осуществить в Java?](#Что-означает-url-encoding-Как-это-осуществить-в-java) + [Какие различные методы управления сессией в сервлетах вы знаете?](#Какие-различные-методы-управления-сессией-в-сервлетах-вы-знаете) + [Что такое _cookies_?](#Что-такое-cookies) + [Какие методы для работы с cookies предусмотрены в сервлетах?](#Какие-методы-для-работы-с-cookies-предусмотрены-в-сервлетах) + [Что такое _URL Rewriting_?](#Что-такое-url-rewriting) + [Зачем нужны и чем отличаются методы `encodeURL()` и `encodeRedirectURL()`?](#Зачем-нужны-и-чем-отличаются-методы-encodeurl-и-encoderedirecturl) + [Что такое _«сессия»_?](#Что-такое-сессия) + [Как уведомить объект в сессии, что сессия недействительна или закончилась?](#Как-уведомить-объект-в-сессии-что-сессия-недействительна-или-закончилась) + [Какой существует эффективный способ удостоверится, что все сервлеты доступны только для пользователя с верной сессией?](#Какой-существует-эффективный-способ-удостоверится-что-все-сервлеты-доступны-только-для-пользователя-с-верной-сессией) + [Как мы можем обеспечить _transport layer security_ для нашего веб приложения?](#Как-мы-можем-обеспечить-transport-layer-security-для-нашего-веб-приложения) + [Как организовать подключение к базе данных, обеспечить журналирование в сервлете?](#Как-организовать-подключение-к-базе-данных-обеспечить-журналирование-в-сервлете) + [Какие основные особенности появились в спецификации _Servlet 3_?](#Какие-основные-особенности-появились-в-спецификации-servlet-3) + [Какие способы аутентификации доступны сервлету?](#Какие-способы-аутентификации-доступны-сервлету) + [Что такое _Java Server Pages (JSP)_?](#Что-такое-java-server-pages-jsp) + [Зачем нужен JSP?](#Зачем-нужен-jsp) + [Опишите, как обрабатываются JSP страницы, начиная от запроса к серверу, заканчивая ответом пользователю.](#Опишите-как-обрабатываются-jsp-страницы-начиная-от-запроса-к-серверу-заканчивая-ответом-пользователю) + [Расскажите об этапах (фазах) жизненного цикла JSP.](#Расскажите-об-этапах-фазах-жизненного-цикла-jsp) + [Расскажите о методах жизненного цикла JSP.](#Расскажите-о-методах-жизненного-цикла-jsp) + [Какие методы жизненного цикла JSP могут быть переопределены?](#Какие-методы-жизненного-цикла-jsp-могут-быть-переопределены) + [Как можно предотвратить прямой доступ к JSP странице из браузера?](#Как-можно-предотвратить-прямой-доступ-к-jsp-странице-из-браузера) + [Какая разница между _динамическим_ и _статическим_ содержимым JSP?](#Какая-разница-между-динамическим-и-статическим-содержимым-jsp) + [Как закомментировать код в JSP?](#Как-закомментировать-код-в-jsp) + [Какие существуют основные типы тегов JSP?](#Какие-существуют-основные-типы-тегов-jsp) + [Что вы знаете о действиях JSP (_Action tag_ и _JSP Action Elements_).](#Что-вы-знаете-о-действиях-jsp-action-tag-и-jsp-action-elements) + [Взаимодействие _JSP - сервлет - JSP_.](#Взаимодействие-jsp---сервлет---jsp) + [Какие области видимости переменных существуют в JSP?](#Какие-области-видимости-переменных-существуют-в-jsp) + [Какие неявные, внутренние объекты и методы есть на JSP странице?](#Какие-неявные-внутренние-объекты-и-методы-есть-на-jsp-странице) + [Какие неявные объекты не доступны в обычной JSP странице?](#Какие-неявные-объекты-не-доступны-в-обычной-jsp-странице) + [Что вы знаете о `PageContext` и какие преимущества его использования?](#Что-вы-знаете-о-pagecontext-и-какие-преимущества-его-использования) + [Как сконфигурировать параметры инициализации для JSP?](#Как-сконфигурировать-параметры-инициализации-для-jsp) + [Почему не рекомендуется использовать скриплеты (скриптовые элементы) в JSP?](#Почему-не-рекомендуется-использовать-скриплеты-скриптовые-элементы-в-jsp) + [Можно ли определить класс внутри JSP страницы?](#Можно-ли-определить-класс-внутри-jsp-страницы) + [Что вы знаете о Языке выражений JSP (JSP Expression Language – EL)?](#Что-вы-знаете-о-Языке-выражений-jsp-jsp-expression-language--el) + [Какие типы EL операторов вы знаете?](#Какие-типы-el-операторов-вы-знаете) + [Назовите неявные, внутренние объекты JSP EL и их отличия от объектов JSP.](#Назовите-неявные-внутренние-объекты-jsp-el-и-их-отличия-от-объектов-jsp) + [Как отключить возможность использования EL в JSP?](#Как-отключить-возможность-использования-el-в-jsp) + [Как узнать тип HTTP метода используя JSP EL?](#Как-узнать-тип-http-метода-используя-jsp-el) + [Что такое _JSTL (JSP Standard tag library)_?](#Что-такое-jstl-jsp-standard-tag-library) + [Из каких групп тегов состоит библиотека _JSTL_?](#Из-каких-групп-тегов-состоит-библиотека-jstl) + [Какая разница между `` и ``?](#Какая-разница-между-cset-и-jspusebean) + [Чем отличается `` от `` и директивы `<%@include %>`?](#Чем-отличается-cimport-от-jspinclude-и-директивы-include-) + [Как можно расширить функциональность JSP?](#Как-можно-расширить-функциональность-jsp) + [Что вы знаете о написании пользовательских JSP тегов?](#Что-вы-знаете-о-написании-пользовательских-jsp-тегов) + [Приведите пример использования собственных тегов.](#Приведите-пример-использования-собственных-тегов) + [Как сделать перенос строки в HTML средствами JSP?](#Как-сделать-перенос-строки-в-html-средствами-jsp) + [Почему не нужно конфигурировать стандартные JSP теги в `web.xml`?](#Почему-не-нужно-конфигурировать-стандартные-jsp-теги-в-webxml) + [Как можно обработать ошибки JSP страниц?](#Как-можно-обработать-ошибки-jsp-страниц) + [Как происходит обработка ошибок с помощью JSTL?](#Как-происходит-обработка-ошибок-с-помощью-jstl) + [Как конфигурируется JSP в дескрипторе развертывания.](#Как-конфигурируется-jsp-в-дескрипторе-развертывания) + [Можно ли использовать Javascript на JSP странице?](#Можно-ли-использовать-javascript-на-jsp-странице) + [Всегда ли создается объект сессии на JSP странице, можно ли отключить его создание?](#Всегда-ли-создается-объект-сессии-на-jsp-странице-можно-ли-отключить-его-создание) + [Какая разница между `JSPWriter` и сервлетным `PrintWriter`?](#Какая-разница-между-jspwriter-и-сервлетным-printwriter) + [Опишите общие практические принципы работы с JSP.](#Опишите-общие-практические-принципы-работы-с-jsp) ## Что такое _«сервлет»_? __Сервлет__ является интерфейсом, реализация которого расширяет функциональные возможности сервера. Сервлет взаимодействует с клиентами посредством принципа запрос-ответ. Хотя сервлеты могут обслуживать любые запросы, они обычно используются для расширения веб-серверов. Большинство необходимых для создания сервлетов классов и интерфейсов содержатся в пакетах `javax.servlet` и `javax.servlet.http`. Основные методы сервлета: + `public void init(ServletConfig config) throws ServletException` запускается сразу после загрузки сервлета в память; + `public ServletConfig getServletConfig()` возвращает ссылку на объект, который предоставляет доступ к информации о конфигурации сервлета; + `public String getServletInfo()` возвращает строку, содержащую информацию о сервлете, например: автор и версия сервлета; + `public void service(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException` вызывается для обработки каждого запроса; + `public void destroy()` выполняется перед выгрузкой сервлета из памяти. Текущая спецификация - Servlet 3.1 описана в JSR-340 и принята в 2013 году. [к оглавлению](#servlets-jsp-jstl) ## В чем заключаются преимущества технологии сервлетов над CGI (Common Gateway Interface)? + Сервлеты предоставляют лучшую производительность обработки запросов и более эффективное использование памяти за счет использования преимущество многопоточности (на каждый запрос создается новая нить, что быстрее выделения памяти под новый объект для каждого запроса, как это происходит в CGI). + Сервлеты, как платформа и система являются независимыми. Таким образом веб-приложение написанное с использованием сервлетов может быть запущена в любом контейнере сервлетов, реализующим этот стандарт и в любой операционной системе. + Использование сервлетов повышает надежность программы, т.к. контейнер сервлетов самостоятельно заботится о жизненном цикле сервлетов (а значит и за утечками памяти), безопасности и сборщике мусора. + Сервлеты относительно легки в изучении и поддержке, таким образом разработчику необходимо заботиться только о бизнес-логике приложения, а не внутренней реализации веб-технологий. [к оглавлению](#servlets-jsp-jstl) ## Какова структура веб-проекта? `src/main/java` Исходники приложения/библиотеки `src/main/resources` Ресурсные файлы приложения/библиотеки `src/main/filters` Файлы сервлетных фильтров `src/main/webapp` Исходники веб-приложения `src/test/java` Исходники тестов `src/test/resources` Ресурсные файлы тестов `src/test/filters` Тесты сервлетных фильтров `src/it` Интеграционные тесты `src/assembly` Описание сборки `src/site` Сайт `LICENSE.txt` Лицензия проекта `NOTICE.txt` Замечания и определения библиотек зависимостей. `README.txt` Описание проекта [к оглавлению](#servlets-jsp-jstl) ## Что такое _«контейнер сервлетов»_? __Контейнер сервлетов__ — программа, представляющая собой сервер, который занимается системной поддержкой сервлетов и обеспечивает их жизненный цикл в соответствии с правилами, определёнными в спецификациях. Может работать как полноценный самостоятельный веб-сервер, быть поставщиком страниц для другого веб-сервера, или интегрироваться в Java EE сервер приложений. Контейнер сервлетов обеспечивает обмен данными между сервлетом и клиентами, берёт на себя выполнение таких функций, как создание программной среды для функционирующего сервлета, идентификацию и авторизацию клиентов, организацию сессии для каждого из них. Наиболее известные реализации контейнеров сервлетов: + Apache Tomcat + Jetty + JBoss + WildFly + GlassFish + IBM WebSphere + Oracle Weblogic [к оглавлению](#servlets-jsp-jstl) ## Зачем нужны сервера приложений, если есть контейнеры сервлетов? + __Пулы соединений с БД__ + Возможность периодического тестирования доступности СУБД и обновления соединения в случае восстановления после сбоев + Замена прав доступа при подключении + Балансировка нагрузки между несколькими СУБД, определение доступность или недоступность того или иного узла + Защита пула соединений от некорректного кода в приложении, которое по недосмотру не возвращает соединения, просто отбирая его после какого-то таймаута. + __JMS__ + Доступность сервера очередей сообщений "из-коробки". + Возможность кластеризации очередей, т.е. доступность построения распределенных очередей, расположенных сразу на нескольких серверах, что существенно увеличивает масштабируемость и доступность приложения + Возможность миграции очередей - в случае падения одного из серверов, его очереди автоматически перемещаются на другой, сохраняя необработанные сообщения. + В некоторых серверах приложений поддерживается _Unit-of-Order_ - гарантированный порядок обработки сообщений, удовлетворяющих некоторым критериям. + __JTA__ Встроенная поддержка распределенных транзакций для обеспечения согласованности данных в разные СУБД или очереди. + __Безопасность__ + Наличие множества провайдеров безопасности и аутентификации: + во встроенном или внешнем _LDAP-сервере_ + в базе данных + в различных _Internet-directory_ (специализированных приложениях для управления правами доступа) + Доступность _Single-Sign-On_ (возможности разделения пользовательской сессии между приложениями) посредством _Security Assertion Markup Language (SAML) 1/2_ или _Simple and Protected Negotiate (SPNEGO)_ и _Kerberos_: один из серверов выступает в роли базы для хранения пользователей, все другие сервера при аутентификации пользователя обращаются к этой базе. + Возможность авторизации посредством протокола _eXtensible Access Control Markup Language (XACML)_, позволяющего описывать довольно сложные политики (например, приложение доступно пользователю только в рабочее время). + Кластеризация всего вышеперечисленного + __Масштабируемость и высокая доступность__ Для контейнера сервлетов обычно так же возможно настроить кластеризацию, но она будет довольно примитивной, так как в случае его использования имееются следующие ограничения: + Сложность передачи пользовательской сессии из одного _центра обработки данных (ЦоД)_ в другой через Интернет + Отсутствие возможности эффективно настроить репликации сессий на большом (состоящем из 40-50 экземпляров серверов) кластере + Невозможность обеспечения миграции экземпляров приложения на другой сервер + Недоступность механизмов автоматического мониторинга и реакции на ошибки + __Управляемость__ + Присутствие единого центра управления, т.н. _AdminServer_ и аналога _NodeManager_’а, обеспечивающего + Возможность одновременного запуска нескольких экземпляров сервера + Просмотр состояния запущенных экземпляров сервера, обработчиков той или иной очереди, на том или ином сервере, количества соединений с той или иной БД + __Административный канал и развертывание в промышленном режиме__ Некоторые сервера приложений позволяют включить так называемый "административный канал" - отдельный порт, запросы по которому имеют приоритет. + Просмотр состояния (выполняющихся транзакций, потоков, очередей) в случае недоступности ("зависания") сервера + Обновление приложений "на-лету", без простоя: + добавление на сервер новой версии приложения в "закрытом" режиме, пока пользователи продолжают работать со предыдущей + тестирование корректности развертывания новой версии + "скрытый" перевод на использование новой версии всех пользователей [к оглавлению](#servlets-jsp-jstl) ## Как контейнер сервлетов управляет жизненным циклом сервлета, когда и какие методы вызываются? Контейнер сервлетов управляет четырьмя фазами жизненного цикла сервлета: + Загрузка класса сервлета — когда контейнер получает запрос для сервлета, то происходит загрузка класса сервлета в память и вызов его конструктора без параметров. + Инициализация класса сервлета — после того как класс загружен контейнер инициализирует объект `ServletConfig` для этого сервлета и внедряет его через `init()` метод. Это и есть место где сервлет класс преобразуется из обычного класса в сервлет. + Обработка запросов — после инициализации сервлет готов к обработке запросов. Для каждого запроса клиента сервлет контейнер порождает новый поток и вызывает метод `service()` путем передачи ссылки на объекты ответа и запроса. + Удаление - когда контейнер останавливается или останавливается приложение, то контейнер сервлетов уничтожает классы сервлетов путем вызова `destroy()` метода. Таким образом, сервлет создаётся при первом обращении к нему и живёт на протяжении всего времени работы приложения (в отличии от объектов классов, которые уничтожаются сборщиком мусора после того как они уже не используются) и весь жизненный цикл сервлета можно описать как последовательность вызова методов: + `public void init(ServletConfig config)` – используется контейнером для инициализации сервлета. Вызывается один раз за время жизни сервлета. + `public void service(ServletRequest request, ServletResponse response)` – вызывается для каждого запроса. Метод не может быть вызван раньше выполнения `init()` метода. + `public void destroy()` – вызывается для уничтожения сервлета (один раз за время жизни сервлета). [к оглавлению](#servlets-jsp-jstl) ## Что такое _«дескриптор развертывания»_? Дескриптор развертывания — это конфигурационный файл артефакта, который будет развернут в контейнере сервлетов. В спецификации Java Platform, Enterprise Edition дескриптор развертывания описывает то, как компонент, модуль или приложение (такое, как веб-приложение или приложение предприятия) должно быть развернуто. Этот конфигурационный файл указывает параметры развертывания для модуля или приложения с определенными настройками, параметры безопасности и описывает конкретные требования к конфигурации. Для синтаксиса файлов дескриптора развертывания используется язык XML. ```xml Display name. Description text. ExampleServlet xyz.company.ExampleServlet 1 configuration default ExampleServlet /example ExampleJSP /sample/Example.jsp myParam the value ``` Для веб-приложений дескриптор развертывания должен называться `web.xml` и находиться в директории `WEB-INF`, в корне веб-приложения. Этот файл является стандартным дескриптором развертывания, определенным в спецификации. Также есть и другие типы дескрипторов, такие, как файл дескриптора развертывания `sun-web.xml`, содержащий специфичные для _Sun GlassFish Enterprise Server_ данные для развертывания именно для этого сервера приложений или файл `application.xml` в директории `META-INF` для приложений _J2EE_. [к оглавлению](#servlets-jsp-jstl) ## Какие действия необходимо проделать при создании сервлетов? Чтобы создать сервлет `ExampleServlet`, необходимо описать его в дескрипторе развёртывания: ```xml ExampleServlet /example ExampleServlet xyz.company.ExampleServlet config default ``` Затем создать класс `xyz.company.ExampleServlet` путём наследования от `HttpServlet` и реализовать логику его работы в методе `service()` или методах `doGet()`/`doPost()`. [к оглавлению](#servlets-jsp-jstl) ## В каком случае требуется переопределять метод `service()`? Метод `service()` переопределяется, когда необходимо, чтобы сервлет обрабатывал все запросы (и `GET`, и `POST`) в одном методе. Когда контейнер сервлетов получает запрос клиента, то происходит вызов метода `service()`, который в зависимости от поступившего запроса вызывает или метод `doGet()` или метод `doPost()`. [к оглавлению](#servlets-jsp-jstl) ## Есть ли смысл определять для сервлета конструктор? Каким образом лучше инициализировать данные? Большого смысла определять для сервлета конструктор нет, т.к. инициализировать данные лучше не в конструкторе, а переопределив метод `init()`, в котором имеется возможность доступа к параметрам инициализации сервлета через использование объекта `ServletConfig`. [к оглавлению](#servlets-jsp-jstl) ## Почему необходимо переопределить только `init()` метод без аргументов? Метод `init()` переопределяется, если необходимо инициализировать какие-то данные до того как сервлет начнет обрабатывать запросы. При переопределении метода `init(ServletConfig config)`, первым должен быть вызван метод `super(config)`, который обеспечит вызов метода `init(ServletConfig config)` суперкласса. `GenericServlet` предоставляет другой метод `init()` без параметров, который будет вызываться в конце метода `init(ServletConfig config)`. Необходимо использовать переопределенный метод `init()` без параметров для инициализации данных во избежание каких-либо проблем, например ошибку, когда вызов `super()` не указан в переопределенном `init(ServletConfig config)`. [к оглавлению](#servlets-jsp-jstl) ## Какие наиболее распространенные задачи выполняются в контейнере сервлетов? + Поддержка обмена данными. Контейнер сервлетов предоставляет легкий способ обмена данными между веб клиентом (браузером) и сервлетом. Благодаря контейнеру нет необходимости создавать слушателя сокета на сервере для отслеживания запросов от клиента, а так же разбирать запрос и генерировать ответ. Все эти важные и комплексные задачи решаются с помощью контейнера и разработчик может сосредоточиться на бизнес логике приложения. + Управление жизненным циклом сервлетов и ресурсов. Начиная от загрузки сервлета в память, инициализации, внедрения методов и заканчивая уничтожением сервлета. Контейнер так же предоставляет дополнительные утилиты, например JNDI, для управления пулом ресурсов. + Поддержка многопоточности. Контейнер самостоятельно создает новую нить для каждого запроса и предоставляет ей запрос и ответ для обработки. Таким образом сервлет не инициализируется заново для каждого запроса и тем самым сохраняет память и уменьшает время до обработки запроса. + Поддержка JSP. JSP классы не похожи на стандартные классы джавы, но контейнер сервлетов преобразует каждую JSP в сервлет и далее управляется контейнером как обычным сервлетом. + Различные задачи. Контейнер сервлетов управляет пулом ресурсов, памятью приложения, сборщиком мусора. Предоставляются возможности настройки безопасности и многое другое. [к оглавлению](#servlets-jsp-jstl) ## Что вы знаете о _сервлетных фильтрах_? __Сервлетный фильтр__ - это Java-код, пригодный для повторного использования и позволяющий преобразовать содержание HTTP-запросов, HTTP-ответов и информацию, содержащуюся в заголовках HTML. Сервлетный фильтр занимается предварительной обработкой запроса, прежде чем тот попадает в сервлет, и/или последующей обработкой ответа, исходящего из сервлета. Сервлетные фильтры могут: + перехватывать инициацию сервлета прежде, чем сервлет будет инициирован; + определить содержание запроса прежде, чем сервлет будет инициирован; + модифицировать заголовки и данные запроса, в которые упаковывается поступающий запрос; + модифицировать заголовки и данные ответа, в которые упаковывается получаемый ответ; + перехватывать инициацию сервлета после обращения к сервлету. Сервлетный фильтр может быть конфигурирован так, что он будет работать с одним сервлетом или группой сервлетов. Основой для формирования фильтров служит интерфейс `javax.servlet.Filter`, который реализует три метода: + `void init(FilterConfig config) throws ServletException`; + `void destroy()`; + `void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException`; Метод `init()` вызывается прежде, чем фильтр начинает работать,и настраивает конфигурационный объект фильтра. Метод `doFilter()` выполняет непосредственно работу фильтра. Таким образом, сервер вызывает `init()` один раз, чтобы запустить фильтр в работу, а затем вызывает `doFilter()` столько раз, сколько запросов будет сделано непосредственно к данному фильтру. После того, как фильтр заканчивает свою работу, вызывается метод `destroy()`. Интерфейс `FilterConfig` содержит метод для получения имени фильтра, его параметров инициации и контекста активного в данный момент сервлета. С помощью своего метода `doFilter()` каждый фильтр получает текущий запрос `request` и ответ `response`, а также `FilterChain`, содержащий список фильтров, предназначенных для обработки. В `doFilter()` фильтр может делать с запросом и ответом всё, что ему захочется - собирать данные или упаковывать объекты для придания им нового поведения. Затем фильтр вызывает `chain.doFilter()`, чтобы передать управление следующему фильтру. После возвращения этого вызова фильтр может по окончании работы своего метода `doFilter()` выполнить дополнительную работу над полученным ответом. К примеру, сохранить регистрационную информацию об этом ответе. После того, как класс-фильтр откомпилирован, его необходимо установить в контейнер и _«приписать» (map)_ к одному или нескольким сервлетам. Объявление и подключение фильтра отмечается в дескрипторе развёртывания `web.xml` внутри элементов `` и ``. Для подключение фильтра к сервлету необходимо использовать вложенные элементы `` и ``. > Объявление класс-фильтра `FilterConnect` с именем `FilterName`: ```xml FilterName FilterConnect active true ``` > Подключение фильтра `FilterName` к сервлету `ServletName`: ```xml FilterName ServletName ``` Для связи фильтра со страницами HTML или группой сервлетов необходимо использовать тег ``: > Подключение фильтра `FilterName` ко всем вызовам .html страниц ```xml FilterName *.html ``` Порядок, в котором контейнер строит цепочку фильтров для запроса определяется следующими правилами: + цепочка, определяемая ``, выстраивается в том порядке, в котором встречаются соответствующие описания фильтров в `web.xml`; + последовательность сервлетов, определенных с помощью ``, также выполняется в той последовательности, в какой эти элементы встречаются в дескрипторе развёртывания `web.xml`. [к оглавлению](#servlets-jsp-jstl) ## Зачем в сервлетах используются различные _listener_? __Listener (слушатель)__ работает как триггер, выполняя определённые действия при наступлении какого-либо события в жизненном цикле сервлета. Слушатели, разделённые по области видимости (scope): + _Request_: + `ServletRequestListener` используется для того, чтобы поймать момент создания и уничтожения запроса; + `ServletRequestAttributeListener` используется для прослушивании событий происходящих с атрибутами запроса. + _Context_: + `ServletContextListener` позволяет поймать момент, когда контекст инициализируется либо уничтожается; + `ServletContextAttributeListener` используется для прослушивании событий происходящих с атрибутами в контексте. + _Session_: + `HttpSessionListener` позволяет поймать момент создания и уничтожения сессии; + `HttpSessionAttributeListener` используется при прослушивании событий происходящих с атрибутами в сессии; + `HttpSessionActivationListener` используется в случае, если происходит миграция сессии между различными JVM в распределённых приложениях; + `HttpSessionBindingListener` так же используется для прослушивания событий происходящих с атрибутами в сессии. Разница между `HttpSessionAttributeListener` и `HttpSessionBindingListener` слушателями: первый декларируется в `web.xml`; экземпляр класса создается контейнером автоматически в единственном числе и применяется ко всем сессиям; второй: экземпляр класса должен быть создан и закреплён за определённой сессией «вручную», количество экземпляров также регулируется самостоятельно. Подключение слушателей: ```xml ... xyz.company.ExampleListener ... ``` `HttpSessionBindingListener` подключается в качестве атрибута непосредственно в сессию, т.е., чтобы его подключить необходимо: + создать экземпляр класса реализующего этот интерфейс; + положить созданный экземпляр в сессию при помощи `setAttribute(String, Object)`. [к оглавлению](#servlets-jsp-jstl) ## Когда стоит использовать фильтры сервлетов, а когда слушателей? Следует использовать фильтры, если необходимо обрабатывать входящие или исходящие данные (например: для аутентификации, преобразования формата, компрессии, шифрования и т.д.), в случае, когда необходимо реагировать на события - лучше применять слушателей. [к оглавлению](#servlets-jsp-jstl) ## Как реализовать запуск сервлета одновременно с запуском приложения? Контейнер сервлетов обычно загружает сервлет по первому запросу клиента. Если необходимо загрузить сервлет прямо на старте приложения (например если загрузка сервлета происходит длительное время) следует использовать элемент `` в дескрипторе или аннотацию `@loadOnStartup` в коде сервлета, что будет указывать на необходимость загрузки сервлета при запуске. Если целочисленное значение этого параметра отрицательно, то сервлет будет загружен при запросе клиента. В противном случае - загрузится на старте приложения, при этом, чем число меньше, тем раньше в очереди на загрузку он окажется. ```xml ExampleServlet xyz.company.ExampleServlet 1 ``` [к оглавлению](#servlets-jsp-jstl) ## Как обработать в приложении исключения, выброшенные другим сервлетом? Когда приложение выбрасывет исключение контейнер сервлетов обрабатывает его и создаёт ответ в формате HTML. Это аналогично тому что происходит при кодах ошибок вроде 404, 403 и т.д. В дополнении к этому существует возможность написания собственных сервлетов для обработки исключений и ошибок с указанием их в дескрипторе развертывания: ```xml 404 /AppExceptionHandler javax.servlet.ServletException /AppExceptionHandler ``` Основная задача таких сервлетов - обработать ошибку/исключение и сформировать понятный ответ пользователю. Например, предоставить ссылку на главную страницу или же описание ошибки. [к оглавлению](#servlets-jsp-jstl) ## Что представляет собой `ServletConfig`? Интерфейс `javax.servlet.ServletConfig` используется для передачи сервлету конфигурационной информации. Каждый сервлет имеет свой собственный экземпляр объекта `ServletConfig`, создаваемый контейнером сервлетов. Для установки параметров конфигурации используются параметры `init-param` в `web.xml`: ```xml ExampleServlet xyz.company.ExampleServlet exampleParameter parameterValue ``` или аннотации `@WebInitParam`: ```java @WebServlet( urlPatterns = "/example", initParams = { @WebInitParam(name = "exampleParameter", value = "parameterValue") } ) public class ExampleServlet extends HttpServlet { //... } ``` Для получения `ServletConfig` сервлета используется метод `getServletConfig()`. [к оглавлению](#servlets-jsp-jstl) ## Что представляет собой `ServletContext`? Уникальный (в рамках веб-приложения) объект `ServletContext` реализует интерфейс `javax.servlet.ServletContext` и предоставляет сервлетам доступ к параметрам этого веб-приложения. Для предоставления доступа используется элемент `` в `web.xml`: ```xml ... exampleParameter parameterValue ... ``` Объект `ServletContext` можно получить с помощью метода `getServletContext()` у интерфейса `ServletConfig`. Контейнеры сервлетов так же могут предоставлять контекстные объекты, уникальные для группы сервлетов. Каждая из групп будет связана со своим набором URL-путей хоста. В спецификации Servlet 3 `ServletContext` был расширен и теперь предоставляет возможности программного добавления слушателей и фильтров в приложение. Так же у этого интерфейса имеется множество полезных методов таких как `getServerInfo()`, `getMimeType()`, `getResourceAsStream()` и т.д. [к оглавлению](#servlets-jsp-jstl) ## В чем отличия `ServletContext` и `ServletConfig`? + `ServletConfig` уникален для сервлета, а `ServletContext` - для приложения; + `ServletConfig` используется для предоставления параметров инициализации конкретному сервлету, а `ServletContext` для предоставления параметров инициализации для всех сервлетов приложения; + для `ServletConfig` возможности модифицировать атрибуты отсутствуют, атрибуты в объекте `ServletContext` можно изменять. [к оглавлению](#servlets-jsp-jstl) ## Для чего нужен интерфейс `ServletResponse`? Интерфейс `ServletResponse` используется для отправки данных клиенту. Все методы данного инструмента служат именно этой цели: + `String getCharacterEncoding()` - возвращает MIME тип кодировки (к примеру - UTF8), в которой будет выдаваться информация; + `void setLocale(Locale locale)`/`Locale getLocale()` - указывают на язык используемый в документе; + `ServletOutputStream getOutputStream()`/`PrintWriter getWriter()` - возвращают потоки вывода данных; + `void setContentLength(int len)` - устанавливает значение поля HTTP заголовка _Content-Length_; + `void setContentType(String type)` - устанавливает значение поля HTTP заголовка _Content-Type_. + `void reset()` - позволяет сбрасить HTTP заголовок к значениям по-умолчанию, если он ещё не был отправлен + и др. [к оглавлению](#servlets-jsp-jstl) ## Для чего нужен интерфейс `ServletRequest`? Интерфейс `ServletRequest` используется для получения параметров соединения, запроса, а также заголовков, входящего потока данных и т.д. [к оглавлению](#servlets-jsp-jstl) ## Что такое `Request Dispatcher`? Интерфейс `RequestDispatcher` используется для передачи запроса другому ресурсу, при этом существует возможность добавления данных полученных из этого ресурса к собственному ответу сервлета. Так же этот интерфейс используется для внутренней коммуникации между сервлетами в одном контексте. В интерфейсе объявлено два метода: + `void forward(ServletRequest var1, ServletResponse var2)` — передает запрос из сервлета к другому ресурсу (сервлету, JSP или HTML файлу) на сервере. + `void include(ServletRequest var1, ServletResponse var2)` — включает контент ресурса (сервлет, JSP или HTML страница) в ответ. Доступ к интерфейсу можно получить с помощью метода интерфейса `ServletContext` - `RequestDispatcher getRequestDispatcher(String path)`, где путь начинающийся с `/`, интерпретируется относительно текущего корневого пути контекста. [к оглавлению](#servlets-jsp-jstl) ## Как из одного сервлета вызвать другой сервлет? Для вызова сервлета из того же приложения необходимо использовать механизм внутренней коммуникации сервлетов (_inter-servlet communication mechanisms_) через вызовы методов `RequestDispatcher`: + `forward()` - передаёт выполнение запроса в другой сервлет; + `include()` - предоставляет возможность включить результат работы другого сервлета в возвращаемый ответ. Если необходимо вызывать сервлет принадлежащий другому приложению, то использовать `RequestDispatcher` уже не получится, т.к. он определен только для текущего приложения. Для подобных целей необходимо использовать метод `ServletResponse` - `sendRedirect()` которому предоставляется полный URL другого сервлета. Для передачи данных между сервлетами можно использовать `cookies`. [к оглавлению](#servlets-jsp-jstl) ## Чем отличается `sendRedirect()` от `forward()`? __`forward()`__: + Выполняется на стороне сервера; + Запрос перенаправляется на другой ресурс в пределах того же сервера; + Не зависит от протокола клиентского запроса, так как обеспечивается контейнером сервлетов; + Нельзя применять для внедрения сервлета в другой контекст; + Клиент не знает о фактически обрабатываемом ресурсе и URL в строке остается прежним; + Выполняется быстрее метода `sendRedirect()`; + Определён в интерфейсе `RequestDispatcher`. __`sendRedirect()`__: + Выполняется на стороне клиента; + Клиенту возвращается ответ `302 (redirect)` и запрос перенаправляется на другой сервер; + Может использоваться только с клиентами HTTP; + Разрешается применять для внедрения сервлета в другой контекст; + URL адрес изменяется на адрес нового ресурса; + Медленнее `forward()` т.к. требует создания нового запроса; + Определён в интерфейсе `HttpServletResponse`. [к оглавлению](#servlets-jsp-jstl) ## Для чего используются атрибуты сервлетов и как происходит работа с ними? Атрибуты сервлетов используются для внутренней коммуникации сервлетов. В веб-приложении существует возможность работы с атрибутами используя методы `setAttribute()`, `getAttribute()`, `removeAttribute()`, `getAttributeNames()`, которые предоставлены интерфейсами `ServletRequest`, `HttpSession` и `ServletContext` (для областей видимости _request_, _session_, _context_ соответственно). [к оглавлению](#servlets-jsp-jstl) ## Каким образом можно допустить в сервлете deadlock? Можно получить блокировку, например, допустив циклические вызовы метода `doPost()` в методе `doGet()` и метода `doGet()` в методе `doPost()`. [к оглавлению](#servlets-jsp-jstl) ## Как получить реальное расположение сервлета на сервере? Реальный путь к расположению сервлета на сервере можно получить из объекта `ServletContext`: `getServletContext().getRealPath(request.getServletPath())`. [к оглавлению](#servlets-jsp-jstl) ## Как получить информацию о сервере из сервлета? Информацию о сервере можно получить из объекта `ServletContext`: `getServletContext().getServerInfo()`. [к оглавлению](#servlets-jsp-jstl) ## Как получить IP адрес клиента на сервере? IP адрес клиента можно получить вызвав `request.getRemoteAddr()`. [к оглавлению](#servlets-jsp-jstl) ## Какие классы-обертки для сервлетов вы знаете? Собственные обработчики `ServletRequest` и `ServletResponse` можно реализовать добавив новые или переопределив существующие методы у классов-обёрток `ServletRequestWrapper` (`HttpServletRequestWrapper`) и `ServletResponseWrapper` (`HttpServletRequestWrapper`). [к оглавлению](#servlets-jsp-jstl) ## В чем отличия `GenericServlet` и `HttpServlet`? Абстрактный класс `GenericServlet` — независимая от используемого протокола реализация интерфейса `Servlet`, а абстрактный класс `HttpServlet` в свою очередь расширяет `GenericServlet` для протокола HTTP.. [к оглавлению](#servlets-jsp-jstl) ## Почему `HttpServlet` класс объявлен как абстрактный? Класс `HTTPServlet` предоставляет лишь общую реализацию сервлета для HTTP протокола. Реализация ключевых методов `doGet()` и `doPost()`, содержащих основную бизнес-логику перекладывается на разработчика и по умолчанию возвращает `HTTP 405 Method Not Implemented error`. [к оглавлению](#servlets-jsp-jstl) ## Какие основные методы присутствуют в классе `HttpServlet`? + `doGet()` - для обработки HTTP запросов `GET`; + `doPost()` - для обработки HTTP запросов `POST`; + `doPut()` - для обработки HTTP запросов `PUT`; + `doDelete()` - для обработки HTTP запросов `DELETE`; + `doHead()` - для обработки HTTP запросов `HEAD`; + `doOptions()` - для обработки HTTP запросов `OPTIONS`; + `doTrace()` - для обработки HTTP запросов `TRACE`. [к оглавлению](#servlets-jsp-jstl) ## Стоит ли волноваться о многопоточной безопасности работая с сервлетами? Методы `init()` и `destroy()` вызываются один раз за жизненный цикл сервлета — поэтому по поводу них беспокоиться не стоит. Методы `doGet()`, `doPost()`, `service()` вызываются на каждый запрос клиента и т.к. сервлеты используют многопоточность, то здесь задумываться о потокобезопасной работе обязательноЮ при этом правила использования многопоточности остаются теми же: локальные переменные этих методов будут созданы отдельно для каждого потока, а при использовании глобальных разделяемых ресурсов необходимо использовать синхронизацию или другие приёмы многопоточного программирования. [к оглавлению](#servlets-jsp-jstl) ## Какой метод HTTP не является неизменяемым? HTTP метод называется неизменяемым, если он на один и тот же запрос всегда возвращает одинаковый результат. HTTP методы `GET`, `PUT`, `DELETE`, `HEAD` и `OPTIONS` являются неизменяемыми, поэтому необходимо реализовывать приложение так, чтобы эти методы возвращали одинаковый результат постоянно. К изменяемым методам относится метод `POST`, который и используется для реализации чего-либо, что изменяется при каждом запросе. К примеру, для доступа к статической HTML странице используется метод `GET`, т.к. он всегда возвращает одинаковый результат. При необходимости сохранять какую-либо информацию, например в базе данных, нужно использовать `POST` метод. [к оглавлению](#servlets-jsp-jstl) ## Какие есть методы отправки данных с клиента на сервер? + `GET` - используется для запроса содержимого указанного ресурса, изображения или гипертекстового документа. Вместе с за просом могут передаваться дополнительные параметры как часть URI, значения могут выбираться из полей формы или передаваться непосредственно через URL. При этом запросы кэшируются и имеют ограничения на размер. Этот метод является основным методом взаимодействия браузера клиента и веб-сервера. + `POST` - используется для передачи пользовательских данных в содержимом HTTP-запроса на сервер. Пользовательские данные упакованы в тело запроса согласно полю заголовка Content-Type и/или включены в URI запроса. При использовании метода POST под URI подразумевается ресурс, который будет обрабатывать запрос. [к оглавлению](#servlets-jsp-jstl) ## В чем разница между методами `GET` и `POST`? + `GET` передает данные серверу используя URL, тогда как `POST` передает данные, используя тело HTTP запроса. Длина URL ограничена 1024 символами, это и будет верхним ограничением для данных, которые можно отослать через `GET`. `POST` может отправлять гораздо большие объемы данных. Лимит устанавливается web-server и составляет обычно около 2 Mb. + Передача данных методом `POST` более безопасна, чем методом `GET`, так как секретные данные (например пароль) не отображаются напрямую в web-клиенте пользователя, в отличии от URL, который виден почти всегда. Иногда это преимущество превращается в недостатком - вы не сможете послать данные за кого-то другого. + `GET`метод является неизменяемым, тогда как `POST` — изменяемый. [к оглавлению](#servlets-jsp-jstl) ## В чем разница между `PrintWriter` и `ServletOutputStream`? `PrintWriter` — класс для работы с символьным потоком, экземпляр которого можно получить через метод `ServletResponse` `getWriter()`; `ServletOutputStream` — класс для работы байтовым потоком. Для получения его экземпляра используется метод `ServletResponse` `getOutputStream()`. [к оглавлению](#servlets-jsp-jstl) ## Можно ли одновременно использовать в сервлете `PrintWriter` и `ServletOutputStream`? Так сделать не получится, т.к. при попытке одновременного вызова `getWriter()` и `getOutputStream()` будет выброшено исключение `java.lang.IllegalStateException` с сообщением, что уже был вызван другой метод. [к оглавлению](#servlets-jsp-jstl) ## Расскажите об интерфейсе `SingleThreadModel`. Интерфейс `SingleThreadModel` является маркерным - в нем не объявлен ни один метод, однако, если сервлет реализует этот интерфейс, то метод `service()` этого сервлета гарантированно не будет одновременно выполняться в двух потоках. Контейнер сервлетов либо синхронизирует обращения к единственному экземпляру, либо обеспечивает поддержку пула экземпляров и перенаправление запроса свободному сервлету. Другими словами, контейнер гарантирует отсутствие конфликтов при одновременном обращении к переменным или методам экземпляра сервлета. Однако существуют также и другие разделяемые ресурсы, которые даже при использовании этого интерфейса, остаются всё так же доступны обработчикам запросов в других потоках. Т.о. пользы от использования этого интерфейса немного и в спецификации Servlet 2.4 он был объявлен `deprecated`. [к оглавлению](#servlets-jsp-jstl) ## Что означает _URL encoding_? Как это осуществить в Java? __URL Encoding__ — процесс преобразования данных в форму CGI (Common Gateway Interface), не содержащую пробелов и нестандартных символов, которые заменяются в процессе кодирования на специальные escape-символы. В Java для кодирования строки используется метод `java.net.URLEncoder.encode(String str, String unicode)`. Обратная операция декодирования возможна через использование метода `java.net.URLDecoder.decode(String str, String unicode)`. > `Hello мир!` преобразовывается в `Hello%20%D0%BC%D0%B8%D1%80!`. [к оглавлению](#servlets-jsp-jstl) ## Какие различные методы управления сессией в сервлетах вы знаете? При посещении клиентом Web-ресурса и выполнении вариантов запросов, контекстная информация о клиенте не хранится. В протоколе HTTP нет возможностей для сохранения и изменения информации о предыдущих посещениях клиента. Сеанс (сессия) – соединение между клиентом и сервером, устанавливаемое на определенное время, за которое клиент может отправить на сервер сколько угодно запросов. Сеанс устанавливается непосредственно между клиентом и Web-сервером. Каждый клиент устанавливает с сервером свой собственный сеанс. Сеансы используются для обеспечения хранения данных во время нескольких запросов Web-страницы или на обработку информации, введенной в пользовательскую форму в результате нескольких HTTP-соединений (например, клиент совершает несколько покупок в интернет-магазине; студент отвечает на несколько тестов в системе дистанционного обучения). Существует несколько способов обеспечения уникального идентификатора сессии: + __User Authentication__ – Предоставление учетных данных самим пользователем в момент аутентификации. Переданная таким образом информация в дальнейшем используется для поддержания сеанса. Это метод не будет работать, если пользователь вошёл в систему одновременно из нескольких мест. + __HTML Hidden Field__ – Присвоение уникального значения скрытому полю HTML страницы, в момент когда пользователь начинает сеанс. Этот метод не может быть использован со ссылками, потому что нуждается в подтверждении формы со скрытым полем каждый раз во время формирования запроса. Кроме того, это не безопасно, т.к. существует возможность простой подмены такого идентификатора. + __URL Rewriting__ – Добавление идентификатора сеанса как параметра URL. Достаточно утомительная операция, потому что требует постоянного отслеживания этого идентификатора при каждом запросе или ответе. + __Cookies__ – Использование небольших фрагментов данных, отправленных web-сервером и хранимых на устройстве пользователя. Данный метод не будет работать, если клиент отключает использование cookies. + __Session Management API__ – Использование специального API для отслеживания сеанса, построенный на основе и на методах описанных выше и который решает частные проблемы перечисленных способов: + Чаще всего недостаточно просто отслеживать сессию, необходимо ещё и сохранять какие-либо дополнительные данные о ней, которые могут потребоваться при обработке последующих запросов. Осуществление такого поведения требует много дополнительных усилий. + Все вышеперечисленные методы не являются универсальными: для каждого из них можно подобрать конкретный сценарий, при котором они не будут работать. [к оглавлению](#servlets-jsp-jstl) ## Что такое _cookies_? __Сookies («куки»)__ — небольшой фрагмент данных, отправленный web-сервером и хранимый на устройстве пользователя. Всякий раз при попытке открыть страницу сайта, web-клиент пересылает соответствующие этому сайту cookies web-серверу в составе HTTP-запроса. Применяется для сохранения данных на стороне пользователя и на практике обычно используется для: + аутентификации пользователя; + хранения персональных предпочтений и настроек пользователя; + отслеживания состояния сеанса доступа пользователя; + ведения разнообразной статистики. [к оглавлению](#servlets-jsp-jstl) ## Какие методы для работы с cookies предусмотрены в сервлетах? Servlet API предоставляет поддержку cookies через класс `javax.servlet.http.Cookie`: + Для получения массива cookies из запроса необходимо воспользоваться методом `HttpServletRequest.getCookies()`. Методов для добавления cookies в `HttpServletRequest` не предусмотрено. + Для добавления cookie в ответ используется `HttpServletResponse.addCookie(Cookie c)`. Метода получения cookies в `HttpServletResponse` отсутствует. [к оглавлению](#servlets-jsp-jstl) ## Что такое _URL Rewriting_? __URL Rewriting__ - специальная перезапись (перекодирование) оригинального URL. Данный механизм может использоваться для управления сессией в сервлетах, когда _cookies_ отключены. [к оглавлению](#servlets-jsp-jstl) ## Зачем нужны и чем отличаются методы `encodeURL()` и `encodeRedirectURL()`? `HttpServletResponse.encodeURL()` предоставляет способ преобразования URL в HTML гиперссылку с преобразованием спецсимволов и пробелов, а так же добавления _session id_ к URL. Такое поведение аналогично `java.net.URLEncoder.encode()`, но с добавлением дополнительного параметра `jsessionid` в конец URL. Метод `HttpServletResponse.encodeRedirectURL()` преобразует URL для последующего использования в методе `sendRedirect()`. Таким образом для HTML гиперссылок при _URL rewriting_ необходимо использовать `encodeURL()`, а для URL при перенаправлении - `encodeRedirectUrl()`. [к оглавлению](#servlets-jsp-jstl) ## Что такое _«сессия»_? __Сессия__ - это сеанс связи между клиентом и сервером, устанавливаемый на определенное время. Сеанс устанавливается непосредственно между клиентом и веб-сервером в момент получения первого запроса к веб-приложению. Каждый клиент устанавливает с сервером свой собственный сеанс, который сохраняется до окончания работы с приложением. [к оглавлению](#servlets-jsp-jstl) ## Как уведомить объект в сессии, что сессия недействительна или закончилась? Чтобы быть уверенным в том, что объект будет оповещён о прекращении сессии, нужно реализовать интерфейс `javax.servlet.http.HttpSessionBindingListener`. Два метода этого интерфейса: `valueBound()` и `valueUnbound()` используются при добавлении объекта в качестве атрибута к сессии и при уничтожении сессии соответственно. [к оглавлению](#servlets-jsp-jstl) ## Какой существует эффективный способ удостоверится, что все сервлеты доступны только для пользователя с верной сессией? Сервлет фильтры используются для перехвата всех запросов между контейнером сервлетов и сервлетом. Поэтому логично использовать соответствующий фильтр для проверки необходимой информации (например валидности сессии) в запросе. [к оглавлению](#servlets-jsp-jstl) ## Как мы можем обеспечить _transport layer security_ для нашего веб приложения? Для обеспечения _transport layer security_ необходимо настроить поддержку SSL сервлет контейнера. Как это сделать зависит от конкретной реализации сервлет-контейнера. [к оглавлению](#servlets-jsp-jstl) ## Как организовать подключение к базе данных, обеспечить журналирование в сервлете? При работе с большим количеством подключений к базе данных рекомендуется инициализировать их в _servlet context listener_, а также установить в качестве атрибута контекста для возможности использования другими сервлетами. Журналирование подключается к сервлету стандартным для логгера способом (например для _log4j_ это может быть property-файл или XML-конфигурация) , а далее эта информация используется при настройке соответствующего _context listener_. [к оглавлению](#servlets-jsp-jstl) ## Какие основные особенности появились в спецификации _Servlet 3_? + __Servlet Annotations__. До Servlet 3 вся конфигурация содержалась в `web.xml`, что приводило к ошибкам и неудобству при работе с большим количестве сервлетов. Примеры аннотаций: `@WebServlet`, `@WebInitParam`, `@WebFilter`, `@WebListener`. + __Web Fragments__. Одностраничное веб приложение может содержать множество модулей: все модули прописываются в `fragment.xml` в папке `META-INF\`. Это позволяет разделять веб приложение на отдельные модули, собранные как .jar-файлы в отдельной `lib\` директории. + __Динамическое добавление веб компонентов__. Появилась возможность программно добавлять фильтры и слушатели, используя `ServletContext` объект. Для этого применяются методы `addServlet()`, `addFilter()`, `addListener()`. Используя это нововведение стало доступным построение динамической системы, в которой необходимый объект будет создан и вызван только по необходимости. + __Асинхронное выполнение__. Поддержка асинхронной обработки позволяет передать выполнение запроса в другой поток без удержания всего сервера занятым. [к оглавлению](#servlets-jsp-jstl) ## Какие способы аутентификации доступны сервлету? Спецификация сервлетов определяет четыре типа проверки подлинности: + __HTTP Basic Authentication__ - `BASIC`. При доступе к закрытым ресурсам появится окно, которое попросит ввести данные для аутентификации. + __Form Based Login__ - `FORM`. Используется собственная html форма: + __HTTP Digest Authentication__ - `DIGEST`. Цифровая аутентификация с шифрованием. + __HTTPS Authentication__ - `CLIENT-CERT`. Аутентификация с помощью клиентского сертификата. ```xml FORM /login.html /error.html ``` [к оглавлению](#servlets-jsp-jstl) ## Что такое _Java Server Pages (JSP)_? __JSP (JavaServer Pages)__ — платформонезависимая переносимая и легко расширяемая технология разработки веб-приложений, позволяющая веб-разработчикам создавать содержимое, которое имеет как статические, так и динамические компоненты. Страница JSP содержит текст двух типов: статические исходные данные, которые могут быть оформлены в одном из текстовых форматов HTML, SVG, WML, или XML, и _JSP-элементы_, которые конструируют динамическое содержимое. Кроме этого могут использоваться _библиотеки JSP-тегов_, а также _EL (Expression Language)_, для внедрения Java-кода в статичное содержимое JSP-страниц. Код JSP-страницы транслируется в Java-код сервлета с помощью компилятора JSP-страниц _Jasper_, и затем компилируется в байт-код JVM. JSP-страницы загружаются на сервере и управляются Java EE Web Application. Обычно такие страницы упакованы в файловые архивы .war и .ear. [к оглавлению](#servlets-jsp-jstl) ## Зачем нужен JSP? JSP расширяет технологию сервлетов обеспечивая возможность создания динамических страницы с HTML подобным синтаксисом. Хотя создание представлений поддерживается и в сервлетах, но большая часть любой веб-страницы является статической, поэтому код сервлета в таком случае получается чересчур перегруженным, замусоренным и поэтому при его написании легко допустить ошибку. Еще одним преимуществом JSP является горячее развертывание - возможность заменить одну страницу на другую непосредственно в контейнере без необходимости перекомпилировать весь проект или перезапускать сервер. Однако рекомендуется избегать написания серьёзной бизнес-логики в JSP и использовать страницу только в качестве представления. [к оглавлению](#servlets-jsp-jstl) ## Опишите, как обрабатываются JSP страницы, начиная от запроса к серверу, заканчивая ответом пользователю. Когда пользователь переходит по ссылке на страницу `page.jsp`, он отправляет http-запрос на сервер `GET /page.jsp`. Затем, на основе этого запроса и текста самой страницы, сервер генерирует java-класс, компилирует его и выполняет полученный сервлет, формирующий ответ пользователю в виде представления этой страницы, который сервер и перенаправляет обратно пользователю. [к оглавлению](#servlets-jsp-jstl) ## Расскажите об этапах (фазах) жизненного цикла JSP. Если посмотреть код внутри созданной JSP страницы, то он будет выглядеть как HTML и не будет похож на java класс. Конвертацией JSP страниц в HTML код занимается контейнер, который так же создает и сервлет для использования в веб приложении. Жизненный цикл JSP состоит из нескольких фаз, которыми руководит JSP контейнер: + __Translation__ – проверка и парсинг кода JSP страницы для создания кода сервлета. + __Compilation__ – компиляция исходного кода сервлета. + __Class Loading__ – загрузка скомпилированного класса в память. + __Instantiation__ – внедрение конструктора без параметра загруженного класса для инициализации в памяти. + __Initialization__ – вызов `init()` метода объекта JSP класса и инициализация конфигурации сервлета с первоначальными параметрами, которые указаны в дескрипторе развертывания (`web.xml`). После этой фазы JSP способен обрабатывать запросы клиентов. Обычно эти фазы происходят после первого запроса клиента (т.е. ленивая загрузка), но можно настроить загрузку и инициализацию JSP на старте приложения по аналогии с сервлетами. + __Request Processing__ – длительный жизненный цикл обработки запросов клиента JSP страницей. Обработка является многопоточной и аналогична сервлетам — для каждого запроса создается новый поток, объекты `ServletRequest` и `ServletResponse`, происходит выполнение сервис методов. + __Destroy__ – последняя фаза жизненного цикла JSP, на которой её класс удаляется из памяти. Обычно это происходит при выключении сервера или выгрузке приложения. [к оглавлению](#servlets-jsp-jstl) ## Расскажите о методах жизненного цикла JSP. Контейнер сервлетов (например, Tomcat, GlassFish) создает из JSP-страницы класс сервлета, наследующего свойства интерфейса `javax.servlet.jsp.HttpJspBase` и включающего следующие методы: + `jspInit()` — метод объявлен в JSP странице и реализуется с помощью контейнера. Этот метод вызывается один раз в жизненном цикле JSP для того, чтобы инициализировать конфигурационные параметры указанные в дескрипторе развертывания. Этот метод можно переопределить с помощью определения элемента _JSP scripting_ и указания необходимых параметров для инициализации; + `_jspService()` — метод переопределяется контейнером автоматически и соответствует непосредственно коду JSP, описанному на странице. Этот метод определен в интерфейсе `HttpJspPage`, его имя начинается с нижнего подчеркивания и он отличается от других методов жизненного цикла тем, что его невозможно переопределить; + `jspDestroy()` — метод вызывается контейнером для удаления объекта из памяти (на последней фазе жизненного цикла JSP - Destroy). Метод вызывается только один раз и доступен для переопределения, предоставляя возможность освободить ресурсы, которые были созданы в `jspInit()`. [к оглавлению](#servlets-jsp-jstl) ## Какие методы жизненного цикла JSP могут быть переопределены? Возможно переопределить лишь `jspInit()` и `jspDestroy()` методы. [к оглавлению](#servlets-jsp-jstl) ## Как можно предотвратить прямой доступ к JSP странице из браузера? Прямой доступ к директории `/WEB-INF/` из веб-приложения отсутствует. Поэтому JSP-страницы можно расположить внутри этой папки и тем самым запретить доступ к странице из браузера. Однако, по аналогии с описанием сервлетов, будет необходимо настроить дескриптор развертывания: ```xml Example /WEB-INF/example.jsp exampleParameter parameterValue Example /example.jsp ``` [к оглавлению](#servlets-jsp-jstl) ## Какая разница между _динамическим_ и _статическим_ содержимым JSP? Статическое содержимое JSP (HTML, код JavaScript, изображения и т.д.) не изменяется в процессе работы веб приложения. Динамические ресурсы созданы для того, чтобы отображать свое содержимое в зависимости от пользовательских действий. Обычно они представлены в виде выражений EL (Expression Language), библиотек JSP-тегов и пр. [к оглавлению](#servlets-jsp-jstl) ## Как закомментировать код в JSP? + `` такие комментарии будут видны клиенту при просмотре кода страницы. + `<%—- JSP комментарий; не отображается на странице JSP —-%>` такие комментарии описываются в созданном сервлете и не посылаются клиенту. Для любых комментариев по коду или отладочной информации необходимо использовать именно такой тип комментариев. [к оглавлению](#servlets-jsp-jstl) ## Какие существуют основные типы тегов JSP? + _Выражение JSP_: `<%= expression %>` - выражение, которое будет обработано с перенаправлением результата на вывод; + _Скриплет JSP_: `<% code %>` - код, добавляемый в метод `service()`. + _Объявление JSP_: `<%! code %>` - код, добавляемый в тело класса сервлета вне метода `service()`. + _Директива JSP page_: `<%@ page att="value" %>` - директивы для контейнера сервлетов с информацией о параметрах. + _Директива JSP include_: `<%@ include file="url" %>` - файл в локальной системе, подключаемый при трансляции JSP в сервлет. + _Комментарий JSP_: `<%-- comment --%>` - комментарий; игнорируется при трансляции JSP страницы в сервлет. [к оглавлению](#servlets-jsp-jstl) ## Что вы знаете о действиях JSP (_Action tag_ и _JSP Action Elements_). __Action tag__ и __JSP Action Elements__ предоставляют методы работы с Java Beans, подключения ресурсов, проброса запросов и создания динамических XML элементов. Такие элементы всегда начинаются с записи `jsp:` и используются непосредственно внутри страницы JSP без необходимости подключения сторонних библиотек или дополнительных настроек. Наиболее часто используемыми JSP Action Elements являются: + `jsp:include`: `` - подключить файл при запросе страницы. Если необходимо, чтобы файл подключался в процессе трансляции страницы, то используется директива `page` совместно с атрибутом `include`; + `jsp:useBean`: `` или `...` - найти или создать Java bean; + `jsp:setProperty`: `` - установить свойства Java bean, или явно, или указанием на соответствующее значение, передаваемое при запросе; + `jsp:forward`: `` - передать запрос другой странице; + `jsp:plugin`: `...` - сгенерировать (в зависимости от типа браузера) тэги `OBJECT` или `EMBED` для апплета, использующего технологию Java Plugin. [к оглавлению](#servlets-jsp-jstl) ## Взаимодействие _JSP - сервлет - JSP_. _«JSP - сервлет - JSP»_ архитектура построения приложений носит название _MVC (Model/View/Controller)_: + _Model_ - классы данных и бизнес-логики; + _View_ - страницы JSP; + _Controller_ - сервлеты. [к оглавлению](#servlets-jsp-jstl) ## Какие области видимости переменных существуют в JSP? Область видимости объектов определяется тем контекстом в который помещается данный объект. В зависимости от той или иной области действия так же определяется время существования объекта. В JSP предусмотрены следующие области действия переменных (объектов): + `request` область действия запроса - объект будет доступен на текущей JSP странице, странице пересылки (при использовании `jsp:forward`) или на включаемой странице (при использовании `jsp:include`); + `session` область действия сессии - объект будет помещен в сеанс пользователя, будет доступен на всех JSP страницах и будет существовать пока существует сессия пользователя, или он не будет из нее принудительно удален. + `application` область действия приложения - объект будет доступен для всех пользователей на всех JSP страницах и будет существовать на протяжении всей работы приложения или пока не будет удален принудительно и контекста приложения. + `page` область действия страницы - объект будет доступен только на той странице, где он определен. На включаемых (`jsp:include`) и переадресуемых (`jsp:forward`) страницах данный объект уже не будет доступен. Таким образом, чтобы объект был доступен всем JSP страницам, необходимо указать область видимости `application` или `session`, в зависимости от того требуется ли доступ к объекту всем пользователям или только текущему. Для указания требуемой области действия при определении объекта на JSP странице используется атрибут scope тега `jsp:useBean`: ``` ``` Если не указывать атрибут `scope`, то по умолчанию задается область видимости страницы `page` [к оглавлению](#servlets-jsp-jstl) ## Какие неявные, внутренние объекты и методы есть на JSP странице? __JSP implicit objects (неявные объекты)__ создаются контейнером при конвертации JSP страницы в код сервлета для помощи разработчикам. Эти объекты можно использовать напрямую в скриптлетах для передачи информации в сервис методы, однако мы не можем использовать неявные объекты в JSP Declaration, т.к. такой код пойдет на уровень класса. Существует 9 видов неявных объектов, которые можно использовать прямо на JSP странице. Семь из них объявлены как локальные переменные в начале `_jspService()` метода, а два оставшихся могут быть использованы как аргументы метода `_jspService()`. + `out Object` : ``` Current Time is: <% out.print(new Date()); %>
``` + `request Object` : ``` Request User-Agent: <%=request.getHeader("User-Agent") %>
``` + `response Object` : ``` Response: <%response.addCookie(new Cookie("Test","Value")); %> ``` + `config Object` : ``` User init param value: <%=config.getInitParameter("User") %>
``` + `application Object` : ``` User context param value: <%=application.getInitParameter("User") %>
``` + `session Object` : ``` User Session ID: <%=session.getId() %>
``` + `pageContext Object` : ``` <% pageContext.setAttribute("Test", "Test Value"); %> PageContext attribute: {Name="Test",Value="<%=pageContext.getAttribute("Test") %>"}
``` + `page Object` : ``` Generated Servlet Name: <%=page.getClass().getName() %> ``` + `exception Object` : ``` Exception occured: <%=exception %>
``` [к оглавлению](#servlets-jsp-jstl) ## Какие неявные объекты не доступны в обычной JSP странице? Неявный объект исключений JSP недоступен в обычных JSP страницах и используется на страницах ошибок JSP (_errorpage_) только для того, чтобы перехватить исключение, выброшенное JSP страницей и далее предоставить какую-либо полезную информацию клиенту. [к оглавлению](#servlets-jsp-jstl) ## Что вы знаете о `PageContext` и какие преимущества его использования? Неявный объект JSP - экземпляр класса `javax.servlet.jsp.PageContext` предоставляет доступ ко всем пространствам имён, ассоциированным с JSP-страницей, а также к различным её атрибутам. Остальные неявные объекты добавляются к `pageContext` автоматически. Класс `PageContext` это абстрактный класс, а его экземпляр можно получить через вызов метода `JspFactory.getPageContext()`, и освободить через вызов метода `JspFactory.releasePageContext()`. `PageContext` обладает следующим набором особенностей и возможностей: + единый API для обслуживания пространств имён различных областей видимости; + несколько удобных API для доступа к различным `public`-объектам; + механизм получения `JspWriter` для вывода; + механизм обслуживания использования сессии страницей; + механизм экспонирования («показа») атрибутов директивы `page` среде скриптинга; + механизмы направления или включения текущего запроса в другие компоненты приложения; + механизм обработки процессов исключений на страницах ошибок _errorpage_; [к оглавлению](#servlets-jsp-jstl) ## Как сконфигурировать параметры инициализации для JSP? Параметры инициализации для JSP задаются в `web.xml` файле аналогично сервлетам - элементами `servlet` и `servlet-mapping`. Единственным отличием будет указание местонахождения JSP страницы: ```xml Example /WEB-INF/example.jsp exampleParameter parameterValue ``` [к оглавлению](#servlets-jsp-jstl) ## Почему не рекомендуется использовать скриплеты (скриптовые элементы) в JSP? JSP страницы используются в основном для целей отображения представления (_view_), а вся бизнес-логика (_controller_) и модель (_model_) должны быть реализованы в сервлетах или классах-моделях. Обязанность JSP страницы - создание HTML ответа из переданных через атрибуты параметров. Большая часть JSP содержит HTML код а для того, чтобы помочь верстальщикам понять JSP код страницы предоставляется функционал элементов _action_, _JSP EL_, _JSP Standart Tag Library_. Именно их и необходимо использовать вместо скриптлетов для создания моста между (JSP)HTML и (JSP)Java частями. [к оглавлению](#servlets-jsp-jstl) ## Можно ли определить класс внутри JSP страницы? Определить класс внутри JSP страницы можно, но это считается плохой практикой: ```java <%! private static class ExampleOne { //... } %> <% private class ExampleTwo { //... } %> ``` [к оглавлению](#servlets-jsp-jstl) ## Что вы знаете о Языке выражений JSP (JSP Expression Language – EL)? __JSP Expression Language (EL)__ — скриптовый язык выражений, который позволяет получить доступ к Java компонентам (JavaBeans) из JSP. Начиная с JSP 2.0 используется внутри JSP тегов для отделения Java кода от JSP для обеспечения лёгкого доступа к Java компонентам, уменьшая при этом количество кода Java в JSP-страницах, или даже полностью исключая его. Развитие EL происходило с целью сделать его более простым для дизайнеров, которые имеют минимальные познания в языке программирования Java. До появления языка выражений, JSP имел несколько специальных тегов таких как скриптлеты (англ.), выражения и т. п. которые позволяли записывать Java код непосредственно на странице. С использованием языка выражений веб-дизайнер должен знать только то, как организовать вызов соответствующих java-методов. Язык выражений JSP 2.0 включает: + Создание и изменение переменных. + Управление потоком выполнения программы: ветвление, выполнение различных типов итераций и т.д. + Упрощенное обращение к встроенным JSP-объектам. + Возможность создавать собственные функции. Язык выражений используется внутри конструкции `${ ... }`. Подобная конструкция может размещаться либо отдельно, либо в правой части выражения установки атрибута тега. [к оглавлению](#servlets-jsp-jstl) ## Какие типы EL операторов вы знаете? Операторы в EL поддерживают наиболее часто используемые манипуляции данными. Типы операторов: + Стандартные операторы отношения: `==` (или `eq`), `!=` (или `neq`), `<` (или `lt`), `>` (или `gt`), `<=` (или `le`), `>=` (или `ge`). + Арифметические операторы: `+`, `–`, `*`, `/` (или `div`), `%` (или `mod`). + Логические операторы: `&&` (или `and`), `||` (или `or`), `!` (или `not`). + Оператор `empty` – используется для проверки переменной на `null`, или «пустое значение», который зависит от типа проверяемого объекта. Например, нулевая длина для строки или нулевой размер для коллекции. [к оглавлению](#servlets-jsp-jstl) ## Назовите неявные, внутренние объекты JSP EL и их отличия от объектов JSP. Язык выражений JSP предоставляет множество неявных объектов, которые можно использовать для получения атрибутов в различных областях видимости (scopes) и для значений параметров. Важно отметить, что они отличаются от неявных объектов JSP и содержат атрибуты в заданной области видимости. Наиболее часто использующийся implicit object в JSP EL и JSP page — это объект pageContext. Ниже представлена таблица неявных объектов JSP EL. [к оглавлению](#servlets-jsp-jstl) ## Как отключить возможность использования EL в JSP? Для игнорирования выполнения языка выражений на странице существует два способа: + использовать директиву `<%@ page isELIgnored = «true» %>`, + настроить `web.xml` (лучше подходит для отключения EL сразу на нескольких страницах): ```xml *.jsp true ``` [к оглавлению](#servlets-jsp-jstl) ## Как узнать тип HTTP метода используя JSP EL? `${pageContext.request.method}`. [к оглавлению](#servlets-jsp-jstl) ## Что такое _JSTL (JSP Standard tag library)_? __JavaServer Pages Standard Tag Library, JSTL, Стандартная библиотека тегов JSP__ — расширение спецификации JSP (конечный результат _JSR 52_), добавляющее библиотеку JSP тегов для общих нужд, таких как разбор XML данных, условная обработка, создание циклов и поддержка интернационализации. JSTL является альтернативой такому виду встроенной в JSP логики, как _скриплеты_ (прямые вставки Java кода). Использование стандартизованного множества тегов предпочтительнее, поскольку получаемый код легче поддерживать и проще отделять бизнес-логику от логики отображения. Для использования JSTL тегов необходимо: + подключить зависимости, например в `pom.xml`: ```xml jstl jstl 1.2 taglibs standard 1.1.2 ``` + указать пространство имен основных тегов JSTL через указание на JSP странице код: ``` <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> ``` [к оглавлению](#servlets-jsp-jstl) ## Из каких групп тегов состоит библиотека _JSTL_? Группы тегов JSTL согласно их функциональности: + _Core Tags_ предоставляют возможности итерации, обработки исключений, URL, _forward_, _redirect response_ и т.д. + _Formatting Tags_ и _Localization Tags_ предоставляют возможности по форматированию чисел, дат и поддержки _i18n_ локализации и _resource bundles_. + _SQL Tags_ – поддержка работы с базами данных. + _XML Tags_ используются для работы с XML документами: парсинга, преобразования данных, выполнения выражений _XPath_ и т.д.. + _JSTL Functions Tags_ предоставляет набор функций, которые позволяют выполнять различные операции со строками и т.п. Например, по конкатенации или разбиению строк. [к оглавлению](#servlets-jsp-jstl) ## Какая разница между `` и ``? Оба тега создают и помещают экземпляры в заданную область видимости, но `` только создаёт экземпляр конкретного типа, а ``, создав экземпляр, позволяет дополнительно извлекать значение, например, из параметров запроса, сессии и т. д. [к оглавлению](#servlets-jsp-jstl) ## Чем отличается `` от `` и директивы `<%@include %>`? По сравнению с action-тегом `` и директивой `<%@include %>` тег `` обеспечивает более совершенное включение динамических ресурсов, т.к. получает доступ к источнику, чтение информации из которого происходит непосредственно без буферизации и контент включается в исходную JSP построчно. [к оглавлению](#servlets-jsp-jstl) ## Как можно расширить функциональность JSP? ## Что вы знаете о написании пользовательских JSP тегов? ## Приведите пример использования собственных тегов. JSP можно расширить с помощью создания собственных тегов с необходимой функциональностью, которые можно добавить в библиотеку тегов на страницу JSP указав необходимое пространство имен. > /WEB-INF/exampleTag.tld ```xml 1.0 example /WEB-INF/exampleTag exampleTag xyz.company.ExampleTag empty The example tag displays Hello World! ``` > xyz.company.ExampleServlet.java ```java package xyz.company; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; public class ExampleTag extends TagSupport{ private static final long serialVersionUID = 1L; @Override public int doStartTag() throws JspException { try { pageContext.getOut().print("Hello World!"); } catch(IOException ioException) { throw new JspException("Error: " + ioException.getMessage()); } return SKIP_BODY; } } ``` > exampleTag.jsp ``` <%@ taglib uri="/WEB-INF/exampleTag.tld" prefix="example"%> <%@ page session="false" pageEncoding="UTF-8"%> Example Tag

Example Tag

``` Также в пользовательских тегах существует возможность задать входные параметры. Например, существует необходимость отформатировать каким-либо стилем очень длинное число. Для этого можно использовать собственный тег по типу: `` Используя входные параметры, число должно быть преобразовано на JSP странице в таком виде `123,456.79` согласно шаблону. Т.к. JSTL не предоставляет такой функциональности, необходимо создать пользовательский тег для получения необходимого результата. [к оглавлению](#servlets-jsp-jstl) ## Как сделать перенос строки в HTML средствами JSP? Для переноса строки можно использовать тег `c:out` и атрибут `escapeXml`, который отключает обработку HTML элементов. В этом случае браузер получит следующий код в виде строки и обработает элемент `
` как требуется: `` [к оглавлению](#servlets-jsp-jstl) ## Почему не нужно конфигурировать стандартные JSP теги в `web.xml`? Стандартные теги JSP не конфигурируются в `web.xml`, потому что tld файлы уже находятся внутри каталога `/META-INF/` в jar файлах JSTL. Когда контейнер загружает веб-приложение и находит tld файлы в в jar файле в директории `/META-INF/`, то он автоматически настраивает их для непосредственного использования на JSP страницах. Остается только задать пространство имен на JSP странице. [к оглавлению](#servlets-jsp-jstl) ## Как можно обработать ошибки JSP страниц? Для обработки исключений выброшенных на JSP странице достаточно лишь задать страницу ошибки JSP и при её создании установить значение _page directive attribute_ `isErrorPage` в значение `true`. Таким образом будет предоставлен доступ к неявным объектам исключений в JSP и появится возможность передавать собственные, более информативные сообщения об ошибках клиенту. При этом настройка дескриптора развертывания выглядит так: ```xml 404 /error.jsp java.lang.Throwable /error.jsp ``` [к оглавлению](#servlets-jsp-jstl) ## Как происходит обработка ошибок с помощью JSTL? Для перехвата и обработки исключений в служебных методах класса служат JSTL Core Tags `c:catch` и `c:if`. > Тег `c:catch` перехватывает исключение и обертывает его в переменную `exception`, доступную для обработки в теге `c:if`: ``` <% int x = 42/0;%>

Exception is : ${exception}
Exception Message: ${exception.message}

``` Обратите внимание что используется язык выражений JSP EL в теге `c:if`. [к оглавлению](#servlets-jsp-jstl) ## Как конфигурируется JSP в дескрипторе развертывания. Для настройки различных параметров JSP страниц используется элемент `jsp-config`, который отвечает за: + управление элементами скриптлетов на странице; + управления выполнением в языке выражений; + определение шаблона URL для encoding; + определение размера буфера, который используется для объектов на странице; + обозначение групп ресурсов, соответствующих шаблону URL, которые должны быть обработаны как XML документ. ```xml http://company.xyz/jsp/tlds/customtags /WEB-INF/exampleTag.tld ``` [к оглавлению](#servlets-jsp-jstl) ## Можно ли использовать Javascript на JSP странице? Да, это возможно. Несмотря на то, что JSP это серверная технология, на выходе она всё равно создает `HTML` страницу, на которую можно добавлять Javascript и CSS. [к оглавлению](#servlets-jsp-jstl) ## Всегда ли создается объект сессии на JSP странице, можно ли отключить его создание? Jsp-страница, по умолчанию, всегда создает сессию. Используя директиву `page` с атрибутом `session` можно изменить это поведение: `<%@ page session ="false" %>` [к оглавлению](#servlets-jsp-jstl) ## Какая разница между `JSPWriter` и сервлетным `PrintWriter`? `PrintWriter` является объектом отвечающим за запись содержания ответа на запрос. `JspWriter` использует объект `PrintWriter` для буферизации. Когда буфер заполняется или сбрасывается, `JspWriter` использует объект `PrintWriter` для записи содержания в ответ. [к оглавлению](#servlets-jsp-jstl) ## Опишите общие практические принципы работы с JSP. Хорошей практикой работы с технологией JSP является соблюдение следующих правил: + Следует избегать использования элементов скриптлетов на странице. Если элементы _action_, _JSTL_, _JSP EL_ не удовлетворяют потребностям, то желательно написать собственный тег. + Рекомендуется использовать разные виды комментариев: так JSP комментарии необходимы для уровня кода и отладки, т.к. они не будут показаны клиенту. + Не стоит размещать какой-либо бизнес логики внутри JSP страницы. Страницы должны использоваться только для создания ответов клиенту. + Для повышения производительности лучше отключать создание сессии на странице, когда это не требуется. + Директивы `taglib`, `page` в начале JSP страницы улучшают читабельность кода. + Следует правильно использовать директиву `include` и элемент `jsp:include action`. Первая используется для статических ресурсов, а второй для динамических ресурсов времени выполнения. + Обработку исключений нужно производить с помощью страниц ошибок. Это помогает избегать запуска специальных служебных методов и может повысить производительность. + Использующиеся CSS и JavaScript должны быть разнесены в разные файлы и подключаться в начале страницы. + В большинстве случаев JSTL должно хватать для всех нужд. Если это не так, то в начале следует проанализировать логику своего приложения, и попробовать перенести выполнения кода в сервлет, а далее с помощью установки атрибутов использовать на JSP странице только результат. [к оглавлению](#servlets-jsp-jstl) # Источники + [javastudy.ru](http://javastudy.ru/interview/jee-servlet-api-questions/) + [java2ee.ru](http://www.java2ee.ru/servlets/) + [Java-online](http://java-online.ru/jsp-questions.xhtml) + [Codenet](http://www.codenet.ru/webmast/java/jsp.php) + [JavaTalks Articles](https://articles.javatalks.ru/articles/24) [Вопросы для собеседования](README.md)