3. Основи веб-розробки на Java
Тепер перейдемо до розробки динамічних веб-додатків, c.a.d, у яких сторінки HTML, що надсилаються користувачеві, генеруються програмами.
3.1. Створення веб-проєкту в Eclipse
Ми розробимо перший веб-додаток за допомогою Eclipse/Tomcat. Ми будемо дотримуватися підходу, аналогічного тому, що використовувався для створення веб-додатка без Eclipse. Запустивши Eclipse, ми створюємо новий проєкт:

який ми визначаємо як динамічний веб-проект:

На першій сторінці майстра створення вказуємо назву проєкту [1] та його розташування [2]:

На другій сторінці майстра ми приймаємо значення за замовчуванням:

На останній сторінці майстра нам пропонується визначити контекст [3] додатка:

Після підтвердження майстра [Finish] Eclipse підключається до сайту [http://java.sun.com], щоб завантажити певні документи, які він хоче зберегти в кеші, щоб уникнути зайвих мережевих запитів. Після цього з’являється запит на підтвердження ліцензії:

Ми погоджуємося. Eclipse створює веб-проект. Для його відображення використовується середовище, яке називається «перспективою» (perspective) і відрізняється від того, що використовується для класичного Java-проекту:

Перспектива, пов’язана з веб-проєктом, — це J2EE. Ми її приймаємо, щоб подивитися... Отриманий результат такий:

Перспектива J2EE насправді є надмірно складною для простих веб-проектів. У цьому випадку достатньо перспективи Java. Щоб її отримати, використовуємо опцію [Window -> Open perspective -> Java]:

src: міститиме Java-код класів додатка, а також файли, які мають бути у Classpath додатка.
build/classes (не показано): міститиме файли .class скомпільованих класів, а також копії всіх файлів, крім .java, розміщених у src. Веб-додаток часто використовує так звані «ресурсні» файли, які повинні бути в Classpath додатка, c.a.d. Сукупність папок, які JVM обходить під час пошуку, коли додаток звертається до класу — як під час компіляції, так і під час виконання. Eclipse забезпечує, щоб папка build/classes була частиною веб-додатку. Файли «ресурсів» розміщують у папці src, знаючи, що Eclipse автоматично скопіює їх у build/classes.
WebContent: міститиме ресурси веб-додатка, які не повинні бути в Classpath цього додатка.
WEB-INF/lib: міститиме архіви .jar, необхідні веб-додатку.
Розглянемо вміст файлу [WEB-INF/web.xml], який налаштовує додаток [personne]:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name> personne</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
Ми вже стикалися з таким типом конфігурації, коли розглядали створення стартових сторінок у розділі 2.3.4. Цей файл лише визначає набір стартових сторінок. Ми залишаємо лише першу. Файл [web.xml] набуває такого вигляду:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Вміст наведеного вище файлу XML має відповідати правилам синтаксису, визначеним у файлі, вказаному атрибутом [xsi:schemaLocation] тегу відкриття <web-app>. У даному випадку це файл [http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd]. Це файл XML, який можна відкрити безпосередньо у веб-браузері. Якщо браузер достатньо сучасний, він зможе відобразити файл XML:

Eclipse спробує перевірити валідність документа XML за допомогою файлу .xsd, вказаного в атрибуті [xsi:schemaLocation] відкриваючого тегу <web-app>. Для цього він здійснить мережевий запит. Якщо ваш комп’ютер знаходиться у приватній мережі, необхідно вказати Eclipse, який сервер використовувати для виходу з приватної мережі, так званий проксі-сервер HTTP. Це робиться за допомогою опції [Window -> Preferences -> Internet]:

Поставте галочку (1), якщо ви перебуваєте у приватній мережі. У полі (2) вкажіть ім’я комп’ютера, який підтримує проксі-сервер HTTP, а в полі (3) — порт, на якому він приймає запити. Нарешті, у полі (4) вказують комп’ютери, для яких не потрібно використовувати проксі-сервер, — ті, що знаходяться в тій самій приватній мережі, що й комп’ютер, на якому ви працюєте.
Тепер ми створимо файл [index.html] для стартової сторінки.
3.2. Створення головної сторінки
Клацаємо правою кнопкою миші на папці [WebContent], а потім вибираємо опцію [New -> Other]:

Ми вибираємо тип [HTML] і перетворюємо [Next] на ->

Вище ми вибираємо батьківську папку [WebContent] у пункті (1) або (2), а потім у пункті (3) вказуємо ім’я файлу, який потрібно створити. Зробивши це, переходимо на наступну сторінку майстра:

За допомогою (1) ми можемо створити файл HTML, попередньо заповнений даними з (2). Якщо зняти галочку з (1), буде створено порожній файл HTML. Ми залишаємо галочку біля (1), щоб отримати шаблон коду. Ми завершуємо роботу майстра, отримавши файл [Finish]. Після цього створюється файл [index.html]:

з таким вмістом:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
Ми змінюємо цей файл наступним чином:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Application personne</title>
</head>
<body>
Application personne active...
<br>
<br>
Vous êtes sur la page d'accueil
</body>
</html>
3.3. Тестування головної сторінки
Якщо вона відсутня, відкриємо вікно [Servers] за допомогою опції [Window - > Show View -> Other -> Servers], а потім клацнемо правою кнопкою миші на сервері Tomcat 5.5:

Зазначена вище опція [Add and Remove Objects] дозволяє додавати/видаляти веб-додатки на сервері Tomcat:

Веб-проєкти, відомі Eclipse, відображаються в (1). Їх можна зареєструвати на сервері Tomcat за допомогою (2). Веб-додатки, зареєстровані на сервері Tomcat, відображаються в (4). Їх можна скасувати за допомогою (3). Зареєструємо проєкт [personne]:

а потім завершимо роботу майстра реєстрації з [Finish]. У вікні [Servers] видно, що проект [personne] було зареєстровано на Tomcat:

Тепер запустимо сервер Tomcat:
![]() | ![]() |
Запустимо веб-браузер:

потім введемо URL-адресу [http://localhost:8080/personne]. Ця URL-адреса відповідає кореневому каталогу веб-додатку. Жодного документа не запитується. У цьому випадку відображається головна сторінка додатка. Якщо її немає, з’являється повідомлення про помилку. У даному випадку головна сторінка існує. Це файл [index.html], який ми створили раніше. Отримано такий результат:

Він відповідає очікуваному результату. Тепер відкриємо браузер поза Eclipse та введемо той самий URL-адресу:

Отже, веб-додаток [personne] також відомий поза межами Eclipse.
3.4. Створення форми HTML
Тепер створимо статичний документ HTML [formulaire.html] у папці [personne]:

Для його створення слід дотримуватися процедури, описаної в розділі 3.2 на сторінці 33. Його вміст буде таким:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form action="" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="" type="text" size="3"></td>
</tr>
</table>
<table>
<tr>
<td><input type="submit" value="Envoyer"></td>
<td><input type="reset" value="Retablir"></td>
<td><input type="button" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
Наведений вище код HTML відповідає наведеному нижче бланку:

тип HTML | назва | код HTML | роль | |
<input type= "text "> | txtNom | рядок 14 | введення імені | |
<input type= "text "> | txtAge | рядок 18 | введення віку | |
<input type= "submit "> | рядок 23 | відправлення введених значень на сервер за адресою /personne1/main | ||
<input type= "reset "> | рядок 24 | щоб повернути сторінку до того стану, в якому вона була спочатку отримана браузером | ||
<input type= "button "> | рядок 25 | щоб очистити вміст полів введення [1] та [2] |
Збережемо документ у папці <personne>/WebContent. Запустимо Tomcat, якщо це необхідно. За допомогою браузера відкриємо сторінку URL http://localhost:8080/personne/formulaire.html :

Архітектура «клієнт-сервер» цього простого додатка така:

Веб-сервер розташований між користувачем і веб-додатком і тут не зображений. [formulaire.html] — це статичний документ, який на кожен запит клієнта повертає однаковий вміст. Веб-програмування має на меті генерувати вміст, адаптований до запиту клієнта. Цей вміст генерується за допомогою програми. Одним із перших рішень є використання сторінки JSP (Java Server Page) замість статичного файлу HTML. Саме це ми зараз і розглянемо.
3.5. Створення сторінки JSP
Розділи [ref1]: розділ 1, розділ 2: 2.2, 2.2.1, 2.2.2, 2.2.3, 2.2.4
Попередня архітектура «клієнт/сервер» трансформується наступним чином:

Сторінка JSP є варіантом сторінки HTML із заданими параметрами. Деякі елементи сторінки отримують свої значення лише під час виконання. Ці значення обчислюються програмою. Отже, ми маємо динамічну сторінку: послідовні запити до сторінки можуть призводити до різних відповідей. Під відповіддю ми тут розуміємо сторінку HTML, що відображається браузером клієнта. У підсумку браузер завжди отримує документ HTML. Цей документ HTML генерується веб-сервером на основі сторінки JSP. Остання слугує шаблоном. Її динамічні елементи замінюються їхніми фактичними значеннями на момент генерації документа HTML.
Щоб створити сторінку JSP, клацаємо правою кнопкою миші на папці [WebContent], а потім вибираємо опцію [New -> Other]:

Вибираємо тип [JSP] і виконуємо [Next] ->

Вище ми вибираємо батьківську папку [WebContent] у пункті (1) або (2), а потім у пункті (3) вказуємо ім’я файлу, який потрібно створити. Зробивши це, переходимо на наступну сторінку майстра:

За допомогою (1) ми можемо створити файл JSP, попередньо заповнений даними з (2). Якщо зняти галочку з (1), буде створено порожній файл JSP. Ми залишаємо галочку біля (1), щоб отримати каркас коду. Ми завершуємо роботу майстра, отримавши файл [Finish]. Після цього створюється файл [formulaire.jsp]:

з таким вмістом:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
Рядок 1 вказує, що ми маємо справу зі сторінкою JSP. Ми перетворюємо наведений вище текст наступним чином:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
// отримуємо параметри
String nom=request.getParameter("txtNom");
if(nom==null) nom="inconnu";
String age=request.getParameter("txtAge");
if(age==null) age="xxx";
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form action="" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="<%= nom %>" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="<%= age %>" type="text" size="3"></td>
</tr>
</table>
<table>
<tr>
<td><input type="submit" value="Envoyer"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="button" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
Документ, який спочатку був статичним, тепер став динамічним завдяки введенню коду Java. Для цього типу документів ми завжди будемо діяти наступним чином:
- вставляємо код Java на самому початку документа, щоб отримати параметри, необхідні для його відображення. Вони часто містяться в об’єкті request. Цей об’єкт представляє запит клієнта. Він може пройти через кілька сервлетів і сторінок JSP, які могли його доповнити. У даному випадку він надходить до нас безпосередньо з браузера.
- Код HTML наведено нижче. Найчастіше він обмежується відображенням змінних, попередньо обчислених у Java-коді, за допомогою тегів <%= variable %>. Слід зауважити, що знак = стоїть безпосередньо після знака %. Це є частою причиною помилок.
Що робить попередній динамічний документ?
- рядки 6–9: він отримує із запиту два параметри з іменами [txtNom] та [txtAge] і присвоює їхні значення змінним [nom] (рядок 6) та [age] (рядок 8). Якщо параметри не знайдено, він присвоює відповідним змінним значення за замовчуванням.
- Він виводить значення обох змінних [nom, age] у наступному коді HTML (рядки 25 та 29).
Проведемо перше тестування. Запустимо Tomcat, якщо потрібно, а потім у браузері відкриємо сторінку URL http://localhost:8080/personne/formulaire.jsp :

Документ formulaire.jsp було викликано без передачі параметрів. Тому були відображені значення за замовчуванням. Тепер запустимо URL http://localhost:8080/personne/formulaire.jsp?txtNom=martin&txtAge=14 :

Цього разу ми передали документу formulaire.jsp параметри txtNom та txtAge, які він очікував. Отже, він їх відобразив. Відомо, що існує два методи передачі параметрів до веб-документа: GET та POST. В обох випадках передані параметри потрапляють до попередньо визначеного об’єкта request. У цьому випадку вони були передані методом GET.
3.6. Створення сервлету
Матеріали для читання [ref1]: розділ 1, розділ 2: 2.1, 2.1.1, 2.1.2, 2.3.1
У попередній версії запит клієнта оброблявся сторінкою JSP. Під час першого виклику цієї сторінки веб-сервер, у даному випадку Tomcat, створює на її основі клас Java та компілює його. Саме результат цієї компіляції в кінцевому підсумку обробляє запит клієнта. Клас, згенерований на основі сторінки JSP, є сервлетом, оскільки він реалізує інтерфейс [javax.Servlet]:

Запит клієнта може оброблятися будь-яким класом, що реалізує цей інтерфейс. Тепер ми створюємо такий клас: ServletFormulaire. Попередня архітектура «клієнт/сервер» трансформується наступним чином:

У архітектурі на основі сторінки JSP документ HTML, надісланий клієнту, був згенерований веб-сервером на основі сторінки JSP, яка слугувала шаблоном. У цьому випадку документ HTML, надісланий клієнту, буде повністю згенерований сервлетом.
3.6.1. Створення сервлета
У Eclipse клацніть правою кнопкою миші на папці [src] і виберіть опцію створення класу:

потім визначимо характеристики класу, що створюється:

У полі (1) вкажіть ім’я пакета, у полі (2) — ім’я класу, що створюється. Цей клас має бути похідним від класу, вказаного в полі (3). Немає потреби вводити повну назву цього класу вручну. Кнопка (4) надає доступ до класів, які наразі містяться у Classpath веб-додатку:

У полі (1) вводять назву класу, який шукають. У полі (2) відображаються класи з Classpath, назва яких містить рядок, введений у полі (1).
Після підтвердження майстром створення веб-проект [personne] змінюється наступним чином:

Створено клас [ServletFormulaire] із шаблоном коду:

На знімку екрана вище видно, що Eclipse позначає [warning] у рядку, де оголошується клас. Клацнімо на піктограму (лампочку), що позначає цей [warning]:

Після натискання на (1) у (2) пропонуються варіанти усунення помилки [warning]. Вибір одного з них призводить до появи у (3) змін у коді, які відбудуться внаслідок цього вибору.
Java 1.5 внесла зміни до мови Java, і те, що було правильним у попередній версії, тепер може викликати [warnings]. Ці повідомлення не вказують на помилки, які могли б завадити компіляції класу. Вони призначені для того, щоб привернути увагу розробника до фрагментів коду, які можна вдосконалити. Показане повідомлення [warning] вказує, що клас повинен мати номер версії. Він використовується для серіалізації/десеріалізації об’єктів, c.a.d. коли об’єкт Java .class у пам’яті потрібно перетворити на послідовність бітів, що послідовно надсилаються у потоці запису, або навпаки — коли об’єкт Java .class у пам’яті потрібно створити з послідовності бітів, що послідовно зчитуються з потоку читання. Все це дуже далеке від наших поточних завдань. Тому ми попросимо компілятор проігнорувати це попередження, вибравши варіант [Add @SuppressWarnings ...]. Тоді код виглядатиме так:

[warning] більше немає. Доданий рядок називається «анотацією» — поняттям, що з’явилося в Java 1.5. Ми доповнимо цей код пізніше.
3.6.2. Classpath проекту Eclipse
Classpath Java-додатка — це сукупність папок та archives.jar, які переглядаються під час компіляції додатка або під час його виконання. Ці два Classpath не обов’язково збігаються, оскільки деякі класи потрібні лише під час виконання, а не під час компіляції. Як компілятор Java, так і JVM мають аргумент, що дозволяє вказати Classpath додатка, який потрібно скомпілювати або виконати. Більш-менш прозоро для користувача Eclipse забезпечує формування та передачу цього аргументу до JVM.
Як дізнатися про елементи Classpath проекту Eclipse? За допомогою опції [<projet> / Build Path / Configure Build Path]:

У результаті ми отримуємо такий майстер налаштування:

Вкладка (1) [Libraries] дозволяє визначити список архівів .jar, що входять до складу Classpath додатка. Отже, вони скануються JVM, коли додаток запитує клас. Кнопки [2] та [3] дозволяють додавати архіви до Classpath. Кнопка [2] дозволяє вказати архіви, що знаходяться в папках проектів, якими керує Eclipse, тоді як кнопка [3] дозволяє вказати будь-який архів у файловій системі комп’ютера.
Вище відображаються три бібліотеки (Libraries):
- [JRE System Library]: базова бібліотека для Java-проектів Eclipse:

- [Tomcat v5.5 runtime]: бібліотека, що надається сервером Tomcat. Вона містить класи, необхідні для веб-розробки. Ця бібліотека включається до кожного веб-проєкту Eclipse, пов’язаного із сервером Tomcat.

Саме архів [servlet-api.jar] містить клас [javax.servlet.http.HttpServlet], який є батьківським класом для класу [ServletFormulaire], що ми зараз створюємо. Саме тому, що цей архів знаходиться в Classpath додатка, його було запропоновано як батьківський клас у майстрі, зображеному нижче.

Якби це не було так, він не з’явився б у списку пропозицій для [2]. Отже, якщо в цьому майстрі потрібно вказати батьківський клас, а його немає серед пропозицій, це означає, що або ви помилилися в назві цього класу, або архів, що його містить, відсутній у Classpath додатка.
- [Web App Libraries] містить архіви, що знаходяться в папці [WEB-INF/lib] проекту. Тут вона порожня:

Архіви з папки Classpath проекту Eclipse відображаються у провіднику проектів. Наприклад, для веб-проекту [personne]:

Оглядач проєктів надає доступ до вмісту цих архівів:

Отже, як показано вище, саме архів [servlet-api.jar] містить клас [javax.servlet.http.HttpServlet].
3.6.3. Налаштування сервлету
Матеріали [ref1]: розділ 2: 2.3, 2.3.1, 2.3.2, 2.3.3, 2.3.4
Файл [WEB-INF/web.xml] використовується для налаштування веб-додатку:

Цей файл для проєкту [personne] наразі має такий вигляд (див. стор. 32):
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
У ньому вказано лише наявність файлу-початкової сторінки (рядок 8). Ми модифікуємо його, щоб вказати:
- наявність сервлету [ServletFormulaire]
- URL, що обробляються цим сервлетом
- параметри ініціалізації сервлета
Файл web.xml нашого додатка «особа» матиме такий вигляд:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<servlet>
<servlet-name>formulairepersonne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletFormulaire
</servlet-class>
<init-param>
<param-name>defaultNom</param-name>
<param-value>inconnu</param-value>
</init-param>
<init-param>
<param-name>defaultAge</param-name>
<param-value>XXX</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>formulairepersonne</servlet-name>
<url-pattern>/formulaire</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Основні моменти цього конфігураційного файлу такі:
- рядки 7–24 пов’язані з наявністю сервлета [ServletFormulaire]
- рядки 7–20: налаштування сервлета здійснюється між тегами <servlet> та </servlet>. Додаток може містити кілька сервлетів і, відповідно, стільки ж розділів налаштування <servlet>...</servlet>.
- рядок 8: тег <servlet-name> присвоює сервлету ім’я — воно може бути будь-яким
- рядки 9–11: тег <servlet-class> вказує повну назву класу, що відповідає сервлету. Tomcat шукатиме цей клас у файлі Classpath веб-проєкту [personne]. Він знайде його у файлі [build/classes]:
![]()
- рядки 12–15: тег <init-param> слугує для передачі параметрів конфігурації сервлету. Зазвичай вони зчитуються у методі init сервлету, оскільки параметри його конфігурації мають бути відомі вже під час першого завантаження.
- рядки 13–14: тег <param-name> визначає ім’я параметра, а <param-value> — його значення.
- рядки 12–15 визначають параметр [defaultNom,"inconnu"], а рядки 16–19 — параметр [defaultAge,"XXX"]
- рядки 21–24: тег <servlet-mapping> слугує для прив’язки сервлету (servlet-name) до шаблону URL (url-pattern). У цьому випадку шаблон є простим. Він визначає, що щоразу, коли URL матиме вигляд /formulaire, слід використовувати сервлет formulairepersonne, c.a.d. клас [istia.st.servlets.ServletFormulaire] (рядки 8–11). Отже, сервлет [formulairepersonne] приймає лише один URL-адресу.
3.6.4. Код сервлета [ServletFormulaire]
Сервлет [ServletFormulaire] матиме такий код:
Вже при першому ознайомленні з сервлетом можна помітити, що він набагато складніший за відповідну сторінку JSP. Це загальне правило: сервлет не призначений для генерації коду HTML. Для цього призначені сторінки JSP. Ми ще повернемося до цього питання. Роз’яснимо кілька важливих моментів щодо наведеного вище сервлету:
- коли сервлет викликається вперше, викликається його метод init (рядок 20). Це єдиний випадок, коли він викликається.
- якщо сервлет було викликано методом HTTP GET, викликається метод doGet (рядок 32) для обробки запиту клієнта.
- якщо сервлет був викликаний методом HTTP POST, то для обробки запиту клієнта викликається метод doPost (рядок 82).
Метод init тут використовується для отримання у [web.xml] значень параметрів ініціалізації, що називаються «defaultNom» та «defaultAge». Метод init, що виконується під час початкового завантаження сервлета, є оптимальним місцем для отримання вмісту файлу [web.xml].
- рядок 22: отримується конфігурація [config] веб-проєкту. Цей об’єкт відображає вміст файлу [WEB-INF/web.xml] додатка.
- рядок 23: з цієї конфігурації отримується значення типу String параметра з назвою «defaultNom». Цим параметром буде ім’я особи. Якщо він не існує, буде отримано значення null.
- рядки 24–25: якщо параметр із назвою «defaultNom» не існує, змінній [defaultNom] присвоюється значення за замовчуванням.
- рядки 26–29: те саме робимо для параметра з назвою «defaultAge».
Метод doPost посилається на метод doGet. Це означає, що клієнт може надсилати свої параметри як за допомогою POST, так і за допомогою GET.
Метод doGet:
- рядок 32: метод отримує два параметри — request та response. request — це об’єкт, що представляє весь запит клієнта. Він має тип HttpServletRequest, який є інтерфейсом. response має тип HttpServletResponse, який також є інтерфейсом. Об’єкт response слугує для надсилання відповіді клієнту.
- request.getParameter("param") використовується для отримання у запиті клієнта значення параметра з іменем param. У рядку 36 отримуємо значення параметра «txtNom», у рядку 40 — значення параметра «txtAge». Якщо ці параметри відсутні у запиті, як значення параметра отримується null.
- рядки 37–39: якщо параметр «txtNom» відсутній у запиті, змінній «nom» присвоюється ім’я за замовчуванням «defaultNom», ініціалізоване в методі init. Те саме робиться в рядках 41–43 для віку.
- рядок 45: response.setContentType(String) слугує для встановлення значення заголовка HTTP Content-type. Цей заголовок вказує клієнту на тип документа, який він отримає. Тип text/html вказує на документ HTML.
- рядок 46: response.getWriter() служить для отримання потоку запису до клієнта
- рядки 47–78: документ HTML, який потрібно надіслати клієнту, записується у потік запису, отриманий у рядку 46.
Компіляція цього сервлета створить файл .class у папці [build/classes] проекту [personne]:

Читачеві рекомендується ознайомитися з довідкою Java щодо сервлетів. Для цього можна скористатися Tomcat. На сторінці входу в Tomcat 5 є посилання [Documentation]:

Це посилання веде на сторінку, яку читачеві пропонується переглянути. Посилання на документацію щодо сервлетів таке:

3.6.5. Тестування сервлета
Ми готові до тестування. Запустимо сервер Tomcat, якщо це необхідно.

Потім за допомогою браузера звернемося до URL [http://localhost:8080/personne/formulaire]. Тут ми звертаємося до URL-адреси [/formulaire] у контексті [/personne]. Файл [web.xml] цього контексту вказує, що URL-адреса [/formulaire] обробляється сервлетом із назвою [formulairepersonne]. У тому ж файлі вказано, що цей сервлет є класом [istia.st.servlets.ServletFormulaire]. Отже, саме цьому класу Tomcat доручить обробку запиту клієнта. Якщо клас ще не завантажено, його буде завантажено. Після цього він залишиться в пам’яті для обробки майбутніх запитів.
За допомогою вбудованого в Eclipse браузера отримуємо такий результат:

Ми отримуємо значення імені та віку за замовчуванням, які записані у файлі [web.xml]. Тепер спробуємо отримати URL та [http://localhost:8080/personne/formulaire?txtNom=tintin&txtAge=30]:

Цього разу ми отримуємо параметри, передані у запиті. Якщо читач не розуміє цих двох результатів, йому слід ще раз перечитати код сервлету [ServletFormulaire].
3.6.6. Автоматичне оновлення контексту веб-додатку
Запустимо Tomcat:

а потім змінимо код сервлета наступним чином:
- рядок 8 було змінено
Збережемо новий клас. Це збереження призведе до того, що Eclipse автоматично перекомпілює клас [ServletFormulaire], що буде виявлено Tomcat. Потім він перезавантажить контекст веб-додатку [personne], щоб врахувати зміни. Це відображається в журналах вікна [console]:

Запросімо URL-адресу [http://localhost:8080/personne/formulaire] без перезапуску Tomcat:

Зміни були успішно застосовані.
Тепер змінимо файл [web.xml] наступним чином:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<servlet>
<servlet-name>formulairepersonne</servlet-name>
...
<init-param>
<param-name>defaultNom</param-name>
<param-value>INCONNU</param-value>
</init-param>
...
</servlet>
...
</web-app>
- рядок 12 було змінено
Зробивши це, збережемо новий файл [web.xml]. У вікні [console] немає жодних записів у журналі, що вказують на перезавантаження контексту додатка. Запросимо URL-адресу [http://localhost:8080/personne/formulaire] без перезапуску Tomcat:

Зміни не були враховані. Перезапустимо Tomcat [clic droit sur serveur -> Restart -> Start]:

потім знову звернемося за URL-адресою [http://localhost:8080/personne/formulaire]:

Цього разу зміна, внесена в [web.xml], відображається.
Отже, зміна у файлі [web.xml] не спричиняє автоматичного перезавантаження веб-додатку, яке врахувало б новий файл конфігурації. Щоб примусово перезавантажити веб-додаток, можна перезапустити Tomcat, як ми це робили раніше, але це досить повільна операція. Краще скористатися інструментом [manager] для адміністрування додатків, розгорнутих у Tomcat. Щоб це стало можливим, у середовищі Eclipse Tomcat має бути налаштований так, як показано в розділі 2.5.
Спочатку за допомогою вбудованого браузера Eclipse відкрийте URL-адресу [http://localhost:8080], а потім перейдіть за посиланням [Tomcat Manager], як описано наприкінці розділу 2.5:

Відкриємо другий браузер [clic droit sur le navigateur -> New Editor]:
![]() | ![]() |
У цьому другому браузері введемо URL-адресу [http://localhost:8080/formulaire]:

Змінимо файл [web.xml] наступним чином, а потім збережемо його:
<!-- ServletFormulaire -->
<servlet>
<servlet-name>formulairepersonne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletFormulaire
</servlet-class>
<init-param>
<param-name>defaultNom</param-name>
<param-value>YYY</param-value>
</init-param>
<init-param>
<param-name>defaultAge</param-name>
<param-value>XXX</param-value>
</init-param>
</servlet>
Потім знову завантажимо URL-адресу [http://localhost:8080/formulaire]. Ми бачимо, що зміна не була врахована. Тепер перейдемо до першого браузера та перезавантажимо додаток [personne]:

Потім знову завантажимо URL-адресу [http://localhost:8080/formulaire] у другому браузері:

Зміна [web.xml] була врахована. На практиці для вирішення подібних випадків корисно мати відкритий браузер із додатком [manager] у Tomcat.
3.7. Взаємодія сервлетів та сторінок JSP
Література [ref1]: розділ 2: 2.3.7
Повернемося до двох розглянутих архітектур:

Жодна з цих двох архітектур не є задовільною. Обидві мають недолік, що поєднують дві технології: технологію програмування на Java, яка відповідає за логіку веб-додатку, та технологію кодування HTML, яка відповідає за відображення інформації у браузері.
- Рішення [1] на основі сторінки JSP має недолік, що поєднує код HTML та код Java в межах однієї сторінки. Ми цього не помітили на розглянутому прикладі, який був досить простим. Але якби [formulaire.jsp] мав перевіряти валідність параметрів [txtNom, txtAge] у запиті клієнта, нам довелося б розміщувати код Java на сторінці. Це дуже швидко стає некерованим.
- Рішення [2] на основі сервлета має ту саму проблему. Хоча в класі міститься лише код Java, він повинен генерувати документ HTML. І знову ж таки, якщо документ HTML не є простим, його генерація стає складною і практично неможливою для підтримки.
Ми уникнемо змішування технологій Java та HTML, застосувавши таку архітектуру:

- користувач надсилає свій запит до сервлету. Сервлет обробляє його та формує значення динамічних параметрів сторінки JSP [formulaire.jsp], які будуть використовуватися для формування відповіді HTML для клієнта. Ці значення утворюють так звану модель сторінки JSP.
- Завершивши свою роботу, сервлет звернеться до сторінки JSP [formulaire.jsp] із запитом на формування відповіді HTML для клієнта. Одночасно вона надасть клієнту елементи, необхідні сторінці JSP для формування цієї відповіді — саме ці елементи і складають модель сторінки.
Тепер ми розглянемо цю нову архітектуру.
3.7.1. Сервлет [ServletFormulaire2]
У наведеній вище архітектурі сервлет матиме назву [ServletFormulaire2]. Він буде створений у тому самому проєкті [personne], що й раніше, так само як і всі майбутні сервлети:

[ServletFormulaire2] спочатку створюється шляхом копіювання та вставлення [ServletFormulaire] у середовищі Eclipse:
- виділити [ServletFormulaire.java] -> клацнути правою кнопкою миші -> «Копіювати»
- виділити [istia.st.servlets.personne] -> клацнути правою кнопкою миші -> Вставити -> змінити ім’я на [ServletFormulaire2.java]
Потім ми змінюємо код [ServletFormulaire2] наступним чином:
Змінилася лише частина, що відповідає за формування відповіді HTTP (рядки 44–46):
- рядок 46: формування відповіді доручено сторінці JSP formulaire2.jsp. Ця сторінка, яку ми ще не розглядали, відповідатиме за відображення параметрів, отриманих із запиту клієнта: імені (рядки 35–38) та віку (рядки 39–42).
- Ці два значення розміщуються в атрибутах запиту [request], пов’язаних із ключами. Атрибути запиту обробляються як словник.
- рядок 44: ім’я вноситься до запиту, пов’язаного з ключем «ім’я»
- рядок 45: вік вноситься до запиту, пов’язаного з ключем «age»
- рядок 46: запит на відображення сторінки JSP [formulaire2.jsp]. До неї передаються такі параметри:
- запит [request] від клієнта, що дозволить сторінці JSP отримати доступ до її атрибутів, які щойно були ініціалізовані сервлетом
- відповідь [response], що дозволить сторінці JSP згенерувати відповідь HTTP для клієнта
Після написання класу [ServletFormulaire2] його скомпільований код з’являється у [build/classes]:

3.7.2. Сторінка JSP [formulaire2.jsp]
Сторінка JSP formulaire2.jsp отримується шляхом копіювання та вставлення зі сторінки [formulaire.jsp]

а потім перетворено таким чином:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
// отримуємо значення, необхідні для відображення
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Personne - formulaire2</title>
</head>
<body>
<center>
<h2>Personne - formulaire2</h2>
<hr>
<form action="" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="<%= nom %>" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="<%= age %>" type="text" size="3"></td>
</tr>
</table>
<table>
<tr>
<td><input type="submit" value="Envoyer"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="button" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
Порівняно з [formulaire.jsp] змінилися лише рядки 4–8:
- рядок 6: отримує значення атрибута з назвою «nom» із запиту [request], атрибут, створений сервлетом [ServletFormulaire2].
- рядок 7: робить те саме для атрибута «age»
3.7.3. Налаштування додатка
Файл конфігурації [web.xml] змінюється наступним чином:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<!-- ServletFormulaire -->
<servlet>
<servlet-name>formulairepersonne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletFormulaire
</servlet-class>
<init-param>
<param-name>defaultNom</param-name>
<param-value>inconnu</param-value>
</init-param>
<init-param>
<param-name>defaultAge</param-name>
<param-value>XXXX</param-value>
</init-param>
</servlet>
<!-- ServletFormulaire 2-->
<servlet>
<servlet-name>formulairepersonne2</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletFormulaire2
</servlet-class>
<init-param>
<param-name>defaultNom</param-name>
<param-value>inconnu</param-value>
</init-param>
<init-param>
<param-name>defaultAge</param-name>
<param-value>XXX</param-value>
</init-param>
</servlet>
<!-- Мапування ServletFormulaire -->
<servlet-mapping>
<servlet-name>formulairepersonne</servlet-name>
<url-pattern>/formulaire</url-pattern>
</servlet-mapping>
<!-- Відповідність ServletFormulaire 2-->
<servlet-mapping>
<servlet-name>formulairepersonne2</servlet-name>
<url-pattern>/formulaire2</url-pattern>
</servlet-mapping>
<!-- файли-шаблони -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Ми зберегли існуючий код та додали:
- рядки 22–36: розділ <servlet> для визначення нового сервлета ServletFormulaire2
- рядки 42–46: розділ <servlet-mapping> для прив’язки до нього URL /formulaire2
Запустіть або перезапустіть сервер Tomcat, якщо це необхідно. Ми запитуємо URL
http://localhost:8080/personne/formulaire2?txtNom=milou&txtAge=10:

Ми отримуємо той самий результат, що й раніше, але структура нашого додатка тепер стала чіткішою: сервлет, що містить логіку додатка та делегує сторінці JSP відправку відповіді клієнту. Відтепер ми завжди будемо діяти саме так.



