Как работает Servlet в Java.

Сегодня пришло время узнать как же работает Servlet, а не просто копировать код и верить мне на слово. Эта статья является продолжением цикла статей о простом сайте на джава, но здесь мы не будем продолжать работать над сайтом, а узнаем, как все работает на низком уровне.

Для тех, кто не в теме: мы пишем простой сайт на языке Java и разбираемся с веб программированием на Java.

Если Вы проделали примеры из прошлых статей, то уже создавали класс, который унаследован от HttpServlet и который и был сервлетом. Мы пока использовали сервлеты только для маппинга страниц, когда отображалась jsp  страница, в зависимости от урл запроса. Это не все, что умеет сервлет.

Сервлет является компонентом приложений Java EE (Enterprise Edition), которые выполняются на стороне сервера, имеют способность обрабатывать клиентские запросы и динамически генерировать ответы на них.

как работает сервлет

Сервлет находится в пакете javax.servlet, который мы добавляли в мавен зависимости в первой статье. Как уже было сказано, сервлет принимает запросы от клиента. Чаще всего это http запросы. Под клиентом в веб программировании имеется браузер. Не путайте с пользователем. Есть несколько типов запросов http:

  • GET;
  • POST;
  • PUT;
  • DELETE.

Есть еще несколько других, но они нам пока не интересны. В этой статье я не буду расписывать разницу между запросами, но знать ее нужно. Хотя бы разницу между гет и пост запросами, которыми мы будем пользоваться. Мы уже писали методы, которые отвечают за обработку этих запросов в сервлете: doGET(), doPost(). На вход они принимал ServletRequest — инкапсулирует связь клиента с сервером; ServletResponse — инкапсулирует обратную связь сервлета с клиентом. ServletRequest и ServletResponse  это интерфейсы, которые тоже находятся в пакете javax.servlet.

Мы использовали только ServletRequest и только малые его функции: получали урл и переводили запрос на jsp. Но ServletRequest дает сервлету доступ к такой информации как имена параметров, переданных клиентом, протоколы, используемые клиентом, имена удаленного хоста создавшего запрос и сервера который их получает. С его помощью можно получать сессию клиента. Для примера я взял сервлет из нашего проекта https://github.com/caligula95/simplewebapp-part2 и прописал несколько методов:

Код    
  1. package com.javamaster.controller;
  2.  
  3. import java.io.IOException;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import javax.servlet.http.HttpSession;
  9.  
  10. /**
  11.  * Servlet implementation class HomeServlet
  12.  */
  13. public class HomeServlet extends HttpServlet {
  14.     private static final long serialVersionUID = 1L;
  15.        
  16.     /**
  17.      * @see HttpServlet#HttpServlet()
  18.      */
  19.     public HomeServlet() {
  20.         super();
  21.         // TODO Auto-generated constructor stub
  22.     }
  23.  
  24.     /**
  25.      * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
  26.      */
  27.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  28.         System.out.println(request.getServletPath());
  29.         System.out.println(request.getServerPort());//порт
  30.         System.out.println(request.getParameter("myParameter"));//получение значения параметна если таковой присутствует
  31.         HttpSession session = request.getSession();//получение сессии
  32.        
  33.         String path = request.getServletPath();
  34.         if (path.equals("/")){
  35.             request.getRequestDispatcher("/WEB-INF/view/index.jsp").forward(request, response);
  36.         }
  37.         else if (path.equals("/welcome")){
  38.             request.getRequestDispatcher("/WEB-INF/view/welcome.jsp").forward(request, response);
  39.         }
  40.     }
  41.  
  42.     /**
  43.      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
  44.      */
  45.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  46.         // TODO Auto-generated method stub
  47.         doGet(request, response);
  48.     }
  49.  
  50. }

Результат выполнения:

/
8080
null

Если мы допишем параметр в нашем урл адресе: http://localhost:8080/?myParameter=Hello world, то получим результат:

/
8080
Hello world

ServletResponse — дает сервлету методы для ответа на запросы клиента:

  • позволяет устанавливать длину содержания и тип MIME ответа;
  • обеспечивает исходящий поток, через который сервлет может отправлять ответные данные;
  • содержит методы, которые позволяют манипулировать информацией заголовка HTTP.

С ним мы подробнее познакомимся в третьей части нашего приложения.

Жизненный цикл сервлета

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

Когда мы только запустили наше приложение Tomcat загрузил и инициализировал наш сервлет вызвав его метод init(). Когда пользователя вводит адрес нашего приложения в браузере или делает запрос другим способом для него создается отдельный поток, в котором вызывается метод service() для обработки запросов клиента. Метод service() предназначен для одновременной обработки множества запросов. Когда приложение завершает работу вызывается метод destroy() и сервлет выгружается из памяти.

Когда мы говорим о том, что вызывается метод service или destroy — это означает, что они могут вызываться без нашего участия. Вы можете например поместить код освобождения занятых сервлетом ресурсов в метод destroy(), но вызывать или переопределять эти методы не обязательно.

Есть много статей, где авторы создают множество сервлетов в одном проекте под каждый отдельный запрос пользователя. Как правило, сервлеты путают с контроллерами Spring фреймворка. Это немного не тот случай. Я не советую Вам создавать множество сервлетов в своем проекте. Многие могут спросить: как тогда обрабатывать множество запросов? Ведь на реальных проектах бывает очень много урл запросов и писать под каждый if-else конструкцию не очень удобно. Отвечаю: есть такой паттерн программирования как команд (Command). С его помощью очень удобно реализовать разные запросы в одном классе. Более детальнее мы будем рассматривать такую реализацию в наших последующих примерах с сайтом на джава.

Сейчас, для Вас главное понять как устроет сервлет, для чего он нужен и как применяется. Все остальное будет понятно по мере разработки приложения.

Добавить комментарий