1
1
Fork 0
java-interview/servlets.md

1360 lines
137 KiB
Markdown
Raw Normal View History

2017-10-21 06:14:08 +03:00
[Вопросы для собеседования](README.md)
2017-05-07 07:05:47 +03:00
2017-10-21 06:01:09 +03:00
# Servlets, JSP, JSTL
2017-05-07 07:05:47 +03:00
+ [Что такое _«сервлет»_?](#Что-такое-сервлет)
+ [В чем заключаются преимущества технологии сервлетов над CGI (Common Gateway Interface)?](#В-чем-заключаются-преимущества-технологии-сервлетов-над-cgi-common-gateway-interface)
+ [Какова структура веб-проекта?](#Какова-структура-веб-проекта)
+ [Что такое _«контейнер сервлетов»_?](#Что-такое-контейнер-сервлетов)
2019-05-18 10:46:47 +03:00
+ [Зачем нужны сервера приложений, если есть контейнеры сервлетов?](#Зачем-нужны-сервера-приложений-если-есть-контейнеры-сервлетов)
2017-05-07 07:05:47 +03:00
+ [Как контейнер сервлетов управляет жизненным циклом сервлета, когда и какие методы вызываются?](#Как-контейнер-сервлетов-управляет-жизненным-циклом-сервлета-когда-и-какие-методы-вызываются)
+ [Что такое _«дескриптор развертывания»_?](#Что-такое-дескриптор-развертывания)
+ [Какие действия необходимо проделать при создании сервлетов?](#Какие-действия-необходимо-проделать-при-создании-сервлетов)
+ [В каком случае требуется переопределять метод `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)
+ [Какая разница между `<c:set>` и `<jsp:useBean>`?](#Какая-разница-между-cset-и-jspusebean)
+ [Чем отличается `<c:import>` от `<jsp:include>` и директивы `<%@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)
2017-10-21 06:01:09 +03:00
## Что такое _«сервлет»_?
2017-05-07 07:05:47 +03:00
__Сервлет__ является интерфейсом, реализация которого расширяет функциональные возможности сервера. Сервлет взаимодействует с клиентами посредством принципа запрос-ответ. Хотя сервлеты могут обслуживать любые запросы, они обычно используются для расширения веб-серверов.
Большинство необходимых для создания сервлетов классов и интерфейсов содержатся в пакетах `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)
2017-10-21 06:01:09 +03:00
## В чем заключаются преимущества технологии сервлетов над CGI (Common Gateway Interface)?
2017-05-07 07:05:47 +03:00
+ Сервлеты предоставляют лучшую производительность обработки запросов и более эффективное использование памяти за счет использования преимущество многопоточности (на каждый запрос создается новая нить, что быстрее выделения памяти под новый объект для каждого запроса, как это происходит в CGI).
+ Сервлеты, как платформа и система являются независимыми. Таким образом веб-приложение написанное с использованием сервлетов может быть запущена в любом контейнере сервлетов, реализующим этот стандарт и в любой операционной системе.
+ Использование сервлетов повышает надежность программы, т.к. контейнер сервлетов самостоятельно заботится о жизненном цикле сервлетов (а значит и за утечками памяти), безопасности и сборщике мусора.
+ Сервлеты относительно легки в изучении и поддержке, таким образом разработчику необходимо заботиться только о бизнес-логике приложения, а не внутренней реализации веб-технологий.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какова структура веб-проекта?
2017-05-07 07:05:47 +03:00
`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)
2017-10-21 06:01:09 +03:00
## Что такое _«контейнер сервлетов»_?
2017-05-07 07:05:47 +03:00
__Контейнер сервлетов__ — программа, представляющая собой сервер, который занимается системной поддержкой сервлетов и обеспечивает их жизненный цикл в соответствии с правилами, определёнными в спецификациях. Может работать как полноценный самостоятельный веб-сервер, быть поставщиком страниц для другого веб-сервера, или интегрироваться в Java EE сервер приложений.
Контейнер сервлетов обеспечивает обмен данными между сервлетом и клиентами, берёт на себя выполнение таких функций, как создание программной среды для функционирующего сервлета, идентификацию и авторизацию клиентов, организацию сессии для каждого из них.
Наиболее известные реализации контейнеров сервлетов:
+ Apache Tomcat
+ Jetty
+ JBoss
2019-05-18 10:46:47 +03:00
+ WildFly
2017-05-07 07:05:47 +03:00
+ GlassFish
+ IBM WebSphere
+ Oracle Weblogic
[к оглавлению](#servlets-jsp-jstl)
2019-05-18 10:46:47 +03:00
## Зачем нужны сервера приложений, если есть контейнеры сервлетов?
+ __Пулы соединений с БД__
+ Возможность периодического тестирования доступности СУБД и обновления соединения в случае восстановления после сбоев
+ Замена прав доступа при подключении
+ Балансировка нагрузки между несколькими СУБД, определение доступность или недоступность того или иного узла
+ Защита пула соединений от некорректного кода в приложении, которое по недосмотру не возвращает соединения, просто отбирая его после какого-то таймаута.
+ __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)
2017-10-21 06:01:09 +03:00
## Как контейнер сервлетов управляет жизненным циклом сервлета, когда и какие методы вызываются?
2017-05-07 07:05:47 +03:00
Контейнер сервлетов управляет четырьмя фазами жизненного цикла сервлета:
+ Загрузка класса сервлета — когда контейнер получает запрос для сервлета, то происходит загрузка класса сервлета в память и вызов его конструктора без параметров.
+ Инициализация класса сервлета — после того как класс загружен контейнер инициализирует объект `ServletConfig` для этого сервлета и внедряет его через `init()` метод. Это и есть место где сервлет класс преобразуется из обычного класса в сервлет.
2020-02-21 19:36:49 +03:00
+ Обработка запросов — после инициализации сервлет готов к обработке запросов. Для каждого запроса клиента сервлет контейнер порождает новый поток и вызывает метод `service()` путем передачи ссылки на объекты ответа и запроса.
2017-05-07 07:05:47 +03:00
+ Удаление - когда контейнер останавливается или останавливается приложение, то контейнер сервлетов уничтожает классы сервлетов путем вызова `destroy()` метода.
2020-02-21 19:36:49 +03:00
Таким образом, сервлет создаётся при первом обращении к нему и живёт на протяжении всего времени работы приложения (в отличии от объектов классов, которые уничтожаются сборщиком мусора после того как они уже не используются) и весь жизненный цикл сервлета можно описать как последовательность вызова методов:
2017-05-07 07:05:47 +03:00
+ `public void init(ServletConfig config)` используется контейнером для инициализации сервлета. Вызывается один раз за время жизни сервлета.
+ `public void service(ServletRequest request, ServletResponse response)` вызывается для каждого запроса. Метод не может быть вызван раньше выполнения `init()` метода.
+ `public void destroy()` вызывается для уничтожения сервлета (один раз за время жизни сервлета).
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что такое _«дескриптор развертывания»_?
2017-05-07 07:05:47 +03:00
Дескриптор развертывания — это конфигурационный файл артефакта, который будет развернут в контейнере сервлетов. В спецификации Java Platform, Enterprise Edition дескриптор развертывания описывает то, как компонент, модуль или приложение (такое, как веб-приложение или приложение предприятия) должно быть развернуто.
Этот конфигурационный файл указывает параметры развертывания для модуля или приложения с определенными настройками, параметры безопасности и описывает конкретные требования к конфигурации. Для синтаксиса файлов дескриптора развертывания используется язык XML.
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Display name.</display-name>
<description>Description text.</description>
<servlet>
<servlet-name>ExampleServlet</servlet-name>
<servlet-class>xyz.company.ExampleServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>configuration</param-name>
<param-value>default</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ExampleServlet</servlet-name>
<url-pattern>/example</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ExampleJSP</servlet-name>
<jsp-file>/sample/Example.jsp</jsp-file>
</servlet>
<context-param>
<param-name>myParam</param-name>
<param-value>the value</param-value>
</context-param>
</web-app>
```
Для веб-приложений дескриптор развертывания должен называться `web.xml` и находиться в директории `WEB-INF`, в корне веб-приложения. Этот файл является стандартным дескриптором развертывания, определенным в спецификации. Также есть и другие типы дескрипторов, такие, как файл дескриптора развертывания `sun-web.xml`, содержащий специфичные для _Sun GlassFish Enterprise Server_ данные для развертывания именно для этого сервера приложений или файл `application.xml` в директории `META-INF` для приложений _J2EE_.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие действия необходимо проделать при создании сервлетов?
2017-05-07 07:05:47 +03:00
Чтобы создать сервлет `ExampleServlet`, необходимо описать его в дескрипторе развёртывания:
```xml
<servlet-mapping>
<servlet-name>ExampleServlet</servlet-name>
<url-pattern>/example</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ExampleServlet</servlet-name>
<servlet-class>xyz.company.ExampleServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>default</param-value>
</init-param>
</servlet>
```
Затем создать класс `xyz.company.ExampleServlet` путём наследования от `HttpServlet` и реализовать логику его работы в методе `service()` или методах `doGet()`/`doPost()`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## В каком случае требуется переопределять метод `service()`?
2017-05-07 07:05:47 +03:00
Метод `service()` переопределяется, когда необходимо, чтобы сервлет обрабатывал все запросы (и `GET`, и `POST`) в одном методе.
Когда контейнер сервлетов получает запрос клиента, то происходит вызов метода `service()`, который в зависимости от поступившего запроса вызывает или метод `doGet()` или метод `doPost()`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Есть ли смысл определять для сервлета конструктор? Каким образом лучше инициализировать данные?
2017-05-07 07:05:47 +03:00
Большого смысла определять для сервлета конструктор нет, т.к. инициализировать данные лучше не в конструкторе, а переопределив метод `init()`, в котором имеется возможность доступа к параметрам инициализации сервлета через использование объекта `ServletConfig`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Почему необходимо переопределить только `init()` метод без аргументов?
2017-05-07 07:05:47 +03:00
Метод `init()` переопределяется, если необходимо инициализировать какие-то данные до того как сервлет начнет обрабатывать запросы.
При переопределении метода `init(ServletConfig config)`, первым должен быть вызван метод `super(config)`, который обеспечит вызов метода `init(ServletConfig config)` суперкласса. `GenericServlet` предоставляет другой метод `init()` без параметров, который будет вызываться в конце метода `init(ServletConfig config)`.
Необходимо использовать переопределенный метод `init()` без параметров для инициализации данных во избежание каких-либо проблем, например ошибку, когда вызов `super()` не указан в переопределенном `init(ServletConfig config)`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие наиболее распространенные задачи выполняются в контейнере сервлетов?
2017-05-07 07:05:47 +03:00
+ Поддержка обмена данными. Контейнер сервлетов предоставляет легкий способ обмена данными между веб клиентом (браузером) и сервлетом. Благодаря контейнеру нет необходимости создавать слушателя сокета на сервере для отслеживания запросов от клиента, а так же разбирать запрос и генерировать ответ. Все эти важные и комплексные задачи решаются с помощью контейнера и разработчик может сосредоточиться на бизнес логике приложения.
+ Управление жизненным циклом сервлетов и ресурсов. Начиная от загрузки сервлета в память, инициализации, внедрения методов и заканчивая уничтожением сервлета. Контейнер так же предоставляет дополнительные утилиты, например JNDI, для управления пулом ресурсов.
+ Поддержка многопоточности. Контейнер самостоятельно создает новую нить для каждого запроса и предоставляет ей запрос и ответ для обработки. Таким образом сервлет не инициализируется заново для каждого запроса и тем самым сохраняет память и уменьшает время до обработки запроса.
+ Поддержка JSP. JSP классы не похожи на стандартные классы джавы, но контейнер сервлетов преобразует каждую JSP в сервлет и далее управляется контейнером как обычным сервлетом.
+ Различные задачи. Контейнер сервлетов управляет пулом ресурсов, памятью приложения, сборщиком мусора. Предоставляются возможности настройки безопасности и многое другое.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что вы знаете о _сервлетных фильтрах_?
2017-05-07 07:05:47 +03:00
__Сервлетный фильтр__ - это 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()` выполнить дополнительную работу над полученным ответом. К примеру, сохранить регистрационную информацию об этом ответе.
2020-02-21 19:36:49 +03:00
После того, как класс-фильтр откомпилирован, его необходимо установить в контейнер и _«приписать» (map)_ к одному или нескольким сервлетам. Объявление и подключение фильтра отмечается в дескрипторе развёртывания `web.xml` внутри элементов `<filter>` и `<filter-mapping>`. Для подключение фильтра к сервлету необходимо использовать вложенные элементы `<filter-name>` и `<servlet-name>`.
2017-05-07 07:05:47 +03:00
> Объявление класс-фильтра `FilterConnect` с именем `FilterName`:
```xml
<filter>
<filter-name>FilterName</filter-name>
<filter-class>FilterConnect</filter-class>
<init-param>
<!--- фильтр имеет параметр инициализации `active`, которому присваивается значение `true`. -->
<param-name>active</param-name>
<param-value>true</param-true>
</init-param>
</filter>
```
> Подключение фильтра `FilterName` к сервлету `ServletName`:
```xml
<filter-mapping>
<filter-name>FilterName</filter-name>
<servlet-name>ServletName</servlet-name>
</filter-mapping>
```
Для связи фильтра со страницами HTML или группой сервлетов необходимо использовать тег `<url-pattern>`:
> Подключение фильтра `FilterName` ко всем вызовам .html страниц
```xml
<filter-mapping>
<filter-name>FilterName</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
```
Порядок, в котором контейнер строит цепочку фильтров для запроса определяется следующими правилами:
+ цепочка, определяемая `<url-pattern>`, выстраивается в том порядке, в котором встречаются соответствующие описания фильтров в `web.xml`;
+ последовательность сервлетов, определенных с помощью `<servlet-name>`, также выполняется в той последовательности, в какой эти элементы встречаются в дескрипторе развёртывания `web.xml`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Зачем в сервлетах используются различные _listener_?
2017-05-07 07:05:47 +03:00
__Listener (слушатель)__ работает как триггер, выполняя определённые действия при наступлении какого-либо события в жизненном цикле сервлета.
Слушатели, разделённые по области видимости (scope):
+ _Request_:
+ `ServletRequestListener` используется для того, чтобы поймать момент создания и уничтожения запроса;
+ `ServletRequestAttributeListener` используется для прослушивании событий происходящих с атрибутами запроса.
+ _Context_:
+ `ServletContextListener` позволяет поймать момент, когда контекст инициализируется либо уничтожается;
+ `ServletContextAttributeListener` используется для прослушивании событий происходящих с атрибутами в контексте.
+ _Session_:
+ `HttpSessionListener` позволяет поймать момент создания и уничтожения сессии;
+ `HttpSessionAttributeListener` используется при прослушивании событий происходящих с атрибутами в сессии;
+ `HttpSessionActivationListener` используется в случае, если происходит миграция сессии между различными JVM в распределённых приложениях;
+ `HttpSessionBindingListener` так же используется для прослушивания событий происходящих с атрибутами в сессии. Разница между `HttpSessionAttributeListener` и `HttpSessionBindingListener` слушателями: первый декларируется в `web.xml`; экземпляр класса создается контейнером автоматически в единственном числе и применяется ко всем сессиям; второй: экземпляр класса должен быть создан и закреплён за определённой сессией «вручную», количество экземпляров также регулируется самостоятельно.
Подключение слушателей:
```xml
<web-app>
...
<listener>
<listener-class>xyz.company.ExampleListener</listener-class>
</listener>
...
</web-app>
```
`HttpSessionBindingListener` подключается в качестве атрибута непосредственно в сессию, т.е., чтобы его подключить необходимо:
+ создать экземпляр класса реализующего этот интерфейс;
+ положить созданный экземпляр в сессию при помощи `setAttribute(String, Object)`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Когда стоит использовать фильтры сервлетов, а когда слушателей?
2017-05-07 07:05:47 +03:00
Следует использовать фильтры, если необходимо обрабатывать входящие или исходящие данные (например: для аутентификации, преобразования формата, компрессии, шифрования и т.д.), в случае, когда необходимо реагировать на события - лучше применять слушателей.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как реализовать запуск сервлета одновременно с запуском приложения?
2017-05-07 07:05:47 +03:00
Контейнер сервлетов обычно загружает сервлет по первому запросу клиента.
Если необходимо загрузить сервлет прямо на старте приложения (например если загрузка сервлета происходит длительное время) следует использовать элемент `<load-on-startup>` в дескрипторе или аннотацию `@loadOnStartup` в коде сервлета, что будет указывать на необходимость загрузки сервлета при запуске.
Если целочисленное значение этого параметра отрицательно, то сервлет будет загружен при запросе клиента. В противном случае - загрузится на старте приложения, при этом, чем число меньше, тем раньше в очереди на загрузку он окажется.
```xml
<servlet>
<servlet-name>ExampleServlet</servlet-name>
<servlet-class>xyz.company.ExampleServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как обработать в приложении исключения, выброшенные другим сервлетом?
2017-05-07 07:05:47 +03:00
Когда приложение выбрасывет исключение контейнер сервлетов обрабатывает его и создаёт ответ в формате HTML. Это аналогично тому что происходит при кодах ошибок вроде 404, 403 и т.д.
В дополнении к этому существует возможность написания собственных сервлетов для обработки исключений и ошибок с указанием их в дескрипторе развертывания:
```xml
<error-page>
<error-code>404</error-code>
<location>/AppExceptionHandler</location>
</error-page>
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/AppExceptionHandler</location>
</error-page>
```
Основная задача таких сервлетов - обработать ошибку/исключение и сформировать понятный ответ пользователю. Например, предоставить ссылку на главную страницу или же описание ошибки.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что представляет собой `ServletConfig`?
2017-05-07 07:05:47 +03:00
Интерфейс `javax.servlet.ServletConfig` используется для передачи сервлету конфигурационной информации. Каждый сервлет имеет свой собственный экземпляр объекта `ServletConfig`, создаваемый контейнером сервлетов.
Для установки параметров конфигурации используются параметры `init-param` в `web.xml`:
```xml
<servlet>
<servlet-name>ExampleServlet</servlet-name>
<servlet-class>xyz.company.ExampleServlet</servlet-class>
<init-param>
<param-name>exampleParameter</param-name>
<param-value>parameterValue</param-value>
</init-param>
</servlet>
```
или аннотации `@WebInitParam`:
```java
@WebServlet(
urlPatterns = "/example",
initParams = {
@WebInitParam(name = "exampleParameter", value = "parameterValue")
}
)
public class ExampleServlet extends HttpServlet {
//...
}
```
Для получения `ServletConfig` сервлета используется метод `getServletConfig()`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что представляет собой `ServletContext`?
2017-05-07 07:05:47 +03:00
Уникальный (в рамках веб-приложения) объект `ServletContext` реализует интерфейс `javax.servlet.ServletContext` и предоставляет сервлетам доступ к параметрам этого веб-приложения. Для предоставления доступа используется элемент `<context-param>` в `web.xml`:
```xml
<web-app>
...
<context-param>
<param-name>exampleParameter</param-name>
<param-value>parameterValue</param-value>
</context-param>
...
</web-app>
```
Объект `ServletContext` можно получить с помощью метода `getServletContext()` у интерфейса `ServletConfig`. Контейнеры сервлетов так же могут предоставлять контекстные объекты, уникальные для группы сервлетов. Каждая из групп будет связана со своим набором URL-путей хоста. В спецификации Servlet 3 `ServletContext` был расширен и теперь предоставляет возможности программного добавления слушателей и фильтров в приложение. Так же у этого интерфейса имеется множество полезных методов таких как `getServerInfo()`, `getMimeType()`, `getResourceAsStream()` и т.д.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## В чем отличия `ServletContext` и `ServletConfig`?
2017-05-07 07:05:47 +03:00
+ `ServletConfig` уникален для сервлета, а `ServletContext` - для приложения;
+ `ServletConfig` используется для предоставления параметров инициализации конкретному сервлету, а `ServletContext` для предоставления параметров инициализации для всех сервлетов приложения;
+ для `ServletConfig` возможности модифицировать атрибуты отсутствуют, атрибуты в объекте `ServletContext` можно изменять.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Для чего нужен интерфейс `ServletResponse`?
2017-05-07 07:05:47 +03:00
Интерфейс `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)
2017-10-21 06:01:09 +03:00
## Для чего нужен интерфейс `ServletRequest`?
2017-05-07 07:05:47 +03:00
Интерфейс `ServletRequest` используется для получения параметров соединения, запроса, а также заголовков, входящего потока данных и т.д.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что такое `Request Dispatcher`?
2017-05-07 07:05:47 +03:00
Интерфейс `RequestDispatcher` используется для передачи запроса другому ресурсу, при этом существует возможность добавления данных полученных из этого ресурса к собственному ответу сервлета. Так же этот интерфейс используется для внутренней коммуникации между сервлетами в одном контексте.
2020-02-21 20:01:36 +03:00
В интерфейсе объявлено два метода:
2017-05-07 07:05:47 +03:00
+ `void forward(ServletRequest var1, ServletResponse var2)` — передает запрос из сервлета к другому ресурсу (сервлету, JSP или HTML файлу) на сервере.
+ `void include(ServletRequest var1, ServletResponse var2)` — включает контент ресурса (сервлет, JSP или HTML страница) в ответ.
Доступ к интерфейсу можно получить с помощью метода интерфейса `ServletContext` - `RequestDispatcher getRequestDispatcher(String path)`, где путь начинающийся с `/`, интерпретируется относительно текущего корневого пути контекста.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как из одного сервлета вызвать другой сервлет?
2017-05-07 07:05:47 +03:00
Для вызова сервлета из того же приложения необходимо использовать механизм внутренней коммуникации сервлетов (_inter-servlet communication mechanisms_) через вызовы методов `RequestDispatcher`:
+ `forward()` - передаёт выполнение запроса в другой сервлет;
+ `include()` - предоставляет возможность включить результат работы другого сервлета в возвращаемый ответ.
Если необходимо вызывать сервлет принадлежащий другому приложению, то использовать `RequestDispatcher` уже не получится, т.к. он определен только для текущего приложения. Для подобных целей необходимо использовать метод `ServletResponse` - `sendRedirect()` которому предоставляется полный URL другого сервлета. Для передачи данных между сервлетами можно использовать `cookies`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Чем отличается `sendRedirect()` от `forward()`?
2017-05-07 07:05:47 +03:00
__`forward()`__:
+ Выполняется на стороне сервера;
+ Запрос перенаправляется на другой ресурс в пределах того же сервера;
2020-02-21 20:07:46 +03:00
+ Не зависит от протокола клиентского запроса, так как обеспечивается контейнером сервлетов;
2017-05-07 07:05:47 +03:00
+ Нельзя применять для внедрения сервлета в другой контекст;
+ Клиент не знает о фактически обрабатываемом ресурсе и URL в строке остается прежним;
+ Выполняется быстрее метода `sendRedirect()`;
+ Определён в интерфейсе `RequestDispatcher`.
__`sendRedirect()`__:
+ Выполняется на стороне клиента;
+ Клиенту возвращается ответ `302 (redirect)` и запрос перенаправляется на другой сервер;
+ Может использоваться только с клиентами HTTP;
+ Разрешается применять для внедрения сервлета в другой контекст;
+ URL адрес изменяется на адрес нового ресурса;
+ Медленнее `forward()` т.к. требует создания нового запроса;
+ Определён в интерфейсе `HttpServletResponse`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Для чего используются атрибуты сервлетов и как происходит работа с ними?
2017-05-07 07:05:47 +03:00
Атрибуты сервлетов используются для внутренней коммуникации сервлетов.
В веб-приложении существует возможность работы с атрибутами используя методы `setAttribute()`, `getAttribute()`, `removeAttribute()`, `getAttributeNames()`, которые предоставлены интерфейсами `ServletRequest`, `HttpSession` и `ServletContext` (для областей видимости _request_, _session_, _context_ соответственно).
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Каким образом можно допустить в сервлете deadlock?
2017-05-07 07:05:47 +03:00
Можно получить блокировку, например, допустив циклические вызовы метода `doPost()` в методе `doGet()` и метода `doGet()` в методе `doPost()`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как получить реальное расположение сервлета на сервере?
2017-05-07 07:05:47 +03:00
Реальный путь к расположению сервлета на сервере можно получить из объекта `ServletContext`:
`getServletContext().getRealPath(request.getServletPath())`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как получить информацию о сервере из сервлета?
2017-05-07 07:05:47 +03:00
Информацию о сервере можно получить из объекта `ServletContext`:
`getServletContext().getServerInfo()`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как получить IP адрес клиента на сервере?
2017-05-07 07:05:47 +03:00
IP адрес клиента можно получить вызвав `request.getRemoteAddr()`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие классы-обертки для сервлетов вы знаете?
2017-05-07 07:05:47 +03:00
Собственные обработчики `ServletRequest` и `ServletResponse` можно реализовать добавив новые или переопределив существующие методы у классов-обёрток `ServletRequestWrapper` (`HttpServletRequestWrapper`) и `ServletResponseWrapper` (`HttpServletRequestWrapper`).
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## В чем отличия `GenericServlet` и `HttpServlet`?
2017-05-07 07:05:47 +03:00
Абстрактный класс `GenericServlet` — независимая от используемого протокола реализация интерфейса `Servlet`, а абстрактный класс `HttpServlet` в свою очередь расширяет `GenericServlet` для протокола HTTP..
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Почему `HttpServlet` класс объявлен как абстрактный?
2017-05-07 07:05:47 +03:00
Класс `HTTPServlet` предоставляет лишь общую реализацию сервлета для HTTP протокола. Реализация ключевых методов `doGet()` и `doPost()`, содержащих основную бизнес-логику перекладывается на разработчика и по умолчанию возвращает `HTTP 405 Method Not Implemented error`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие основные методы присутствуют в классе `HttpServlet`?
2017-05-07 07:05:47 +03:00
+ `doGet()` - для обработки HTTP запросов `GET`;
+ `doPost()` - для обработки HTTP запросов `POST`;
+ `doPut()` - для обработки HTTP запросов `PUT`;
+ `doDelete()` - для обработки HTTP запросов `DELETE`;
+ `doHead()` - для обработки HTTP запросов `HEAD`;
+ `doOptions()` - для обработки HTTP запросов `OPTIONS`;
+ `doTrace()` - для обработки HTTP запросов `TRACE`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Стоит ли волноваться о многопоточной безопасности работая с сервлетами?
2017-05-07 07:05:47 +03:00
Методы `init()` и `destroy()` вызываются один раз за жизненный цикл сервлета — поэтому по поводу них беспокоиться не стоит.
Методы `doGet()`, `doPost()`, `service()` вызываются на каждый запрос клиента и т.к. сервлеты используют многопоточность, то здесь задумываться о потокобезопасной работе обязательноЮ при этом правила использования многопоточности остаются теми же: локальные переменные этих методов будут созданы отдельно для каждого потока, а при использовании глобальных разделяемых ресурсов необходимо использовать синхронизацию или другие приёмы многопоточного программирования.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какой метод HTTP не является неизменяемым?
2017-05-07 07:05:47 +03:00
HTTP метод называется неизменяемым, если он на один и тот же запрос всегда возвращает одинаковый результат. HTTP методы `GET`, `PUT`, `DELETE`, `HEAD` и `OPTIONS` являются неизменяемыми, поэтому необходимо реализовывать приложение так, чтобы эти методы возвращали одинаковый результат постоянно. К изменяемым методам относится метод `POST`, который и используется для реализации чего-либо, что изменяется при каждом запросе.
К примеру, для доступа к статической HTML странице используется метод `GET`, т.к. он всегда возвращает одинаковый результат. При необходимости сохранять какую-либо информацию, например в базе данных, нужно использовать `POST` метод.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие есть методы отправки данных с клиента на сервер?
2017-05-07 07:05:47 +03:00
+ `GET` - используется для запроса содержимого указанного ресурса, изображения или гипертекстового документа. Вместе с за просом могут передаваться дополнительные параметры как часть URI, значения могут выбираться из полей формы или передаваться непосредственно через URL. При этом запросы кэшируются и имеют ограничения на размер. Этот метод является основным методом взаимодействия браузера клиента и веб-сервера.
+ `POST` - используется для передачи пользовательских данных в содержимом HTTP-запроса на сервер. Пользовательские данные упакованы в тело запроса согласно полю заголовка Content-Type и/или включены в URI запроса. При использовании метода POST под URI подразумевается ресурс, который будет обрабатывать запрос.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## В чем разница между методами `GET` и `POST`?
2017-05-07 07:05:47 +03:00
+ `GET` передает данные серверу используя URL, тогда как `POST` передает данные, используя тело HTTP запроса. Длина URL ограничена 1024 символами, это и будет верхним ограничением для данных, которые можно отослать через `GET`. `POST` может отправлять гораздо большие объемы данных. Лимит устанавливается web-server и составляет обычно около 2 Mb.
+ Передача данных методом `POST` более безопасна, чем методом `GET`, так как секретные данные (например пароль) не отображаются напрямую в web-клиенте пользователя, в отличии от URL, который виден почти всегда. Иногда это преимущество превращается в недостатком - вы не сможете послать данные за кого-то другого.
+ `GET`метод является неизменяемым, тогда как `POST` — изменяемый.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## В чем разница между `PrintWriter` и `ServletOutputStream`?
2017-05-07 07:05:47 +03:00
`PrintWriter` — класс для работы с символьным потоком, экземпляр которого можно получить через метод `ServletResponse` `getWriter()`;
`ServletOutputStream` — класс для работы байтовым потоком. Для получения его экземпляра используется метод `ServletResponse` `getOutputStream()`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Можно ли одновременно использовать в сервлете `PrintWriter` и `ServletOutputStream`?
2017-05-07 07:05:47 +03:00
Так сделать не получится, т.к. при попытке одновременного вызова `getWriter()` и `getOutputStream()` будет выброшено исключение `java.lang.IllegalStateException` с сообщением, что уже был вызван другой метод.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Расскажите об интерфейсе `SingleThreadModel`.
2017-05-07 07:05:47 +03:00
Интерфейс `SingleThreadModel` является маркерным - в нем не объявлен ни один метод, однако, если сервлет реализует этот интерфейс, то метод `service()` этого сервлета гарантированно не будет одновременно выполняться в двух потоках. Контейнер сервлетов либо синхронизирует обращения к единственному экземпляру, либо обеспечивает поддержку пула экземпляров и перенаправление запроса свободному сервлету.
Другими словами, контейнер гарантирует отсутствие конфликтов при одновременном обращении к переменным или методам экземпляра сервлета. Однако существуют также и другие разделяемые ресурсы, которые даже при использовании этого интерфейса, остаются всё так же доступны обработчикам запросов в других потоках. Т.о. пользы от использования этого интерфейса немного и в спецификации Servlet 2.4 он был объявлен `deprecated`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что означает _URL encoding_? Как это осуществить в Java?
2017-05-07 07:05:47 +03:00
__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)
2017-10-21 06:01:09 +03:00
## Какие различные методы управления сессией в сервлетах вы знаете?
2017-05-07 07:05:47 +03:00
При посещении клиентом Web-ресурса и выполнении вариантов запросов, контекстная информация о клиенте не хранится. В протоколе HTTP нет возможностей для сохранения и изменения информации о предыдущих посещениях клиента. Сеанс (сессия) соединение между клиентом и сервером, устанавливаемое на определенное время, за которое клиент может отправить на сервер сколько угодно запросов. Сеанс устанавливается непосредственно между клиентом и Web-сервером. Каждый клиент устанавливает с сервером свой собственный сеанс. Сеансы используются для обеспечения хранения данных во время нескольких запросов Web-страницы или на обработку информации, введенной в пользовательскую форму в результате нескольких HTTP-соединений (например, клиент совершает несколько покупок в интернет-магазине; студент отвечает на несколько тестов в системе дистанционного обучения).
Существует несколько способов обеспечения уникального идентификатора сессии:
+ __User Authentication__ Предоставление учетных данных самим пользователем в момент аутентификации. Переданная таким образом информация в дальнейшем используется для поддержания сеанса. Это метод не будет работать, если пользователь вошёл в систему одновременно из нескольких мест.
+ __HTML Hidden Field__ Присвоение уникального значения скрытому полю HTML страницы, в момент когда пользователь начинает сеанс. Этот метод не может быть использован со ссылками, потому что нуждается в подтверждении формы со скрытым полем каждый раз во время формирования запроса. Кроме того, это не безопасно, т.к. существует возможность простой подмены такого идентификатора.
+ __URL Rewriting__ Добавление идентификатора сеанса как параметра URL. Достаточно утомительная операция, потому что требует постоянного отслеживания этого идентификатора при каждом запросе или ответе.
+ __Cookies__ Использование небольших фрагментов данных, отправленных web-сервером и хранимых на устройстве пользователя. Данный метод не будет работать, если клиент отключает использование cookies.
+ __Session Management API__ Использование специального API для отслеживания сеанса, построенный на основе и на методах описанных выше и который решает частные проблемы перечисленных способов:
+ Чаще всего недостаточно просто отслеживать сессию, необходимо ещё и сохранять какие-либо дополнительные данные о ней, которые могут потребоваться при обработке последующих запросов. Осуществление такого поведения требует много дополнительных усилий.
+ Все вышеперечисленные методы не являются универсальными: для каждого из них можно подобрать конкретный сценарий, при котором они не будут работать.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что такое _cookies_?
2017-05-07 07:05:47 +03:00
__Сookies («куки»)__ — небольшой фрагмент данных, отправленный web-сервером и хранимый на устройстве пользователя. Всякий раз при попытке открыть страницу сайта, web-клиент пересылает соответствующие этому сайту cookies web-серверу в составе HTTP-запроса. Применяется для сохранения данных на стороне пользователя и на практике обычно используется для:
+ аутентификации пользователя;
+ хранения персональных предпочтений и настроек пользователя;
+ отслеживания состояния сеанса доступа пользователя;
+ ведения разнообразной статистики.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие методы для работы с cookies предусмотрены в сервлетах?
2017-05-07 07:05:47 +03:00
Servlet API предоставляет поддержку cookies через класс `javax.servlet.http.Cookie`:
+ Для получения массива cookies из запроса необходимо воспользоваться методом `HttpServletRequest.getCookies()`. Методов для добавления cookies в `HttpServletRequest` не предусмотрено.
+ Для добавления cookie в ответ используется `HttpServletResponse.addCookie(Cookie c)`. Метода получения cookies в `HttpServletResponse` отсутствует.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что такое _URL Rewriting_?
2017-05-07 07:05:47 +03:00
__URL Rewriting__ - специальная перезапись (перекодирование) оригинального URL. Данный механизм может использоваться для управления сессией в сервлетах, когда _cookies_ отключены.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Зачем нужны и чем отличаются методы `encodeURL()` и `encodeRedirectURL()`?
2017-05-07 07:05:47 +03:00
`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)
2017-10-21 06:01:09 +03:00
## Что такое _«сессия»_?
2017-05-07 07:05:47 +03:00
__Сессия__ - это сеанс связи между клиентом и сервером, устанавливаемый на определенное время. Сеанс устанавливается непосредственно между клиентом и веб-сервером в момент получения первого запроса к веб-приложению. Каждый клиент устанавливает с сервером свой собственный сеанс, который сохраняется до окончания работы с приложением.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как уведомить объект в сессии, что сессия недействительна или закончилась?
2017-05-07 07:05:47 +03:00
Чтобы быть уверенным в том, что объект будет оповещён о прекращении сессии, нужно реализовать интерфейс `javax.servlet.http.HttpSessionBindingListener`. Два метода этого интерфейса: `valueBound()` и `valueUnbound()` используются при добавлении объекта в качестве атрибута к сессии и при уничтожении сессии соответственно.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какой существует эффективный способ удостоверится, что все сервлеты доступны только для пользователя с верной сессией?
2017-05-07 07:05:47 +03:00
Сервлет фильтры используются для перехвата всех запросов между контейнером сервлетов и сервлетом. Поэтому логично использовать соответствующий фильтр для проверки необходимой информации (например валидности сессии) в запросе.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как мы можем обеспечить _transport layer security_ для нашего веб приложения?
2017-05-07 07:05:47 +03:00
Для обеспечения _transport layer security_ необходимо настроить поддержку SSL сервлет контейнера. Как это сделать зависит от конкретной реализации сервлет-контейнера.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как организовать подключение к базе данных, обеспечить журналирование в сервлете?
2017-05-07 07:05:47 +03:00
При работе с большим количеством подключений к базе данных рекомендуется инициализировать их в _servlet context listener_, а также установить в качестве атрибута контекста для возможности использования другими сервлетами.
Журналирование подключается к сервлету стандартным для логгера способом (например для _log4j_ это может быть property-файл или XML-конфигурация) , а далее эта информация используется при настройке соответствующего _context listener_.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие основные особенности появились в спецификации _Servlet 3_?
2017-05-07 07:05:47 +03:00
+ __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)
2017-10-21 06:01:09 +03:00
## Какие способы аутентификации доступны сервлету?
2017-05-07 07:05:47 +03:00
Спецификация сервлетов определяет четыре типа проверки подлинности:
+ __HTTP Basic Authentication__ - `BASIC`. При доступе к закрытым ресурсам появится окно, которое попросит ввести данные для аутентификации.
+ __Form Based Login__ - `FORM`. Используется собственная html форма:
+ __HTTP Digest Authentication__ - `DIGEST`. Цифровая аутентификация с шифрованием.
+ __HTTPS Authentication__ - `CLIENT-CERT`. Аутентификация с помощью клиентского сертификата.
```xml
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.html</form-login-page>
<form-error-page>/error.html</form-error-page>
</form-login-config>
</login-config>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что такое _Java Server Pages (JSP)_?
2017-05-07 07:05:47 +03:00
__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)
2017-10-21 06:01:09 +03:00
## Зачем нужен JSP?
2017-05-07 07:05:47 +03:00
JSP расширяет технологию сервлетов обеспечивая возможность создания динамических страницы с HTML подобным синтаксисом.
Хотя создание представлений поддерживается и в сервлетах, но большая часть любой веб-страницы является статической, поэтому код сервлета в таком случае получается чересчур перегруженным, замусоренным и поэтому при его написании легко допустить ошибку.
Еще одним преимуществом JSP является горячее развертывание - возможность заменить одну страницу на другую непосредственно в контейнере без необходимости перекомпилировать весь проект или перезапускать сервер.
Однако рекомендуется избегать написания серьёзной бизнес-логики в JSP и использовать страницу только в качестве представления.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Опишите, как обрабатываются JSP страницы, начиная от запроса к серверу, заканчивая ответом пользователю.
2017-05-07 07:05:47 +03:00
Когда пользователь переходит по ссылке на страницу `page.jsp`, он отправляет http-запрос на сервер `GET /page.jsp`. Затем, на основе этого запроса и текста самой страницы, сервер генерирует java-класс, компилирует его и выполняет полученный сервлет, формирующий ответ пользователю в виде представления этой страницы, который сервер и перенаправляет обратно пользователю.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Расскажите об этапах (фазах) жизненного цикла JSP.
2017-05-07 07:05:47 +03:00
Если посмотреть код внутри созданной 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)
2017-10-21 06:01:09 +03:00
## Расскажите о методах жизненного цикла JSP.
2017-05-07 07:05:47 +03:00
Контейнер сервлетов (например, Tomcat, GlassFish) создает из JSP-страницы класс сервлета, наследующего свойства интерфейса `javax.servlet.jsp.HttpJspBase` и включающего следующие методы:
+ `jspInit()` — метод объявлен в JSP странице и реализуется с помощью контейнера. Этот метод вызывается один раз в жизненном цикле JSP для того, чтобы инициализировать конфигурационные параметры указанные в дескрипторе развертывания. Этот метод можно переопределить с помощью определения элемента _JSP scripting_ и указания необходимых параметров для инициализации;
+ `_jspService()` — метод переопределяется контейнером автоматически и соответствует непосредственно коду JSP, описанному на странице. Этот метод определен в интерфейсе `HttpJspPage`, его имя начинается с нижнего подчеркивания и он отличается от других методов жизненного цикла тем, что его невозможно переопределить;
+ `jspDestroy()` — метод вызывается контейнером для удаления объекта из памяти (на последней фазе жизненного цикла JSP - Destroy). Метод вызывается только один раз и доступен для переопределения, предоставляя возможность освободить ресурсы, которые были созданы в `jspInit()`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие методы жизненного цикла JSP могут быть переопределены?
2017-05-07 07:05:47 +03:00
Возможно переопределить лишь `jspInit()` и `jspDestroy()` методы.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как можно предотвратить прямой доступ к JSP странице из браузера?
2017-05-07 07:05:47 +03:00
Прямой доступ к директории `/WEB-INF/` из веб-приложения отсутствует. Поэтому JSP-страницы можно расположить внутри этой папки и тем самым запретить доступ к странице из браузера. Однако, по аналогии с описанием сервлетов, будет необходимо настроить дескриптор развертывания:
```xml
<servlet>
<servlet-name>Example</servlet-name>
<jsp-file>/WEB-INF/example.jsp</jsp-file>
<init-param>
<param-name>exampleParameter</param-name>
<param-value>parameterValue</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Example</servlet-name>
<url-pattern>/example.jsp</url-pattern>
</servlet-mapping>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какая разница между _динамическим_ и _статическим_ содержимым JSP?
2017-05-07 07:05:47 +03:00
Статическое содержимое JSP (HTML, код JavaScript, изображения и т.д.) не изменяется в процессе работы веб приложения.
Динамические ресурсы созданы для того, чтобы отображать свое содержимое в зависимости от пользовательских действий. Обычно они представлены в виде выражений EL (Expression Language), библиотек JSP-тегов и пр.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как закомментировать код в JSP?
2017-05-07 07:05:47 +03:00
+ `<!—- HTML комментарий; отображается на странице JSP —->` такие комментарии будут видны клиенту при просмотре кода страницы.
+ `<%—- JSP комментарий; не отображается на странице JSP —-%>` такие комментарии описываются в созданном сервлете и не посылаются клиенту. Для любых комментариев по коду или отладочной информации необходимо использовать именно такой тип комментариев.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие существуют основные типы тегов JSP?
2017-05-07 07:05:47 +03:00
+ _Выражение 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)
2017-10-21 06:01:09 +03:00
## Что вы знаете о действиях JSP (_Action tag_ и _JSP Action Elements_).
2017-05-07 07:05:47 +03:00
__Action tag__ и __JSP Action Elements__ предоставляют методы работы с Java Beans, подключения ресурсов, проброса запросов и создания динамических XML элементов. Такие элементы всегда начинаются с записи `jsp:` и используются непосредственно внутри страницы JSP без необходимости подключения сторонних библиотек или дополнительных настроек.
Наиболее часто используемыми JSP Action Elements являются:
+ `jsp:include`: `<jsp:include page="относительный URL" flush="true"/>` - подключить файл при запросе страницы. Если необходимо, чтобы файл подключался в процессе трансляции страницы, то используется директива `page` совместно с атрибутом `include`;
+ `jsp:useBean`: `<jsp:useBean att=значение*/>` или `<jsp:useBean att=значение*>...</jsp:useBean>` - найти или создать Java bean;
+ `jsp:setProperty`: `<jsp:setProperty att=значение*/>` - установить свойства Java bean, или явно, или указанием на соответствующее значение, передаваемое при запросе;
+ `jsp:forward`: `<jsp:forward page="относительный URL"/>` - передать запрос другой странице;
+ `jsp:plugin`: `<jsp:plugin attribute="значение"*>...</jsp:plugin>` - сгенерировать (в зависимости от типа браузера) тэги `OBJECT` или `EMBED` для апплета, использующего технологию Java Plugin.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Взаимодействие _JSP - сервлет - JSP_.
2017-05-07 07:05:47 +03:00
_«JSP - сервлет - JSP»_ архитектура построения приложений носит название _MVC (Model/View/Controller)_:
+ _Model_ - классы данных и бизнес-логики;
+ _View_ - страницы JSP;
+ _Controller_ - сервлеты.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие области видимости переменных существуют в JSP?
2017-05-07 07:05:47 +03:00
Область видимости объектов определяется тем контекстом в который помещается данный объект. В зависимости от той или иной области действия так же определяется время существования объекта.
В JSP предусмотрены следующие области действия переменных (объектов):
+ `request` область действия запроса - объект будет доступен на текущей JSP странице, странице пересылки (при использовании `jsp:forward`) или на включаемой странице (при использовании `jsp:include`);
+ `session` область действия сессии - объект будет помещен в сеанс пользователя, будет доступен на всех JSP страницах и будет существовать пока существует сессия пользователя, или он не будет из нее принудительно удален.
+ `application` область действия приложения - объект будет доступен для всех пользователей на всех JSP страницах и будет существовать на протяжении всей работы приложения или пока не будет удален принудительно и контекста приложения.
+ `page` область действия страницы - объект будет доступен только на той странице, где он определен. На включаемых (`jsp:include`) и переадресуемых (`jsp:forward`) страницах данный объект уже не будет доступен.
Таким образом, чтобы объект был доступен всем JSP страницам, необходимо указать область видимости `application` или `session`, в зависимости от того требуется ли доступ к объекту всем пользователям или только текущему.
Для указания требуемой области действия при определении объекта на JSP странице используется атрибут scope тега `jsp:useBean`:
```
<jsp:useBean id="myBean" class="ru.javacore.MyBean" scope="session"/>
```
Если не указывать атрибут `scope`, то по умолчанию задается область видимости страницы `page`
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие неявные, внутренние объекты и методы есть на JSP странице?
2017-05-07 07:05:47 +03:00
__JSP implicit objects (неявные объекты)__ создаются контейнером при конвертации JSP страницы в код сервлета для помощи разработчикам. Эти объекты можно использовать напрямую в скриптлетах для передачи информации в сервис методы, однако мы не можем использовать неявные объекты в JSP Declaration, т.к. такой код пойдет на уровень класса.
Существует 9 видов неявных объектов, которые можно использовать прямо на JSP странице. Семь из них объявлены как локальные переменные в начале `_jspService()` метода, а два оставшихся могут быть использованы как аргументы метода `_jspService()`.
+ `out Object` :
```
<strong>Current Time is</strong>: <% out.print(new Date()); %><br>
```
+ `request Object` :
```
<strong>Request User-Agent</strong>: <%=request.getHeader("User-Agent") %><br>
```
+ `response Object` :
```
<strong>Response</strong>: <%response.addCookie(new Cookie("Test","Value")); %>
```
+ `config Object` :
```
<strong>User init param value</strong>: <%=config.getInitParameter("User") %><br>
```
+ `application Object` :
```
<strong>User context param value</strong>: <%=application.getInitParameter("User") %><br>
```
+ `session Object` :
```
<strong>User Session ID</strong>: <%=session.getId() %><br>
```
+ `pageContext Object` :
```
<% pageContext.setAttribute("Test", "Test Value"); %>
<strong>PageContext attribute</strong>: {Name="Test",Value="<%=pageContext.getAttribute("Test") %>"}<br>
```
+ `page Object` :
```
<strong>Generated Servlet Name</strong>: <%=page.getClass().getName() %>
```
+ `exception Object` :
```
<strong>Exception occured</strong>: <%=exception %><br>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какие неявные объекты не доступны в обычной JSP странице?
2017-05-07 07:05:47 +03:00
Неявный объект исключений JSP недоступен в обычных JSP страницах и используется на страницах ошибок JSP (_errorpage_) только для того, чтобы перехватить исключение, выброшенное JSP страницей и далее предоставить какую-либо полезную информацию клиенту.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что вы знаете о `PageContext` и какие преимущества его использования?
2017-05-07 07:05:47 +03:00
Неявный объект JSP - экземпляр класса `javax.servlet.jsp.PageContext` предоставляет доступ ко всем пространствам имён, ассоциированным с JSP-страницей, а также к различным её атрибутам.
Остальные неявные объекты добавляются к `pageContext` автоматически.
Класс `PageContext` это абстрактный класс, а его экземпляр можно получить через вызов метода `JspFactory.getPageContext()`, и освободить через вызов метода `JspFactory.releasePageContext()`.
`PageContext` обладает следующим набором особенностей и возможностей:
+ единый API для обслуживания пространств имён различных областей видимости;
+ несколько удобных API для доступа к различным `public`-объектам;
+ механизм получения `JspWriter` для вывода;
+ механизм обслуживания использования сессии страницей;
+ механизм экспонирования («показа») атрибутов директивы `page` среде скриптинга;
+ механизмы направления или включения текущего запроса в другие компоненты приложения;
+ механизм обработки процессов исключений на страницах ошибок _errorpage_;
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как сконфигурировать параметры инициализации для JSP?
2017-05-07 07:05:47 +03:00
Параметры инициализации для JSP задаются в `web.xml` файле аналогично сервлетам - элементами `servlet` и `servlet-mapping`. Единственным отличием будет указание местонахождения JSP страницы:
```xml
<servlet>
<servlet-name>Example</servlet-name>
<jsp-file>/WEB-INF/example.jsp</jsp-file>
<init-param>
<param-name>exampleParameter</param-name>
<param-value>parameterValue</param-value>
</init-param>
</servlet>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Почему не рекомендуется использовать скриплеты (скриптовые элементы) в JSP?
2017-05-07 07:05:47 +03:00
JSP страницы используются в основном для целей отображения представления (_view_), а вся бизнес-логика (_controller_) и модель (_model_) должны быть реализованы в сервлетах или классах-моделях. Обязанность JSP страницы - создание HTML ответа из переданных через атрибуты параметров. Большая часть JSP содержит HTML код а для того, чтобы помочь верстальщикам понять JSP код страницы предоставляется функционал элементов _action_, _JSP EL_, _JSP Standart Tag Library_. Именно их и необходимо использовать вместо скриптлетов для создания моста между (JSP)HTML и (JSP)Java частями.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Можно ли определить класс внутри JSP страницы?
2017-05-07 07:05:47 +03:00
Определить класс внутри JSP страницы можно, но это считается плохой практикой:
```java
<%!
private static class ExampleOne {
//...
}
%>
<%
private class ExampleTwo {
//...
}
%>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что вы знаете о Языке выражений JSP (JSP Expression Language EL)?
2017-05-07 07:05:47 +03:00
__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)
2017-10-21 06:01:09 +03:00
## Какие типы EL операторов вы знаете?
2017-05-07 07:05:47 +03:00
Операторы в EL поддерживают наиболее часто используемые манипуляции данными.
Типы операторов:
+ Стандартные операторы отношения: `==` (или `eq`), `!=` (или `neq`), `<` (или `lt`), `>` (или `gt`), `<=` (или `le`), `>=` (или `ge`).
+ Арифметические операторы: `+`, ``, `*`, `/` (или `div`), `%` (или `mod`).
+ Логические операторы: `&&` (или `and`), `||` (или `or`), `!` (или `not`).
+ Оператор `empty` используется для проверки переменной на `null`, или «пустое значение», который зависит от типа проверяемого объекта. Например, нулевая длина для строки или нулевой размер для коллекции.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Назовите неявные, внутренние объекты JSP EL и их отличия от объектов JSP.
2017-05-07 07:05:47 +03:00
Язык выражений JSP предоставляет множество неявных объектов, которые можно использовать для получения атрибутов в различных областях видимости (scopes) и для значений параметров. Важно отметить, что они отличаются от неявных объектов JSP и содержат атрибуты в заданной области видимости. Наиболее часто использующийся implicit object в JSP EL и JSP page — это объект pageContext. Ниже представлена таблица неявных объектов JSP EL.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как отключить возможность использования EL в JSP?
2017-05-07 07:05:47 +03:00
Для игнорирования выполнения языка выражений на странице существует два способа:
+ использовать директиву `<%@ page isELIgnored = «true» %>`,
+ настроить `web.xml` (лучше подходит для отключения EL сразу на нескольких страницах):
```xml
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как узнать тип HTTP метода используя JSP EL?
2017-05-07 07:05:47 +03:00
`${pageContext.request.method}`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Что такое _JSTL (JSP Standard tag library)_?
2017-05-07 07:05:47 +03:00
__JavaServer Pages Standard Tag Library, JSTL, Стандартная библиотека тегов JSP__ — расширение спецификации JSP (конечный результат _JSR 52_), добавляющее библиотеку JSP тегов для общих нужд, таких как разбор XML данных, условная обработка, создание циклов и поддержка интернационализации.
JSTL является альтернативой такому виду встроенной в JSP логики, как _скриплеты_ (прямые вставки Java кода). Использование стандартизованного множества тегов предпочтительнее, поскольку получаемый код легче поддерживать и проще отделять бизнес-логику от логики отображения.
Для использования JSTL тегов необходимо:
+ подключить зависимости, например в `pom.xml`:
```xml
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
```
+ указать пространство имен основных тегов 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)
2017-10-21 06:01:09 +03:00
## Из каких групп тегов состоит библиотека _JSTL_?
2017-05-07 07:05:47 +03:00
Группы тегов 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)
2017-10-21 06:01:09 +03:00
## Какая разница между `<c:set>` и `<jsp:useBean>`?
2017-05-07 07:05:47 +03:00
Оба тега создают и помещают экземпляры в заданную область видимости, но `<jsp:useBean>` только создаёт экземпляр конкретного типа, а `<c:set>`, создав экземпляр, позволяет дополнительно извлекать значение, например, из параметров запроса, сессии и т. д.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Чем отличается `<c:import>` от `<jsp:include>` и директивы `<%@include %>`?
2017-05-07 07:05:47 +03:00
По сравнению с action-тегом `<jsp:include>` и директивой `<%@include %>` тег `<c:import>` обеспечивает более совершенное включение динамических ресурсов, т.к. получает доступ к источнику, чтение информации из которого происходит непосредственно без буферизации и контент включается в исходную JSP построчно.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как можно расширить функциональность JSP?
## Что вы знаете о написании пользовательских JSP тегов?
## Приведите пример использования собственных тегов.
2017-05-07 07:05:47 +03:00
JSP можно расширить с помощью создания собственных тегов с необходимой функциональностью, которые можно добавить в библиотеку тегов на страницу JSP указав необходимое пространство имен.
> /WEB-INF/exampleTag.tld
```xml
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_1.xsd">
<tlib-version>1.0</tlib-version>
<short-name>example</short-name>
<uri>/WEB-INF/exampleTag</uri>
<tag>
<name>exampleTag</name>
<tag-class>xyz.company.ExampleTag</tag-class>
<body-content>empty</body-content>
<info>The example tag displays Hello World!</info>
</tag>
</taglib>
```
> 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"%>
<html>
<head>
<title>Example Tag</title>
</head>
<body>
<h1>Example Tag</h1>
<p><example:exampleTage /><p>
</body>
</html>
```
Также в пользовательских тегах существует возможность задать входные параметры. Например, существует необходимость отформатировать каким-либо стилем очень длинное число. Для этого можно использовать собственный тег по типу:
2017-10-21 06:01:09 +03:00
`<mytags:formatNumber number="123456.789" format="#,## #.00"/>`
2017-05-07 07:05:47 +03:00
Используя входные параметры, число должно быть преобразовано на JSP странице в таком виде `123,456.79` согласно шаблону. Т.к. JSTL не предоставляет такой функциональности, необходимо создать пользовательский тег для получения необходимого результата.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как сделать перенос строки в HTML средствами JSP?
2017-05-07 07:05:47 +03:00
Для переноса строки можно использовать тег `c:out` и атрибут `escapeXml`, который отключает обработку HTML элементов. В этом случае браузер получит следующий код в виде строки и обработает элемент `<br>` как требуется:
`<c:out value="<br> creates a new line in HTML" escapeXml="true"></c:out>`
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Почему не нужно конфигурировать стандартные JSP теги в `web.xml`?
2017-05-07 07:05:47 +03:00
Стандартные теги JSP не конфигурируются в `web.xml`, потому что tld файлы уже находятся внутри каталога `/META-INF/` в jar файлах JSTL.
Когда контейнер загружает веб-приложение и находит tld файлы в в jar файле в директории `/META-INF/`, то он автоматически настраивает их для непосредственного использования на JSP страницах. Остается только задать пространство имен на JSP странице.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как можно обработать ошибки JSP страниц?
2017-05-07 07:05:47 +03:00
Для обработки исключений выброшенных на JSP странице достаточно лишь задать страницу ошибки JSP и при её создании установить значение _page directive attribute_ `isErrorPage` в значение `true`. Таким образом будет предоставлен доступ к неявным объектам исключений в JSP и появится возможность передавать собственные, более информативные сообщения об ошибках клиенту. При этом настройка дескриптора развертывания выглядит так:
```xml
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как происходит обработка ошибок с помощью JSTL?
2017-05-07 07:05:47 +03:00
Для перехвата и обработки исключений в служебных методах класса служат JSTL Core Tags `c:catch` и `c:if`.
> Тег `c:catch` перехватывает исключение и обертывает его в переменную `exception`, доступную для обработки в теге `c:if`:
```
<c:catch var ="exception">
<% int x = 42/0;%>
</c:catch>
<c:if test = "${exception ne null}">
<p>Exception is : ${exception} <br />
Exception Message: ${exception.message}</p>
</c:if>
```
Обратите внимание что используется язык выражений JSP EL в теге `c:if`.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Как конфигурируется JSP в дескрипторе развертывания.
2017-05-07 07:05:47 +03:00
Для настройки различных параметров JSP страниц используется элемент `jsp-config`, который отвечает за:
+ управление элементами скриптлетов на странице;
+ управления выполнением в языке выражений;
+ определение шаблона URL для encoding;
+ определение размера буфера, который используется для объектов на странице;
+ обозначение групп ресурсов, соответствующих шаблону URL, которые должны быть обработаны как XML документ.
```xml
<jsp-config>
<taglib>
<taglib-uri>http://company.xyz/jsp/tlds/customtags</taglib-uri>
<taglib-location>/WEB-INF/exampleTag.tld</taglib-location>
</taglib>
</jsp-config>
```
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Можно ли использовать Javascript на JSP странице?
2017-05-07 07:05:47 +03:00
Да, это возможно. Несмотря на то, что JSP это серверная технология, на выходе она всё равно создает `HTML` страницу, на которую можно добавлять Javascript и CSS.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Всегда ли создается объект сессии на JSP странице, можно ли отключить его создание?
2017-05-07 07:05:47 +03:00
Jsp-страница, по умолчанию, всегда создает сессию. Используя директиву `page` с атрибутом `session` можно изменить это поведение:
`<%@ page session ="false" %>`
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Какая разница между `JSPWriter` и сервлетным `PrintWriter`?
2017-05-07 07:05:47 +03:00
`PrintWriter` является объектом отвечающим за запись содержания ответа на запрос. `JspWriter` использует объект `PrintWriter` для буферизации. Когда буфер заполняется или сбрасывается, `JspWriter` использует объект `PrintWriter` для записи содержания в ответ.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:01:09 +03:00
## Опишите общие практические принципы работы с JSP.
2017-05-07 07:05:47 +03:00
Хорошей практикой работы с технологией JSP является соблюдение следующих правил:
+ Следует избегать использования элементов скриптлетов на странице. Если элементы _action_, _JSTL_, _JSP EL_ не удовлетворяют потребностям, то желательно написать собственный тег.
+ Рекомендуется использовать разные виды комментариев: так JSP комментарии необходимы для уровня кода и отладки, т.к. они не будут показаны клиенту.
+ Не стоит размещать какой-либо бизнес логики внутри JSP страницы. Страницы должны использоваться только для создания ответов клиенту.
+ Для повышения производительности лучше отключать создание сессии на странице, когда это не требуется.
+ Директивы `taglib`, `page` в начале JSP страницы улучшают читабельность кода.
+ Следует правильно использовать директиву `include` и элемент `jsp:include action`. Первая используется для статических ресурсов, а второй для динамических ресурсов времени выполнения.
+ Обработку исключений нужно производить с помощью страниц ошибок. Это помогает избегать запуска специальных служебных методов и может повысить производительность.
+ Использующиеся CSS и JavaScript должны быть разнесены в разные файлы и подключаться в начале страницы.
+ В большинстве случаев JSTL должно хватать для всех нужд. Если это не так, то в начале следует проанализировать логику своего приложения, и попробовать перенести выполнения кода в сервлет, а далее с помощью установки атрибутов использовать на JSP странице только результат.
[к оглавлению](#servlets-jsp-jstl)
2017-10-21 06:14:08 +03:00
# Источники
2017-05-07 07:05:47 +03:00
+ [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)
2017-10-21 06:01:09 +03:00
+ [Codenet](http://www.codenet.ru/webmast/java/jsp.php)
2019-05-18 10:46:47 +03:00
+ [JavaTalks Articles](https://articles.javatalks.ru/articles/24)
2017-10-21 06:14:08 +03:00
[Вопросы для собеседования](README.md)