Часть 5. Сервлеты, Java servlet API. Пишем простое веб-приложение
Этот материал — часть цикла “Введение в Enterprise-разработку”. Предыдущие статьи:
- о сети;
- об архитектуре ПО;
- о протоколах HTTP/HTTPS;
- об основах Maven.
Ты уже умеешь писать Java-приложения, которые выводят текст на консоль, но еще толком не знаешь, как создать свое первое веб-приложение? Отлично, устраивайся поудобнее. В этой статье мы познакомимся с сервлетами и напишем приложение, которым ты сможешь похвастать перед друзьями, не отправляя им джарник и не заставляя их качать джаву. Напишем веб-приложение . Если ты еще не знаком с подходами, которые используются в веб-программировании, советую начать чтение с первой статьи цикла “Введение в Enterprise-разработку”.
Что такое сервлет
Для начала разберемся, что такое сервлет и почему ты так часто слышишь о нем. Java Servlet API — стандартизированный API, предназначенный для реализации на сервере и работе с клиентом по схеме запрос-ответ. Сервлет — это класс, который умеет получать запросы от клиента и возвращать ему ответы. Да, сервлеты в Java — именно те элементы, с помощью которых строится клиент-серверная архитектура. Если помнишь, о ней мы уже говорили в одной из статей цикла. Не будем ходить вокруг да около: давай сразу напишем немного кода.
Что нужно для создания веб-приложения
Для комфортной работы с сервлетами в Java тебе понадобится Intellij IDEA Ultimate Edition. Она платная, но можно активировать 30 дней пробного периода или же пользоваться early access версией — она всегда бесплатная. Также установи сервер нашего приложения — Apache Tomcat. Tomcat — это контейнер сервлетов: именно он обрабатывает входящие запросы извне и передает их нашему приложению. Скачать Tomcat можно по этой ссылке.
Создаем первое веб-приложение
-
В pom.xml добавим зависимость javax.servlet-api и установим packaging war:
4.0.0 org.example servlets 1.0-SNAPSHOT war javax.servlet javax.servlet-api 4.0.1
Класс простого сервлета:
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/hello") public class MainServlet extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < resp.setContentType("text/html"); PrintWriter printWriter = resp.getWriter(); printWriter.write("Hello!"); printWriter.close(); >>
Если все работает, давай разберем код. Чтобы из обычного класса сделать http-сервлет , его нужно унаследовать от класса HttpServlet. Над классом указываем аннотацию @WebServlet(), в которой привязываем (мапим) сервлет к конкретному пути (“/hello”). Эта аннотация появилась только в Java Servlet API 3.0, поэтому в интернете очень много примеров, где мапинг сервлетов происходит через XML-файл. Сейчас это не обязательно. Чтобы обрабатывать GET-запросы , переопределяем метод doGet(). Обрати внимание на аргументы метода — HttpServletRequest и HttpServletResponse. С объекта HttpServletRequest мы можем взять всю необходимую информацию о запросе, в HttpServletResponse можем записать наш ответ и установить необходимые заголовки.
Работа с параметрами и сессией
Усовершенствуем наш сервлет, чтобы он мог обрабатывать параметры запроса и работать с сессией:
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/hello") public class MainServlet extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < HttpSession session = req.getSession(); Integer visitCounter = (Integer) session.getAttribute("visitCounter"); if (visitCounter == null) < visitCounter = 1; >else < visitCounter++; >session.setAttribute("visitCounter", visitCounter); String username = req.getParameter("username"); resp.setContentType("text/html"); PrintWriter printWriter = resp.getWriter(); if (username == null) < printWriter.write("Hello, Anonymous" + "
"); > else < printWriter.write("Hello, " + username + "
"); > printWriter.write("Page was visited " + visitCounter + " times."); printWriter.close(); > >
Сейчас сервлет работает с сессией, увеличивая счетчик visitCounter при каждом посещении страницы. Если атрибут visitCounter еще не создан (при первом посещении страницы), метод getAttribute() вернет null, поэтому нужно проводить проверку на null. То же касается и параметров запроса. Если пользователь не передал параметр username, его значение будет null. В таком случае поприветствуем пользователя как анонимного. Чтобы передать параметр в GET-запросе, используются path-variables, то есть нужно обратиться по ссылке http://localhost:8080/hello?username=Pavel. Подробней об http-запросах можно почитать в предыдущей статье цикла. Теперь у нашего приложения есть минимальная логика, но немного раздражает 404-я ошибка в root-пути. Чтобы исправить ее, создадим еще один сервлет и замапим его на начальную страницу @WebServlet(«/»). Задача этого сервлета — перенаправлять запросы на путь “/hello”. Сделать это можно двумя способами: с помощью forward или redirect. Пожалуй, стоит разобраться, в чем между ними разница. forward — делегирует обработку запроса другому сервлету на сервере, клиент при этом не задействуется. Для этого в метод doGet() нового сервлета нужно добавить такой код:
getServletContext().getRequestDispatcher("/hello").forward(req, resp);
В этом коде мы обращаемся к контексту сервлетов, из него достаем диспетчер запросов нужного сервлета и просим его обработать конкретный запрос с указанными параметрами (req, resp). redirect — возвращает клиенту адрес, по которому нужно обратиться для обработки его запроса. Большинство браузеров переходит на переданную ссылку автоматически. Для реализации редиректа нужно добавить этот код:
resp.sendRedirect(req.getContextPath() + "/hello");
Мы в HttpServletResponse вызываем метод redirect() и передаем ему адрес, на который клиенту нужно обратиться. Важная деталь: http-параметры нужно также добавить в конце полного пути редиректа, что не очень удобно. В нашей ситуации предпочтительнее использовать forward, а бывает так, что лучше — redirect. Если будешь понимать разницу в их работе, не ошибешься с выбором. Код нового сервлета выглядит так:
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/") public class IndexServlet extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < // getServletContext().getRequestDispatcher("/hello").forward(req, resp); resp.sendRedirect(req.getContextPath() + "/hello"); >>
Итог
Твое первое веб-приложение готово. В следующей статье ты узнаешь, как развернуть его без использования Intellij IDEA. Мы написали приложение, которое обрабатывает только GET-запросы. Остальные http-методы обрабатываются аналогичным образом — переопределяя соответствующие методы родительского класса. Используя такие простые сервлеты, можно строить сложные многофункциональные веб-приложения. Конечно, используя большие фреймворки типа Spring это делать намного проще. Но если очень хочется вникнуть подробнее во все возможности сервлетов, можешь почитать официальную спецификацию. Часть 6. Контейнеры сервлетов Часть 7. Знакомство с паттерном MVC (Model-View-Controller) Часть 8. Пишем небольшое приложение на spring-boot
Что такое сервлеты java
Сервлет — это класс Java, используемый для расширения возможностей сервера, на котором размещаются приложения и доступ к которому осуществляется по модели запрос-ответ. Хотя сервлеты могут отвечать на любые запросы, они обычно используются для расширения приложений, размещаемых на веб-серверах. Для таких приложений технология Java Servlet определяет специфичные для HTTP классы сервлетов.
Пакеты javax.servlet и javax.servlet.http предоставляют интерфейсы и классы для написания сервлетов. Все сервлеты должны реализовывать интерфейс Servlet , который определяет методы жизненного цикла. Наиболее общий сервис может быть реализован с использованием или расширением класса GenericServlet , предоставляемого с API сервлетов Java. Класс HttpServlet предоставляет методы, такие как doGet и doPost , для обработки специфичных для HTTP сервисов.
Назад | Вперёд |
Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)
Руководство по Servlets. Введение.
В данной статье мы рассмотрим основы Java Servlets (далее – сервлеты).
Сервлеты – это Java программы, которые работают на сервере и являются обработчиками запросов. Эти запросы приходят от HTTP клиента и Java приложением (HTTP сервер), либо базой данных (далее – БД).
Сервлеты позволяют нам предавать данные, полученные с веб-страницы и выводить данные из БД (или приложения) в окно браузера.
- высокая производительность
- платформо-независимы
- возможность использования всех преимуществ Java
- работают в адресном пространстве веб-сервера – нет необходимости создавать отдельные процессы для каждого запроса от клиента.
Ниже представлена, общая архитектура Java приложения, которое использует сервлеты:
От HTTP клиента приходит запрос. Данный запрос обрабатывается сервлетом, далее – идёт работа классов, которые связаны с БД.
Если запрос был корректным, то в результате сервер возвращает ответ.
Сервлеты выполняют следующие задачи:
- Чтение и анализ HTTP запроса от клиента
- Обработка данных
- Передача данных HTTP клиенту
- Передача HTTP ответа клиенту
Java классы, которые представляют собой сервлеты. Они находятся в пакетах javax.servlet и javax.servlet.http.
Требования к данным классам изложены в Java Servlet Specification (Март 2017 – версия 3.0).
На этом мы заканчиваем обзор Java сервлетов.
В следующей статье мы рассмотрим жизненный цикл сервлетов.
Что такое сервлет и зачем нужен портлет?
И так, дорогие друзья, я планирую открыть блог, посвящённый портальным технологиям.
Для разогрева, предлагаю вам коротенький рассказик, прочитав которую, вы узнаете что такое сервлет и зачем изобрели портлет. Места мало, обо всем напишу кратенько. Переписывать книжки, коих выпущено не одна сотня, я не собираюсь. Я буду писать о общих вещах, а так же о приёмах, которые существенно упрощают жизнь разработчику. Если вы хотите узнать больше, то лучше http://java.sun.com/javaee/index.jsp
вряд ли что-то может быть.
Приготовьтесь, вы ощутите мощь Java EE.
Интро
Пишем мы портлеты на Джаве (Java). Что же такое портлет (portlet)? Портлет, это по своей сути -— сервлет (servlet).
Servlet
Это класс, расширяющий HttpServlet, у которого есть два главных метода
void doGet(HttpServletRequest request, HttpServletResponse response)<>
void doPost(HttpServletRequest request, HttpServletResponse response)<>
Не секрет, что браузер может инициировать два вида запроса к серверу: пост (POST) и гет (GET).
Как вы уже догадались, первый метод сработает при запросе GET к сервлету, второй — при запросе POST.
Можно переопределить третий главный метод
void processRequest(HttpServletRequest request, HttpServletResponse response)<>
Он будет обрабатывать и геты и посты, приходящие к сервлету.
Параметры запроса мы вытаскиваем из request, результат записываем в response. Респонс уходит к браузеру клиента.
Можно получить какой-то конкретный параметр, список всех имен, карту (Map).
Map -— это интерфейс, смысл его заключается в том, что он хранит ключ и значение, связанных с ключом. В случае с параметрами запроса, ключом является имя параметра, значением -— значение параметра (железная логика).
Например, пользователь заполнил форму регистрации и отправил её на сервер:
lolik.ru/registrationservlet?name=lolos&surname=lolobot&age=102
Карта параметров будет выглядеть следующим образом:
name->lols
age->102
surname->lolobot
Если интересно, о картах и прочих вкусностях Java SE мы можем поговорить отдельно.
Значениями параметров реквеста могут быть только строки (String), которые можно привести к нужному типу. Очевидно, значение age лучше превратить в целое число (int или Integer).
Посмотрим на метод:
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException response.setContentType(«text/html;charset=UTF-8»);
PrintWriter out = response.getWriter();
try out.println(«»);
out.println(«»);
out.println(«Servlet MyServlet»);
out.println(«»);
out.println(«»);
out.println(«
Servlet MyServlet at » + request.getContextPath () + «
«);
out.println(»
lols!
«);
out.println(«»);
out.println(«»);
> finally <
out.close();
>
>
Берём респонс, пихаем в него html и отправляем пользователю.
Ремарка:
Спасибо zer0access за то, что поправил меня. Пройдя по ссылке java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html вы увидите, что есть ещё методы, кроме doGet и doPost.
Метод processRequest генерируется рядом IDE, например NetBeans 6.1 Делается это следующим образом:
/**
* Handles the HTTP GET method.
* param request servlet request
* param response servlet response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException processRequest(request, response);
>
/**
* Handles the HTTP POST method.
* param request servlet request
* param response servlet response
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException processRequest(request, response);
>
т.е. описав метод processRequest, ваши doPost и doGet отработают единообразно. Если есть разница при вызове doPost или doGet, то использовать processRequest врядли придётся.
Метод service первым принимает запрос, после запрос переправляется нужному doXxx. В service можно сделать какие-то общие операции, например сделать запись в БД, что такой-то пользователь обратился к такому-то сервлету, затем запрос передается на обработку нужному методу сервлета.
zer0access, спасибо тебе.
Всем сервлеты хороши, но только один сервлет может быть на странице. Два сервлета не влезут — слишком важные персоны.
Как же быть, если очень хочется на одну страницу поместить сервлет-калькулятор и сервлет-переводчик?
Portlet
Очень просто — написать два портлета, один будет считать, второй — переводить. Два, три, много портлетов можно поселить на одной странице. Классический портлет в редакции Sun имеет три режима: view, edit, help. Первый — основной, его видит пользователь. В случае калькулятора, в режиме view (просмотр) будут доступны кнопки. В режиме edit (настройки), например, можно задавать тип калькулятора: обычный или научный, с синусами, косинусами и прочими мудрёными вещами. В режиме help (справка)? как вы уже догадались, будет справка по калькулятору.
Режимы view, edit, help отображаются при помощи jsp (java server pages). Они очень-очень похожи на php-страницы:
Вывод в столбик чисел от 1 до 10 включительно.
можно заменить на (как тут пхпшный код-то писать?) и разницы не будет (за исключением того, что Джава требует определения типов переменных).
С режимом view и help все понятно, а зачем нужен режим edit? Допустим, У нас на портале есть две группы пользователей: первая — бухгалтеры, вторая — мы с вами, программисты. Бухгалтерам достаточно обычного калькулятора, где есть +,-,*,/, а нам нужно складывать двоичные числа. В этом случае администратор портала для группы бухгалтеров настроит портлет, как обычный калькулятор, а для нашей группы, как научный.
Чувствуете какой кайф?
Портлет, считай, как маленькое веб-приложение, которое можно поместить на страничку портала и настроить (если возможность реализована программистом) под конкретные нужды пользователя. Можно комбинировать разные портлеты на одной странице.
В следующем номере мы поговорим о портлетах более подробно. Я расскажу, как можно за 5 минут настроить сервер приложений, контейнер для портлетов и как отлаживаться на всем этом хозяйстве нажатием одной кнопки.