Ответы на вопросы на собеседование JSP, Servlets, JSTL (часть 2).
- Каков жизненный цикл сервлета и когда какие методы вызываются?
Контейнер сервлетов управляет четырьмя фазами жизненного цикла сервлета:
- Загрузка класса сервлета - когда контейнер получает запрос для сервлета, то происходит загрузка класса сервлета в память и вызов конструктора без параметров.
- Инициализация класса сервлета - после того как класс загружен контейнер инициализирует объект ServletContext для этого сервлета и внедряет его через init() метод. Это и есть место где сервлет класс преобразуется из обычного класса в сервлет.
- Обработка запросов - после инициализации сервлет готов к обработке запросов. Для каждого запроса клиента сервлет контейнер порождает новую нить (поток) и вызывает метод service() путем передачи ссылки на объект ответы и запроса.
- Удаление из Service - когда контейнер останавливается или останавливается приложение, то контейнер сервлетов уничтожает классы сервлетов путем вызова destroy() метода.
Можно описать как последовательность вызова методов: init(), service(), destroy().
- public void init(ServletConfig config) - используется контейнером для инициализации сервлета. Вызывается один раз за время жизни сервлета.
- public void service(ServletRequest request, ServletResponse response) - вызывается для каждого запроса. Метод не может быть вызван раньше выполнения init() метода.
- public void destroy() - вызывается для уничтожения сервлета (один раз за время жизни сервлета).
- Какие методы необходимо определить при создании сервлетов?
Чтобы создать сервлет, необходимо описать сервлет с помощью:
Затем расширить класс сервлета от класса HttpServlet.
Реализовать метод service() или doGet(), doPost() (или первый или вторые).
Метод service() переопределяется, когда мы хотим, чтобы сервлет обрабатывал как GET так и POST запросы в одном методе. Когда контейнер сервлетов получает запрос клиента, то происходит вызов метода service(), который в свою очередь вызывает doGet(), doPost() методы, основанные на HTTP методе запроса. Есть мнение, что метод service() переопределять особого смысла нет, кроме указанного вначале случая использования одного метода на два типа запросов.
Такая возможность есть, но считается бессмысленной. Инициализировать данные лучше переопределив метод init(), в котором получить доступ к параметрам инициализации сервлета через использование объекта ServletConfig.
Абстрактный класс GenericServlet - независимая от используемого протокола реализация интерфейса Servlet. HttpServlet, как понятно из название, реализация интерфейса сервлета для протокола HTTP. Следует отметить, что HttpServlet extends GenericServlet.
Если необходимо вызывать сервлет из того же приложения, то необходимо использовать механизм внутренней коммуникации сервлетов. Мы можем вызвать другой сервлет с помощью RequestDispatcher forward() и include() методов для доступа к дополнительным атрибутам в запросе для использования в другом сервлете. Метод forward() используется для передачи обработки запроса в другой сервлет. Метод include() используется, если мы хотим вложить результат работы другого сервлета в возвращаемый ответ.
Если необходимо вызывать сервлет из другого приложения, то использовать RequestDispatcher уже не получится (определен для приложения). Поэтому можно использовать ServletResponse sendRedirect() метод и предоставить полный URL из другого сервлета. Для передачи данных можно использовать cookies как часть ответа сервлета, а потом использовать их в нашем сервлете.
Методы класса HTTPServlet init() и destroy() вызываются один раз за жизненный цикл сервлета - поэтому по поводу них беспокоиться не стоит. Методы doGet(), doPost() вызываются на каждый запрос клиента и т.к. сервлеты используют многопоточность, то здесь нужно задумываться о потокобезопасной работе.
В случае наличия локальных переменных в этих методах нет необходимости думать о многопоточной безопасности, т.к. они будут созданы отдельно для каждой нити. Но если используются глобальные ресурсы, то необходимо использовать синхронизацию как и в любом многопоточном приложении Java.
HTTP метод называется неизменяемым, если он всегда возвращает одинаковый результат. HTTP методы GET, PUT, DELETE, HEAD, OPTIONS являются неизменяемыми. Необходимо реализовывать приложение так, чтобы эти методы возвращали одинаковый результат. К изменяемым методам относится HTTP метод POST. Post метод используется для реализации чего-либо, что изменяется при каждом запросе.
К примеру, для доступа к HTML странице или изображению необходимо использовать метод GET, т.к. он возвращает одинаковый результат. Но если нам необходимо сохранить информацию о заказе в базе данных, то нужно использовать POST метод. Неизменяемые методы так же известны как безопасные методы и нет необходимости заботится о повторяющихся запросах от клиента для этих методов.
Метод doGet() - используется для запроса содержимого указанного ресурса, изображения или гипертекстового документа. Вместе с за просом могут передаваться дополнительные параметры как часть URI, значения могут выбираться из полей формы или передаваться непосредственно через URL. При этом запросы кэшируются и имеют ограничения на размер. Этот метод является основным методом взаимодействия браузера клиента и веб-сервера.
Метод doPost() - используется для передачи пользовательских данных в содержимом HTTP-запроса на сервер. Пользовательские данные упакованы в тело запроса согласно полю заголовка Content-Type и/или включены в URI запроса. При использовании метода POST под URI подразумевается ресурс, который будет обрабатывать запрос.
В спецификации HTTP определены методы: GET, HEAD, POST, PUT, DELETE, OPTIONS и TRACE.
Класс HTTPServlet предоставляет реализацию HTTP протокола сервлета (а следовательно помогает избежать постоянного кодинга повторяющейся информации), но он не имеет реализованных методов doGet() и doPost() (у них по умолчанию возвращение HTTP 405 Method Not Implemented error), а следовательно объявлен абстрактным. Реализация этих методов перекладывается на разработчика.
Основные отличия:
Технология сервлетов была создана для преодоления недостатков Common Gateway Interface (общий интерфейс шлюза). Можно выделить следующие преимущества сервлетов над CGI:
Некоторые из них:
Мы не можем создать два объекта этих классов в одном сервлете. При попытке внедрить оба метода getWriter() и getOutputStream() в ответе, мы получим исключение java.lang.IllegalStateException с сообщением, что уже другой метод был вызван для этого ответа.
Интерфейс был создан, чтобы гарантировать потокобезопасность и невозможность создания двух нитей в сервис методе сервлета. Однако интерфейс SingleThreadModel не решает всех проблем потокобезопасности. Например, атрибуты сессии или статические переменные могут быть доступны различным запросам в различных потоках в одно и тоже время (даже при использовании этого интерфейса). Интерфейс объявлен deprecated начиная с Servlet 2.4.
Атрибуты сервлетов используются для внутренней коммуникации сервлетов. Мы можем использовать атрибуты set, get, remove в веб приложении.
Интерфейсы ServletRequest, HttpSession и ServletContext предоставляют методы для get(), set(), remove() атрибутов из request scope, session scope, application scope.
Если нам необходимо инициализировать какие-то ресурсы до того как сервлет начнет обрабатывать запросы, то необходимо переопределить метод init(). Если переопределить метод init(ServletConfig config), то первым должен быть вызван метод super(config), который обеспечит вызов метода init(ServletConfig config) суперкласса. Именно поэтому GenericServlet предоставляет другой метод init() без параметров, который будет вызываться в конце метода init(ServletConfig config). Разработчик должен использовать переопределенный метод init() без параметров для инициализации переменных для избежания каких-либо проблем, например не указав вызов super() в переопределенном методе init(ServletConfig config).
URL Encoding - процесс преобразования данных в форму CGI (Common Gateway Interface), который позволит путешествовать по сети без проблем. URL Encoding разделяет пробелы и заменяет специальные символы с помощью escape-символов. Например, для кодирования строки используется метод java.net.URLEncoder.encode(String str, String unicode). Обратная операция декодирования возможна благодаря методу java.net.URLDecoder.decode(String str, String unicode). Пример работы метода: строка “ Java programing language” будет преобразована в “Java%20programing%20language ”.
Реализовать метод service() или doGet(), doPost() (или первый или вторые).
- В каком случае вы будете переопределять метод service()?
Метод service() переопределяется, когда мы хотим, чтобы сервлет обрабатывал как GET так и POST запросы в одном методе. Когда контейнер сервлетов получает запрос клиента, то происходит вызов метода service(), который в свою очередь вызывает doGet(), doPost() методы, основанные на HTTP методе запроса. Есть мнение, что метод service() переопределять особого смысла нет, кроме указанного вначале случая использования одного метода на два типа запросов.
- Есть ли смысл определить конструктор для сервлета? Как лучше инициализировать данные?
Такая возможность есть, но считается бессмысленной. Инициализировать данные лучше переопределив метод init(), в котором получить доступ к параметрам инициализации сервлета через использование объекта ServletConfig.
- В чем отличия GenericServlet и HttpServlet?
Абстрактный класс GenericServlet - независимая от используемого протокола реализация интерфейса Servlet. HttpServlet, как понятно из название, реализация интерфейса сервлета для протокола HTTP. Следует отметить, что HttpServlet extends GenericServlet.
- Как вызвать из сервлета другой сервлет этого же и другого приложения?
Если необходимо вызывать сервлет из того же приложения, то необходимо использовать механизм внутренней коммуникации сервлетов. Мы можем вызвать другой сервлет с помощью RequestDispatcher forward() и include() методов для доступа к дополнительным атрибутам в запросе для использования в другом сервлете. Метод forward() используется для передачи обработки запроса в другой сервлет. Метод include() используется, если мы хотим вложить результат работы другого сервлета в возвращаемый ответ.Если необходимо вызывать сервлет из другого приложения, то использовать RequestDispatcher уже не получится (определен для приложения). Поэтому можно использовать ServletResponse sendRedirect() метод и предоставить полный URL из другого сервлета. Для передачи данных можно использовать cookies как часть ответа сервлета, а потом использовать их в нашем сервлете.
- Стоит ли волноваться о "многопоточной безопасности" работая с сервлетами?
Методы класса HTTPServlet init() и destroy() вызываются один раз за жизненный цикл сервлета - поэтому по поводу них беспокоиться не стоит. Методы doGet(), doPost() вызываются на каждый запрос клиента и т.к. сервлеты используют многопоточность, то здесь нужно задумываться о потокобезопасной работе.В случае наличия локальных переменных в этих методах нет необходимости думать о многопоточной безопасности, т.к. они будут созданы отдельно для каждой нити. Но если используются глобальные ресурсы, то необходимо использовать синхронизацию как и в любом многопоточном приложении Java.
- Какой метод HTTP не является неизменяемым?
HTTP метод называется неизменяемым, если он всегда возвращает одинаковый результат. HTTP методы GET, PUT, DELETE, HEAD, OPTIONS являются неизменяемыми. Необходимо реализовывать приложение так, чтобы эти методы возвращали одинаковый результат. К изменяемым методам относится HTTP метод POST. Post метод используется для реализации чего-либо, что изменяется при каждом запросе.К примеру, для доступа к HTML странице или изображению необходимо использовать метод GET, т.к. он возвращает одинаковый результат. Но если нам необходимо сохранить информацию о заказе в базе данных, то нужно использовать POST метод. Неизменяемые методы так же известны как безопасные методы и нет необходимости заботится о повторяющихся запросах от клиента для этих методов.
- Какие есть методы отправки данных с клиента на сервер? Чем они отличаются?
Метод doGet() - используется для запроса содержимого указанного ресурса, изображения или гипертекстового документа. Вместе с за просом могут передаваться дополнительные параметры как часть URI, значения могут выбираться из полей формы или передаваться непосредственно через URL. При этом запросы кэшируются и имеют ограничения на размер. Этот метод является основным методом взаимодействия браузера клиента и веб-сервера.Метод doPost() - используется для передачи пользовательских данных в содержимом HTTP-запроса на сервер. Пользовательские данные упакованы в тело запроса согласно полю заголовка Content-Type и/или включены в URI запроса. При использовании метода POST под URI подразумевается ресурс, который будет обрабатывать запрос.
- Методы сервлета (обычно имеется ввиду HttpServlet).
В спецификации HTTP определены методы: GET, HEAD, POST, PUT, DELETE, OPTIONS и TRACE.- Метод GET (method="GET") используется для запроса содержимого указанного ресурса, изображения или гипертекстового документа. Вместе с запросом могут передаваться дополнительные параметры как часть URI, значения могут выбираться из полей формы или передаваться непосредственно через URL. При этом запросы кэшируются и имеют ограничения на размер. Этот метод является основным методом взаимодействия браузера клиента и веб-сервера.
- Метод POST используется для передачи пользовательских данных в содержимом HTTP-запроса на сервер. Пользовательские данные упакованы в тело запроса согласно полю заголовка Content-Type и/или включены в URI запроса. При использовании метода POST под URI подразумевается ресурс, который будет обрабатывать запрос.
- Метод PUT схож с методом POST за тем исключением, что здесь URI подразумевает ресурс, который будет создан или сохранен на сервере в результате выполнения PUT-запроса.
- Метод DELETE предназначен для удаления целевого ресурса.
- Метод HEAD предполагает возврат сервером такого же ответа, как и при использовании GET, но без тела ответа. Метод обычно используется для того, чтобы проверить существование ресурса либо узнать, изменился ли запрашиваемый ресурс с момента последнего обращения.
- Метод OPTIONS должен возвращать информацию о возможностях вебсервера или параметрах соединения для конкретного ресурса.
- Метод TRACE возвращает клиенту запрос в том виде, в каком он пришел на сервер - используется для отладки, определяя заголовки, добавляемые промежуточными серверами, а также для тестирования настроек соединения.
- Почему HttpServlet класс объявлен как абстрактный?
Класс HTTPServlet предоставляет реализацию HTTP протокола сервлета (а следовательно помогает избежать постоянного кодинга повторяющейся информации), но он не имеет реализованных методов doGet() и doPost() (у них по умолчанию возвращение HTTP 405 Method Not Implemented error), а следовательно объявлен абстрактным. Реализация этих методов перекладывается на разработчика.
- В чем разница между методами GET и POST?
Основные отличия:- GET метод является неизменяемым, тогда как POST - изменяемый.
- С помощью метода GET можно посылать ограниченное кол-во данных, которые будут пересланы в заголовке URL. В случае POST метода мы можем пересылать большие объемы данных, т.к. они будут находится в теле метода.
- Данные GET метода передаются в открытом виде, что может использоваться в зловредных целях. POST данные передаются в теле запроса и скрыты от пользователя.
- GET метод является HTTP методом по умолчанию, а POST метод необходимо указывать явно, чтобы отправить запрос.
- GET метод используется гиперссылками на странице.
- Назовите преимущества Servlet над CGI?
Технология сервлетов была создана для преодоления недостатков Common Gateway Interface (общий интерфейс шлюза). Можно выделить следующие преимущества сервлетов над CGI:- Сервлеты предоставляют лучшую производительность в условиях обработки запросов, лучшее использование памяти за счет использования преимущества многопоточности (на каждый запрос создается новая нить, что быстрее выделения памяти под новый объект для каждого запроса, как это происходит в CGI).
- Сервлеты, платформа и система являются независимыми. Таким образом веб приложение написанное с использованием сервлетов может быть запущена в любом контейнере сервлетов, реализующим стандарт и в любой операционной системе.
- Использование сервлетов повышает надежность программы, т.к. контейнер сервлетов самостоятельно заботится о жизненном цикле сервлетов (а значит и за утечками памяти), безопасности и сборщике мусора.
- Сервлеты относительно легки в изучении и поддержке, т.к. разработчику необходимо заботится только о бизнес логике приложения, а не внутренней реализации веб технологий.
- Каковы наиболее распространенные задачи выполняются в Servlet контейнере?
Некоторые из них:- Поддержка обмена данными. Контейнер сервлетов предоставляет легкий способ обмена данными между веб клиентом (браузером) и сервлетом. Благодаря контейнеру нет необходимости создавать слушателя сокета на сервере для отслеживания запросов от клиента, а также разбирать запрос и генерировать ответ. Все эти важные и комплексные задачи решаются с помощью контейнера и разработчик может сосредоточиться на бизнес логике приложения.
- Управления жизненным циклом сервлетов и ресурсов. Начиная от загрузки сервлета в память, инициализации, внедрения методов и заканчивая уничтожением сервлета. Контейнер так же предоставляет дополнительные утилиты, например JNDI, для управления пулом ресурсов.
- Поддержка многопоточности. Контейнер самостоятельно создает новую нить для каждого запроса и предоставляет ей запрос и ответ для обработки. Таким образом сервлет не инициализируется заново для каждого запроса и тем самым сохраняет память и уменьшает время до обработки запроса.
- Поддержка JSP. JSP классы не похожи на стандартные классы джавы, но контейнер сервлетов преобразует каждую JSP в сервлет и далее управляется контейнером как обычным сервлетом.
- Различные задачи. Контейнер сервлетов управляет пулом ресурсов, памятью приложения, сборщиком мусора. Предоставляются возможности настройки безопасности и многое другое.
- В чем разница между PrintWriter и ServletOutputStream?
PrintWriter - это класс для работы с символьным потоком, а ServletOutputStream - класс для работы байтовым потоком. PrintWriter используется для записи информации на основе символов, вроде массива символов или строки в ответ, в то время как ServletOutputStream используется для записи в ответ массива байтов. Для получения экземпляра ServletOutputStream используется метод ServletResponse getOutputStream(), а для PrintWriter - метод ServletResponse getWriter().
- Можем ли мы получить PrintWriter и ServletOutputStream одновременно в сервлете?
Мы не можем создать два объекта этих классов в одном сервлете. При попытке внедрить оба метода getWriter() и getOutputStream() в ответе, мы получим исключение java.lang.IllegalStateException с сообщением, что уже другой метод был вызван для этого ответа.
- Расскажите об интерфейсе SingleThreadModel.
Интерфейс был создан, чтобы гарантировать потокобезопасность и невозможность создания двух нитей в сервис методе сервлета. Однако интерфейс SingleThreadModel не решает всех проблем потокобезопасности. Например, атрибуты сессии или статические переменные могут быть доступны различным запросам в различных потоках в одно и тоже время (даже при использовании этого интерфейса). Интерфейс объявлен deprecated начиная с Servlet 2.4.
- Какие существуют атрибуты у сервлетов и какая сфера их применения?
Атрибуты сервлетов используются для внутренней коммуникации сервлетов. Мы можем использовать атрибуты set, get, remove в веб приложении.Интерфейсы ServletRequest, HttpSession и ServletContext предоставляют методы для get(), set(), remove() атрибутов из request scope, session scope, application scope.
В первом вопросе в инициализации должен быть ServletConfig а не ServletContext
ОтветитьУдалить