Если вы решили создать 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 можно глянуть тут. И мы получим тот же результат, но без лишних файлов и с аннотацией:
На этом все, надеюсь данный туториал будет вам полезен. На вопросы отвечу в комментариях :)
Также читайте серию статей «Spring Data JPA. Работа с БД»: часть 1, часть 2 и часть 3
ПОХОЖИЕ ПУБЛИКАЦИИ
- None Found
41 комментариев к статье "Как создать Servlet? Полное руководство"
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
Вот спасибо: все четко, кратко и понятно!!!
Классная статья!!!
что не так я делаю? после деплоя у меня открывается главная страница tomcat и все. причем артефакты я там найти не могу а ссылка http://localhost:8080/servletexam/ вообще не работает….
разобрался)))) tomcat 6 чтото глючил
Удалил web.xml и без maven-war-plugin все нормально задеплоилось.
Отличная статься, а какие есть еще варианты добавить данные на страницу кроме ${name}, к примеру на index после обработки сменить значение в поле ввода?
Делал все сам, качал исходник – в обоихслучиях после деплоя и запуска сервера появляется 404 The requested resource is not available.
Подскажите, как с этим бороться?
Антон, при выборе артифакта попробуй выбрать exploded. В моем случает решило такую же проблему. В Tomcat запускается по URL: http://localhost:8080
Статья содержательная и информативная, спасибо огромное автору.
Без 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
Попробуйте задать этой странице mypage.jsp стили, css, прикрутить js. Все это работать в таком случае не будет, на stackoverflow полно вопросов на данную тему. Есть какое-нибудь решение?
Владимир, вы решили свой вопрос о проблеме подключения стилей?
Аналогично вишу с этой проблемой
Спасибо большое за статью
Спасибо большое, мне очень помогло!
Не работает. Откуда вообще взялось “servletexam” в “http://localhost:8080/servletexam/” ?!
Да. Тоже не понял почему “servletexam” если везде переход на “/”.
Все очень просто. Варник который вы положили в томкет называется servletexam, поэтому и нужно набирать «http://localhost:8080/servletexam/»
Попробуйте задать этой странице mypage.jsp стили, css, прикрутить js. Все это работать в таком случае не будет, на stackoverflow полно вопросов на данную тему. Есть какое-нибудь решение?
Благодарю за полезный урок,
в своем проекте хочу создать сервлет, который будет выполнять несколько sql запросов-> передавать результат jsp-> на основание этого будет строиться таблица
Не могу понять как в сервлете несколько запросов создавать, подскажите пожалуйста
по результатам
Не работает у мен этот код. Чего я только уже не пробовал. Страницу jsp я не создавал. И с web.xml пробовал, и без него. не открывает у меня Томкат это war. А мне позарез нужен сервлет, который будет обрабатывать входящий запрос и выдавать результат. Как мне всю эту логику в неработающий сервлет засунуть ума не приложу. Уже несколько дней мучаюсь :(
Отличная статья ! Все просто, доступно, понятно .
javax.servlet
javax.servlet-api
3.1.0
Добрый день! А как узнать версию сервлета? Что то я ни где этого найти не могу.
вот что нашел. может кому пригодится http://mvnrepository.com/artifact/javax.servlet/servlet-api
Не понял, почему http://localhost:8080/servletexam/ . Мы его нигде не задаем. Любой URL типа http://localhost:8080/что_угодно выдаст нам наш сервлет.
Аналогичный вопрос, servletexam нигде ранее не указывался
Спасибо. Инфа помогла разобратся с некоторіми вопросами
Подскажите пожалуйста, как в jsp подключить картинки и js, используя данную архитектуру.
Не разворачивается проект в 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.
В чем может быть причина?
Подскажите почему у меня создается файл с расширение jar, а не war? Все делаю по инструкции, уйму раз перепроверял все, выполнил все как в статье на данном сайте по деплою на томкат. Делаю все в intelilij idea 2016.2 ultimate. спасибо за помощь)
в pom.xml нужно указать war
Евгений, в pom.xml добавьте war.
Мне помогло, когда сделал так:
Maventest
Maventest
1.0-SNAPSHOT
war
Добавь в pom.xml
war
Большое спасибо, очень чётко сделано, жалко лайкнуть нельзя для всего интернета.)
Спасибо!
Может кому поможет:
При переопределении метода через Code -> Override Methods (Ctrl+O) -> doGet(), автоматически устанавливается super.doGet(req, resp);
После деплоя вылезает ошибка 405, контент соответственно не отображается.
in your doGet() method, get rid of super.doGet(req, resp);
The HttpServlet basically follows the template method pattern where all non-overridden HTTP methods returns a HTTP 405 error “Method not supported”. When you override such a method, you should not call super method, because you would otherwise still get the HTTP 405 error. The same story goes on for your doPost() method.
Большое спасибо. Именно в таком формате статьи и рулят. Последовательные, понятные. Продолжайте в том же духе
Полезная статья, многое разъяснила
Классный урок спасибо!
спасибо огромное!
Написано слишком сжато, информация устарела. Пришлось постоянно гуглить из-за недостатка информации. На последнем шаге в pom.xml нужно заключить , в . По-другому проект не собирался.