JavaRush /Java блог /Random UA /Частина 5. Сервлети, Java servlet API. Пишемо просте веб-...
Professor Hans Noodles
41 рівень

Частина 5. Сервлети, Java servlet API. Пишемо просте веб-додаток

Стаття з групи Random UA
Цей матеріал - частина циклу "Введення в Enterprise-розробку". Попередні статті: Частина 5. Сервлети, Java servlet API.  Пишемо просте веб-додаток - 1Ти вже вмієш писати Java-додатки, які виводять текст на консоль, але ще до ладу не знаєш, як створити свій перший веб-додаток? Добре, влаштовуйся зручніше. У цій статті ми познайомимося з сервлетами і напишемо програму, якою ти зможеш похвалитися перед друзями, не відправляючи їм джарник і не змушуючи їх качати джаву. Напишемо веб-додаток . Якщо ти ще не знайомий з підходами, які використовуються у веб-програмуванні, раджу почати читання з першої статті циклу " Введення в Enterprise-розробку ".

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

Спочатку розберемося, що таке сервлет і чому ти так часто чуєш про нього. Java Servlet API - стандартизований API, призначений для реалізації на сервері та роботі з клієнтом за схемою запит-відповідь. Сервлет – це клас, який вміє отримувати запити від клієнта та повертати йому відповіді. Так, сервлети Java — саме ті елементи, за допомогою яких будується клієнт-серверна архітектура. Якщо пам'ятаєш, про неї ми вже говорабо в одній із статей циклу. Не будемо ходити навкруги: давай відразу напишемо трохи коду.

Що потрібно для створення веб-програми

Для комфортної роботи з сервлетами Java тобі знадобиться Intellij IDEA Ultimate Edition. Вона платна, але можна активувати 30 днів пробного періоду або ж скористатися early access версією — вона завжди безкоштовна. Також установи сервер нашої програми - Apache Tomcat. Tomcat – це контейнер сервлетів: саме він обробляє вхідні запити ззовні та передає їх нашому додатку. Завантажити Tomcat можна за цим посиланням .

Створюємо перший веб-додаток

Якщо все готово, створимо Maven-проект. Якщо ти не знайомий з Мавеном, зверни увагу на попередню статтю . Ну що почнемо!
  1. У pom.xml додамо залежність javax.servlet-api та встановимо packaging war:

    <?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>org.example</groupId>
       <artifactId>servlets</artifactId>
       <version>1.0-SNAPSHOT</version>
       <packaging>war</packaging>
    
       <dependencies>
           <dependency>
               <groupId>javax.servlet</groupId>
               <artifactId>javax.servlet-api</artifactId>
               <version>4.0.1</version>
           </dependency>
       </dependencies>
    </project>

    Клас простого сервлету:

    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();
       }
    }
  2. Для запуску програми потрібно створити конфігурацію Tomcat:

    Частина 5. Сервлети, Java servlet API.  Пишемо просте веб-додаток - 2 Частина 5. Сервлети, Java servlet API.  Пишемо просте веб-додаток - 3

  3. Далі вказуємо, яку версію Tomcat ми будемо використовувати, URL, яким можна звертатися до сервера і порт. У тебе має вийти приблизно так:

    Частина 5. Сервлети, Java servlet API.  Пишемо просте веб-додаток - 4
  4. Залишилося вказати артефакт (зібраний проект у jar-архів), який розгорнеться у контейнері. Можна натиснути кнопку Fix і вибрати war exploded : це означає, що після перескладання проекту артефакт автоматично поміщатиметься в контейнер сервлетів. Частина 5. Сервлети, Java servlet API.  Пишемо просте веб-додаток - 5

  5. Application context за промовчанням встановлений servlets_war_exploded , а це означає, що до додатку потрібно звертатися за адресаою: http://localhost:8080/servlets_war_exploded .

    Навіщо нам зайвий текст? Видалимо непотрібне. Тепер адресаа програми у нас така: http://localhost:8080 .

    Частина 5. Сервлети, Java servlet API.  Пишемо просте веб-додаток - 6

  6. Натискаємо ОК. Бачимо, що у нас з'явилася можливість запуску програми:

    Частина 5. Сервлети, Java servlet API.  Пишемо просте веб-додаток - 7

    Тепер при запуску програми повинен відкритися браузер і видати 404 помилку. Це логічно, адже за адресаою http://localhost:8080/ повинен бути сервлет з мапінгом “/”, а у нашого єдиного сервлету мапінг "/hello" .

  7. Звертаємось до нього за адресаою http://localhost:8080/hello , і отримуємо очікувану відповідь - рядок "Hello"!

Якщо все працює, то давай розберемо код. Щоб зі звичайного класу зробити 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" + "<br>");
       } else {
           printWriter.write("Hello, " + username + "<br>");
       }
       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
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ