Создание сервлетов для чайников. Пошаговое руководство

image

Когда начинающий разработчик сталкивается с сервлетами, ему бывает очень сложно понять, как он работает и от чего зависит эта работа. Всё потому, что все примеры и видеоуроки рассчитаны на людей, понимающих природу сервлетов и что за чем следует. Поэтому я решил написать руководство по созданию самых простых сервлетов. Возможно, эта статья кому-нибудь поможет.

Итак.

Предположим, что Вы уже где-то скачали пример с применением maven и Вам удалось задеплоить Ваш код на Tomcat (с этого обычно начинается познание сервлетов) любым способом (WAR-архивом или прямо из среды разработки). Вы имеете структуру приложения, в которой присутствует файл web.xml. C него и надо начинать создание страниц.

Первое и самое важное: машина не видит прямой связи между куском адресной строки и одноимённой страницей в Вашем проекте. localhost:8080/имя_WAR/test и test.jsp — не одно и то же. /test — это «url-метка» сервлета. По которой машина находит нужный Java-файл и тот уже указывает на test.jsp.

Путь от чтения кода машиной и до отображения страницы в браузере выглядит так:

webapp/WEB-INF/web.xml -> servlet
---> ru.user.project/web/ClassName -> request
---> page.jsp

Да, пока ничего не понятно, но мы ещё вернёмся к этой схеме. Если описать её простыми человеческими словами, то это будет выглядеть так:

Из файла web.xml через сервлет машина получает путь к Java-классу, который, в свою очередь, направляет машину на искомую страницу.

Это было лирическое отступление, переходим к коду.

Итак, мы имеем задеплоенный на Tomcat проект, главная страница которого открывается по вызову localhost:8080/имя_WAR (если мы деплоили WAR-файл).

Открываем web.xml. Этот файл сканируется Tomcat'ом в первую очередь. Здесь мы и зададим начало пути. Вот код нашего web.xml:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
		 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <display-name>Test</display-name>

    <servlet>
        <servlet-name>testServlet</servlet-name>
        <servlet-class>ru.user.project.web.TestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>

</web-app>

Сервлет связывает ссылку из адресной строки и Java-класс. Java-класс, в нашем случае, открывает JSP-страницу. Сервлет состоит из 2 составляющих:

<servlet>    //здесь прописан путь к Java-классу
        <servlet-name>testServlet</servlet-name>
        <servlet-class>ru.user.project.web.TestServlet</servlet-class>
    </servlet>
    <servlet-mapping>    //здесь прописан путь к куску адресной строки, вызывающей сервлет
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>

Прописываем <servlet-class>. По этому пути хранится Java-класс, который обработается при вызове адресной строки. Потом дописываем <servlet-mapping>. Это кусок адреса из адресной строки, привязанный к сервлету. Когда мы допишем к нашей первоначальной строке /test, начнётся магия. Но пока мы ещё не дописали остальную часть кода. Пишем Java-файл. Он у нас находится по адресу ru.user.project.web (для этого нужно создать папку web, если её нет).

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by promoscow on 17.07.17.
 */
public class TestServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/test.jsp").forward(request, response);
    }
}

Класс надо унаследовать от HttpServlet и переопределить метод doGet(); В переопределённом методе мы пишем название строки, на которую будет осуществлён переход (в нашем случае, это "/test.jsp".

Таким образом, при вызове адреса localhost:8080/имя_WAR/test Tomcat находит нужный <url-pattern>, выясняет, что он принадлежит testServlet, далее видит, что этому testServlet принадлежит Java-файл TestSevlet, исполняет его, а в Java-файле идёт переход на test.jsp. Осталось написать test.jsp:

<%--
  Created by IntelliJ IDEA.
  User: promoscow
  Date: 17.07.17
  Time: 23:22
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Test</title>
</head>
<body>
Hey there! It's test servlet page!
</body>
</html>

Теперь, когда пользователь допишет /test к изначальному адресу, выполнится алгоритм, описанный в начале статьи (помните, я обещал к ней вернуться?) и браузер покажет содержимое файла test.jsp. Также, можно, например, написать в стартовом файле (например, index.html) ссылку:

<a href="test">Test page</a>

И произойдёт вышеописанная цепь событий, которая вызовет, в итоге, страницу test.jsp.

Надеюсь, эта статья поможет барахтающимся в поисках здравого смысла начинающим разработчикам написать первый сервлет, а уже в дальнейшем к этому пониманию постепенно будет присоединяться всё остальное (как это обычно бывает).
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 28

  • НЛО прилетело и опубликовало эту надпись здесь
      +1
      Больше похоже на небольшой рандомный кусок из какого-то руководства, чем на полезную статью.
        0
        При чем руководство это, судя по всему, немножно устаревшее
        0
        А ничего что jsp это тоже сервлет?
          +3
          Дорогие начинающие Java-разработчики (и автор?), пользуясь случаем очень хочется сказать пару вещей. Во первых, не обращайте внимания на комментарии, некоторые люди легко забывают что сами когда-то продирались через дебри мутной и пугающей документации для сервлет контейнеров, чтобы понять что вообще там к чему. Во-вторых, не думайте сильно сервлетами и прочими низкоуровневыми абстракциями.

          Первая реакция, которая возникает, когда пытаешься задеплоить Hello World в сервлет контейнер, даже следуя такому простому и понятному руководству, как в этой статье — это ужас. Особенно после простых, как бревно, Node.js, PHP, Python. И наверное возникает мысль «Зачем люди так делают?!». Так вот, в целом — не делают. Сейчас на уровне сервлетов пишут и мыслят только разработчики фреймворков, для обычных разработчиков знать и понимать их полезно, но возможно не в самую первую очередь.

          Так вот, если вы смотрите на то, чтобы начать web-разработку на Java в 2017, я бы порекомендовал следующее:
          1. Особо не погружайтесь в дебри JSP или сервлетов. Берите простой и понятный веб-фреймворк, типа Spark, Ninja, Jooby — там все очень удобно и понятно. Плюс современные и приличные движки для шаблонов, а не (кхм) JSP.

          Вот пример на Spark:
          import static spark.Spark.*;
          
          public class HelloWorld {
              public static void main(String[] args) {
                  get("/hello", (req, res) -> "Hello World");
              }
          }
          


          2. Не разбирайтесь (пока) в тонкостях сервлет-контейнеров и деплоя WAR, любой фреймворк даст embedded сервер, который запустится в командной строке

          3. Даже не смотрите (пока) на сервера приложений и Java EE, там сразу слишком много новых концепций. Если хочется современного энтерпрайза — можно посмотреть на Spring, начиная с малого. Вопреки популярному заблуждению, он простой, легкий, и удобный для новичков — если брать Spring Boot.

          Современная Java это все-таки не совсем ужас-ужас, вот эти все килобайты XML и JSP сейчас, к счастью, не нужны чтобы начать писать web-приложения.
            0
            P.S. Если все таки Spring — то есть супер вещь Spring Initializr, он может сгенерить (если выбрать Web зависимость) готовый и настроенный Maven / Gradle Спринг проект, в котором все сразу будет работать и который можно будет запустить из Idea или командной строки.
              0
              Огромное спасибо за наводку.
                0

                Не соглашусь. По опыту моего обучения:


                • Считаю, что осваивать web, особенно новичкам, следует с сервлетов. Самое примитивное CRUD приложение на сервлетах. Разобраться не так сложно. А если таки сложно-приглашаю на свою практику по Java.
                  Spark, Ninja, Jooby — это все круто, модно и удобно но не для начинающих. Если вы напишите в резюме что работали с этими фреймворками и не сможете ответить на элементарный вопрос про сервлет на собеседовании шансов, что вас возьмут будет 0.

                Некоторые вообще рекомендуют начинать изучение Java без IDE (я к ним не отношусь).
                Для новичков самое основное- понимать, КАК внути все это работает. Я собеседовал людей, которые изучали Spring без знания основ (а сервлеты это основы). Ужастно. Николай Алименков задает новичкам на собеседовании вопросы, поверх чего реализован Hibernate. Если вы не ответите, что JBDC и не будете иметь про него представление- кому нужен такой разработчик?


                • Про JSP — с 2005 года я поработал более чем на 10 проектах. В 60% использовался JSP. Почему? Да потому что встроено в Tomcat (42% по статистике 2016 г) и на нем выводят что-то достаточно примитивное. Остальное делается в основном на js фреймворках. И еще потому что в основном проекты уже N-летней давности. И в 90% смысла переписывать JSP на чтото другое никакого. Далее — если вы знаете JSP, то например освоить Thymleaf или любой другой шаблонизатор будет легче. А сам JSP достаточно простой.


                • изучать Spring MVC можно только после того, как будете знать что такое сервлет. Тогда будет понятно что такое DispatcherServlet и паттерн Front Controller
                  Как можно работать со спринг не зная HttpServletRequest и прочие 5 основных классов сервлетов? Как вы будете его хотя бы дебажить?


                • НЕ беритесь за Spring-Boot, пока не освоили Spring. Точнее не так: все зависит от ваших задач. Если вам надо быстро написать небольшое работающее приложение- отличный выбор. Но если вы хотите стать Java разработчиком, пройти собеседование, устроится на работу и использовать Boot на больших проектах- не ваш вариант. Для вас это будет черный ящик, полный магии.

                Те еще раз- джуниорам нужно учить именно основы и то, что требуется в вакансиях. Проверить легко: на hh в поиске работы по ключевым словам, ограничив область поиска разработкой ПО.


                Напоследок приведу цитату


                Любое знание стоит воспринимать как подобие семантического дерева: убедитесь в том, что понимаете фундаментальные принципы, то есть ствол и крупные ветки, прежде чем лезть в мелкие листья-детали. Иначе последним не на чем будет держаться.

                Илон Маск

                  0
                  А как же вы в Spring страницы собираетесь делать без JSP?
                    0
                    А как одно зависит от другого?
                  0
                  Эм… Так ведь 2017 год на дворе.
                  Уж извините, не смог удержаться.
                    0
                    Вот бы кто про Spring написал и рассказал, что там к чему.
                      0
                      кто бы написал, как это всё на живую выкатывать.
                        0
                        Вы о чём?
                          0
                          да вот как раз разбираюсь в спринг. Я сумел поставить томкат, написал хелло ворлд первый. А теперь есть желание узнать как это всё ставится на живой сервер. Особенно где и как, в конфигурации убирается localhost:8080/имя_WAR/test имя_WAR. чтобы было не test.com/имя_WAR/test, а test.com/test
                            0
                            Зависит от проекта. Если это Spring без извращений — то это Spring MVC и там в пути war не будет, если задеплоить проект как root.war / root.jar. Если проект новый и там Spring Boot — то ничего деплоить не нужно, просто запустить полученный jar через java -jar . Boot предоставляет настенный и готовый к запуску embedded Tomcat.
                              0
                              В tomcat'e это сродни магии. На сколько помню, один из вариантов переименовать имя_WAR.war в ROOT.war.
                              Проще поставить nginx перед tomcat'ом и настроить в нем проксирование запросов на localhost:8080/имя_WAR/
                                0
                                А вот, кстати, Apache Server не подойдет вместо nginx? Я промудохался 2 дня, ничего особо не вышло, с этими бесконечными файлами конфигураций.
                                  0
                                  Давно не работал с apache, но вроде как mod_proxy должен подойти.
                                  По поводу nginx: для такой задачи конфиг у него будет не очень большой. На хабре есть статья на эту тему.
                                0
                                В свое время я начал с того, что выкинул Томкат и взял embedded jetty — жизнь упростилась в разы, чего и вам желаю :)
                          • НЛО прилетело и опубликовало эту надпись здесь
                            • НЛО прилетело и опубликовало эту надпись здесь
                                0
                                Спасибо, годные посты. Но все же хочется найти обзорную лекцию про спринг, он все таки огромный и что там за что отвечает разобраться трудно.
                          0

                          Если уж есть желание работать с сервлетами на Java, то советую изучить аннотации из последних спецификаций. Конфигурация и деплоймент значительно упростятся (например, не нужно вручную мапить сервлеты в web.xml).

                            0
                            Вброшу, так сказать, свои пару слов:
                            1. Начиная с servlet-api 3.0, файл web.xml стал необязательным и указание сервлетов, фильтров, слушателей осуществляется соответствующими аннотациями — WebServlet, WebFilter, WebListener и т.д.
                            2. Если нужно определить синонимы урлов страниц (aka чистые ссылки), то это стоит выделить в отдельный сервлет или вовсе переложить обязанность на фронтенд веб-сервер (например, nginx).
                            3. По поводу выкладки на сервер. На продуктивной среде автодеплой war-ников в целях безопасности обычно выключают, в server.xml прописываем свои приложения, а выкладку делаем руками или шелл-скриптами. Для тестовой (часто обновляемой) среды можно использовать CI систему.
                              0
                              В интересное время живём: статья про «Создание сервлетов для чайников» вполне может оказаться не для начинающих, а про интернет вещей.
                                0
                                Допустим, мы где-то взяли Maven и знаем, как работает Maven, HTTP и что такое аспектно-ориентированное программирование.
                                Когда пишете простой мануал на систему из огромных кусков, хотя бы подготовьте ссылки на тот же Хабр, где почитать об остальных кусках, необходимых для понимания искомого. Или сразу предупреждайте, каким уровнем знаний должен обладать читатель вашей статьи.

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

                                Самое читаемое