Как создать Servlet? Полное руководство

Если вы решили создать web проект на Java EE, то вам не обойтись без Servlet-ов. В этом уроке я продемонстрирую работу с Servlets, а также расскажу о их особенностях.

 

Шаг 0. Введение

Servlet — в первую очередь это простой Java интерфейс, реализация которого расширяет функциональные возможности сервера.

Сервлет взаимодействует с клиентами посредством принципа запрос-ответ. Хотя сервлеты могут обслуживать любые запросы, они обычно используются для расширения веб-серверов. Для таких приложений технология Java Servlet определяет HTTP-специфичные сервлет классы.

 

Шаг 1. Создание и конфигурирование проекта

Заходим в нами всеми любимую IDE Intellij IDEA и создаем Maven Project. Структура проекта простая и не сложная, один класс и стандартная структура Maven проекта.

Теперь откройте pom.xml и добавьте туда зависимость, которая позволит нам использовать Servlet-ы.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.devcolibri</groupId>
    <artifactId>com.devcolibri.servlet</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>

</project>

Обратите внимание, что мы используем Servlet версии 3.1 они присутствуют в Java EE7.

 

Шаг 2. Создание сервлета

Теперь создаем класс MainServlet.java как показанно на скриншоте структуры высше, дальше наследуем его от HttpServlet и переопределяем два метода void doGet(…) и void doPost(…):

package com.devcolibri.servlet;

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

public class MainServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {

        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {

        super.doPost(req, resp);
    }

}

Теперь разберем что да как. Как вы уже заметили мы унаследовались от HttpServlet это абстрактный класс GenericServlet который в свою очередь реализует интерфейс Servlet.

HttpServlet предназначен для написания сервлетов по типу общения клиент-сервер, а именно используя HTTP протокол.

Вспоминаем что такое HTTP протокол. Wiki говорит следующее:

HTTP (HyperText Transfer Protocol — «протокол передачи гипертекста») — протокол прикладного уровня передачи данных (изначально — в виде гипертекстовых документов в формате HTML, в настоящий момент используется для передачи произвольных данных).

Известно, что HTTP протокол имеет 7 методов передачи данных:

— DELETE
— HEAD
— GET
— OPTIONS
— POST
— PUT
— TRACE

Но только два из них пользуются особой популярностью, а именно GET и POST.  Метод GET вызвать легко, достаточно ввести в браузере ссылку и перейти по ней, а вот POST не так просто выполнить, один из простых способов используя form тег указать ему action. Но нам все это не потребуется.

Для того чтобы мы погли обрабатывать методы HTTP запроса в нашем сервлете, нужно переопределить соответствующий метод.

Но чаще всего используются методы GET и POST. Именно их мы и разберем на примере.

 

Шаг 3. Hello World Servlet

Для того чтобы создать наш первый Hello World нам нужно реализовать метод doGet:

package com.devcolibri.servlet;

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

public class MainServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        PrintWriter out = resp.getWriter();
        out.print("<h1>Hello Servlet</h1>");

    }

}

Разберем пример. Как видите метод doGet принимает два параметра:

HttpServletRequest req — это запрос, который пришел к сервлету;

HttpServletResponse resp — это ответ который даст сервлет.

Теперь создаем папку src/main/webapp/WEB-INF, а там создаем файл web.xml в этом файле мы зарегистрируем наш сервлет и замапим его на URL.

Вот содержимое web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <servlet>
        <servlet-name>mainServlet</servlet-name>
        <servlet-class>com.devcolibri.servlet.MainServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>mainServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

Мы описали два тега servlet и servlet-mapping и которые и заставят наш сервлет показаться в браузере по URL — /

В строке 8 мы указываем имя сервлета (оно может быть любое) это имя является идентификатором, и должно быть уникальным.

В строке 9 мы указываем полный пакетный путь к севрлету. После чего мы можем к нему обращаться по его name (идентификатору).

В строке 13 мы указываем имя сервлета (идентификатор) который хотим замапить на определенный URL.

Строка 14 говорит на какой URL мапить сервлет. Так как у нас стоит / — это значит что зайдя в корень проекта http://localhost:8080/servletexam/ мы получим сервлет, а именно то что в методе doGet.

Теперь собираем проект:

Теперь запускаем, как это сделать рассказанно тут Intellij IDEA деплой на Tomcat.

После запуска перейдите по ссылке http://localhost:8080/servletexam/. Вы увидите следующее:

Дальше мы рассмотрим более правильный способ использования Servlets в веб-проектах.

 

Шаг 4. Используем JSP

Не совсем красиво выводить все HTML теги по средством response. Поэтому давайте прикрутим к сервлету jsp страничку.

Для этого создаем mypage.jsp в webapp:

И содержимое этого файла:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Devcolibri.com</title>
</head>
<body>
    <h1>Hello Servlet</h1>
</body>
</html>

Обратите внимание на первую строку, где мы указываем кодировку страницы, если этого не сделать то символы, в том числе и русские, будут отображаться не корректно.

Дальше редактируем метод doGet в нашем MainServlet:

package com.devcolibri.servlet;

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

public class MainServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.getRequestDispatcher("mypage.jsp").forward(req, resp);

    }

}

В 15-й строке мы с запроса получаем Request Dispatcher (Диспетчер Запросов) и указываем ему jsp страницу которая будет отображаться при обращении к данному методуGET. Метод forward(req, resp) перенаправляет наш запрос на jsp страницу.

Теперь если пересобрать приложение Maven-ом и запустить, то получим уже вывод на страницу в браузере содержимого mypage.jsp.

 

Шаг 5. Передаем данные с Servlet на JSP

Для того чтобы передать какие либо дынные на JSP нам нужно в сервлете в request добавить атрибут.

Чтобы добавить атрибут в request нужно вызвать метод setAttribute(String key, Object value), где

key — это ключ по которому вы получите доступ к данным на JSP;

value — данные которые мы передаем.

package com.devcolibri.servlet;

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

public class MainServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.setAttribute("name", "Devcolibri");

        req.getRequestDispatcher("mypage.jsp").forward(req, resp);

    }

}

Как видите в строке 15 я передаю имя с ключем (name) и значением (Devcolibri).

Теперь чтобы принять эти данные на JSP нужно обратится к ключу по определенной конструкции ${key}

Давайте на нашей mypage.jsp приймем данные с сервлета:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Devcolibri.com</title>
</head>
<body>
    <h1>Hello ${name}</h1>
</body>
</html>

Теперь пересобираем проект с помощью Maven и щапускаем. Мы увидим следующий результат:

Вот видим результат, где вместо World выводится Devcolibri.

 

Шаг 6. Улучшаем сервлет и удаляем web.xml

Согласитесь не совсем удобно регистрировать наш сервлет в web.xml, особенно если у нас будет не один-два сервлета, а 100+, тогда это будет неудобно :) Но в этом есть и плюс, когда все сервлеты зарегистрированы в одном месте, а именно web.xml мы можем удобно их перемаплиапть на другой URL.

Я больше предпочитаю способ регистрации сервлетов, который опишу ниже.

Для начало проаннотируем сервлет аннотацией @WebServlet:

package com.devcolibri.servlet;

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 MainServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.setAttribute("name", "Devcolibri");

        req.getRequestDispatcher("mypage.jsp").forward(req, resp);

    }

}

Данная аннотация регистрирует сервлет в контексте приложения, это тоже самое что мы делали в web.xml:

<servlet>
    <servlet-name>mainServlet</servlet-name>
    <servlet-class>com.devcolibri.servlet.MainServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>mainServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Аннотация принимает как параметр строку, именно эта строка соответствует тегу url-pattern, тоесть это URL по которому будет доступен сервлет.

Вы возможно зададите вопрос, — Зачем тогда этот web.xml? В нашем случае он уже не надо, поэтому смело его удаляем вместе с папкой WEB-INF.

Но если на этом этапе собрать проект и задеалоить, то он у нас не задеплоится, и будет ругаться на отсуствие web.xml. Для того чтобы это исправить идем в pom.xml и в maven-war-plugin добавляем свойство которое делает не обязательным web.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.1.1</version>
    <configuration>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
</plugin>

Именно этот Maven плагин отвечает за зборку war архива, который мы потом деплоим на сервер приложений.

Конечная структура проекта выглядит так:

Теперь пересобираем проект вызвав в Maven фазу Install и деплоим на сервер приложений. Нопоминаю как это делать со студии Intellij IDEA можно глянуть тут. И мы получим тот же результат, но без лишних вайлов и с аннотацией:

На этом все, надеюсь данный туториал будет вам полезен. На вопросы отвечу в комментариях :)

Урок создан: 16 апреля 2014 | Просмотров: 100620 | Автор: Александр Барчук | Правила перепечатки


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

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

Ваш e-mail не будет опубликован.

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

  • 23 мая 2014 в 13:36

    Александр

    Вот спасибо: все четко, кратко и понятно!!!

  • 01 июля 2014 в 13:45

    Andrey

    Классная статья!!!

  • 26 августа 2014 в 08:54

    Павел

    что не так я делаю? после деплоя у меня открывается главная страница tomcat и все. причем артефакты я там найти не могу а ссылка http://localhost:8080/servletexam/ вообще не работает….

    • 26 августа 2014 в 09:15

      Павел

      разобрался)))) tomcat 6 чтото глючил

  • 09 сентября 2014 в 15:09

    Константин

    Удалил web.xml и без maven-war-plugin все нормально задеплоилось.

  • 23 января 2015 в 02:14

    Богдан

    Отличная статься, а какие есть еще варианты добавить данные на страницу кроме ${name}, к примеру на index после обработки сменить значение в поле ввода?

  • 17 февраля 2015 в 10:42

    Антон

    Делал все сам, качал исходник — в обоихслучиях после деплоя и запуска сервера появляется 404 The requested resource is not available.
    Подскажите, как с этим бороться?

    • 27 февраля 2015 в 12:29

      Константин

      Антон, при выборе артифакта попробуй выбрать exploded. В моем случает решило такую же проблему. В Tomcat запускается по URL: http://localhost:8080

  • 27 февраля 2015 в 12:30

    Константин

    Статья содержательная и информативная, спасибо огромное автору.

  • 01 марта 2015 в 21:12

    Руслан

    Без maven-war-plugin деплоится без ошибок. Но если пересобирать в maven, то ругается на отсутствие web.xml.
    После добавления ….. в pom.xml пытаемся пересобрать в maven и получаем ошибку unrecognised tag ‘plugin’.
    Лечится так: нужно тег ….. заключить в родительские теги и . Теперь pom.xml должен принять следующий вид:

    org.apache.maven.plugins
    maven-war-plugin
    2.1.1

    false

    З.Ы. Использую IDEA 14.0.2

    • 28 июля 2015 в 18:01

      Владимир

      Попробуйте задать этой странице mypage.jsp стили, css, прикрутить js. Все это работать в таком случае не будет, на stackoverflow полно вопросов на данную тему. Есть какое-нибудь решение?

      • 30 января 2016 в 18:16

        {dima}

        Владимир, вы решили свой вопрос о проблеме подключения стилей?

        • 22 мая 2016 в 18:32

          Аноним

          Аналогично вишу с этой проблемой

  • 11 марта 2015 в 10:36

    Галина

    Спасибо большое за статью

  • 02 апреля 2015 в 18:45

    Виталий

    Спасибо большое, мне очень помогло!

  • 13 июня 2015 в 17:30

    machet1k

    Не работает. Откуда вообще взялось «servletexam» в «http://localhost:8080/servletexam/» ?!

    • 04 июля 2015 в 16:18

      Вадим

      Да. Тоже не понял почему «servletexam» если везде переход на «/».

      • 15 июля 2015 в 23:22

        Sergey

        Все очень просто. Варник который вы положили в томкет называется servletexam, поэтому и нужно набирать «http://localhost:8080/servletexam/»

  • 28 июля 2015 в 18:28

    Владимир

    Попробуйте задать этой странице mypage.jsp стили, css, прикрутить js. Все это работать в таком случае не будет, на stackoverflow полно вопросов на данную тему. Есть какое-нибудь решение?

  • 15 октября 2015 в 10:41

    Эльвина

    Благодарю за полезный урок,
    в своем проекте хочу создать сервлет, который будет выполнять несколько sql запросов-> передавать результат jsp-> на основание этого будет строиться таблица
    Не могу понять как в сервлете несколько запросов создавать, подскажите пожалуйста
    по результатам

  • 25 ноября 2015 в 15:05

    Юрий

    Не работает у мен этот код. Чего я только уже не пробовал. Страницу jsp я не создавал. И с web.xml пробовал, и без него. не открывает у меня Томкат это war. А мне позарез нужен сервлет, который будет обрабатывать входящий запрос и выдавать результат. Как мне всю эту логику в неработающий сервлет засунуть ума не приложу. Уже несколько дней мучаюсь :(

  • 29 ноября 2015 в 19:40

    Денис

    Отличная статья ! Все просто, доступно, понятно .

  • 04 декабря 2015 в 14:36

    Сергей

    javax.servlet
    javax.servlet-api
    3.1.0
    Добрый день! А как узнать версию сервлета? Что то я ни где этого найти не могу.

  • 08 декабря 2015 в 17:15

    Аноним

    Не понял, почему http://localhost:8080/servletexam/ . Мы его нигде не задаем. Любой URL типа http://localhost:8080/что_угодно выдаст нам наш сервлет.

    • 08 мая 2016 в 19:46

      Аноним

      Аналогичный вопрос, servletexam нигде ранее не указывался

  • 10 апреля 2016 в 19:44

    Александр

    Спасибо. Инфа помогла разобратся с некоторіми вопросами

  • 16 июня 2016 в 11:00

    Татьяна

    Подскажите пожалуйста, как в jsp подключить картинки и js, используя данную архитектуру.

  • 23 августа 2016 в 18:26

    Сергей

    Не разворачивается проект в tomcat8, выдается 500 ошибка:
    type Exception report

    message Path mypage.jsp does not start with a «/» character

    description The server encountered an internal error that prevented it from fulfilling this request.

    exception

    java.lang.IllegalArgumentException: Path mypage.jsp does not start with a «/» character
    org.apache.catalina.connector.Request.getRequestDispatcher(Request.java:1366)
    org.apache.catalina.connector.RequestFacade.getRequestDispatcher(RequestFacade.java:613)
    com.devcolibri.servlet.MainServlet.doGet(MainServlet.java:19)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    note The full stack trace of the root cause is available in the Apache Tomcat/8.0.14 (Debian) logs.

    В чем может быть причина?

  • 06 сентября 2016 в 22:16

    Евгений

    Подскажите почему у меня создается файл с расширение jar, а не war? Все делаю по инструкции, уйму раз перепроверял все, выполнил все как в статье на данном сайте по деплою на томкат. Делаю все в intelilij idea 2016.2 ultimate. спасибо за помощь)

    • 16 октября 2016 в 02:47

      Андрей

      в pom.xml нужно указать war

    • 19 октября 2016 в 15:56

      Михаил

      Евгений, в pom.xml добавьте war.

      Мне помогло, когда сделал так:
      Maventest
      Maventest
      1.0-SNAPSHOT
      war

    • 11 ноября 2016 в 12:54

      Александр

      Добавь в pom.xml
      war

  • 12 октября 2016 в 15:52

    рмк

    Большое спасибо, очень чётко сделано, жалко лайкнуть нельзя для всего интернета.)

  • 06 декабря 2016 в 09:57

    Аноним

    Спасибо!