1. Загальні відомості
PDF цього документа доступний за посиланням |TYT|.
1.1. Цілі
Тут ми пропонуємо ознайомитися з методом розробки під назвою STRUTS. Jakarta Struts — це проєкт Apache Software Foundation (www.apache.org), метою якого є надання стандартного фреймворку для розробки веб-додатків на Java, що відповідає архітектурі, відомій як MVC (Модель-Вигляд-Контролер).
1.2. Модель MVC
Модель MVC спрямована на розділення рівнів представлення, обробки та доступу до даних. Веб-додаток, що відповідає цій моделі, матиме таку архітектуру:
![]() |
Таку архітектуру називають трирівневою або трикомпонентною:
- інтерфейс користувача — це V (представлення)
- логіка додатка — це C (контролер)
- джерела даних — це M (модель)
Інтерфейс користувача часто є веб-браузером, але це може бути також автономний додаток, який через мережу надсилає запити HTTP до веб-сервісу та оформлює результати, які той йому повертає. Логіка додатка складається зі скриптів, що обробляють запити користувача. Джерелом даних часто є база даних, але це можуть бути також прості текстові файли, каталог LDAP, віддалений веб-сервіс тощо. Розробнику вигідно підтримувати значну незалежність між цими трьома компонентами, щоб у разі зміни одного з них інші два не потребували змін або потребували їх у мінімальному обсязі.
При спробі застосувати цю модель із сервлетами та сторінками JSP отримуємо таку архітектуру:
![]() |
У блоці [Logique Applicative] виділяється
- сервлет, який є вхідними воротами додатка і який також називають контролером
- блок [Classes métier], що об’єднує класи Java, необхідні для реалізації логіки додатка;
- блок [Classes d'accès aux données], що об’єднує класи Java, необхідні для отримання даних, потрібних сервлету, часто це постійні дані (BD, файли, служба WEB тощо)
- блок сторінок JSP, що утворюють представлення додатка.
1.3. Підхід до розробки MVC із використанням сервлетів та сторінок JSP
Ми визначили підхід до розробки веб-додатків на Java, що відповідає наведеному вище MVC-моделі. Нагадаємо його тут.
- Спочатку визначимо всі види додатка. Це веб-сторінки, що відображаються користувачеві. Тому при розробці видів ми будемо виходити з точки зору користувача. Вирізняємо три типи видів:
- форма введення даних, призначена для отримання інформації від користувача. Зазвичай вона має кнопку для надсилання введених даних на сервер.
- сторінка відповіді, яка служить виключно для надання інформації користувачеві. Вона часто має посилання, що дозволяє користувачеві продовжити роботу з додатком на іншій сторінці.
- змішана сторінка: сервлет надіслав клієнту сторінку, що містить інформацію, яку він згенерував. Ця сама сторінка слугуватиме клієнту для надання сервлету іншої інформації.
- Кожен вигляд дасть початок сторінці JSP. Для кожної з них:
- буде визначено зовнішній вигляд сторінки
- буде визначено, які її частини є динамічними:
- інформація, призначена для користувача, яку сервлет повинен передати у вигляді параметрів до подання JSP
- дані введення, які повинні бути передані сервлету для обробки. Вони повинні бути частиною форми HTML.
- Можна схематично зобразити вхідні та вихідні дані кожного подання
![]() |
- вхідні дані — це дані, які сервлет повинен надати сторінці JSP у запиті (request) або сесії (session).
- Виходи — це дані, які сторінка JSP повинна надати сервлету. Вони є частиною форми HTML, і сервлет отримає їх за допомогою операції типу request.getparameter(...).
- Ми напишемо код Java/JSP для кожного подання. Найчастіше він матиме такий вигляд:
<%@ page ... %> // найчастіші імпорти класів
<%!
// змінні екземпляру сторінки JSP (=глобальні)
// потрібно лише в тому випадку, якщо сторінка JSP має методи, що використовують спільні змінні (рідко)
...
%>
<%
// отримання даних, надісланих сервлетом
// або у запиті (request), або у сесії (session)
...
%>
<html>
...
// тут ми намагатимемося мінімізувати код Java
</html>
- Тепер можна перейти до перших тестів. Метод розгортання, описаний нижче, є специфічним для сервера Tomcat:
- контекст додатка потрібно створити у файлі server.xml сервера Tomcat. Можна почати з тестування саме цього контексту. Нехай C — це контекст, а DC — папка, пов’язана з ним. Створимо статичний файл test.html, який розмістимо в папці DC. Після запуску Tomcat у браузері відкриємо сторінку URL http://localhost:8080/DC/test.html.
- Кожну сторінку JSP можна перевірити. Якщо сторінка JSP називається formulaire.jsp, то в браузері потрібно буде запросити URL за адресою http://localhost:8080/DC/formulaire.jsp. Сторінка JSP очікує значення від сервлету, який її викликає. Тут ми викликаємо її безпосередньо, тому вона не отримає очікуваних параметрів. Щоб все ж таки можна було провести тестування, ми самостійно ініціалізуємо на сторінці JSP очікувані параметри за допомогою констант. Ці перші тести дозволяють перевірити, чи сторінки JSP є синтаксично правильними.
- Далі ми напишемо код сервлета. Він має два чітко розмежовані методи:
- метод init, який слугує для:
- отримання параметрів конфігурації додатка з файлу web.xml
- за необхідності створити екземпляри бізнес-класів, які їй знадобляться надалі
- обробки можливого списку помилок ініціалізації, який буде надіслано майбутнім користувачам додатка. Ця обробка помилок може включати навіть надсилання електронного листа адміністратору додатка з метою попередження про збій у роботі
- метод doGet або doPost залежно від того, як сервлет отримує параметри від клієнтів. Якщо сервлет обробляє кілька форм, бажано, щоб кожна з них надсилала інформацію, яка однозначно її ідентифікує. Це можна зробити за допомогою прихованого атрибута у формі типу <input type="hidden" name="action" value="...">. Сервлет може спочатку зчитати значення цього параметра, а потім делегувати обробку запиту внутрішньому приватному методу, призначеному для обробки цього типу запитів.
- Слід максимально уникати розміщення бізнес-коду в сервлеті. Вона не призначена для цього. Сервлет — це свого роду керівник команди (контролер), який отримує запити від своїх клієнтів (веб-клієнтів) і доручає їх виконання найбільш підходящим особам (бізнес-класам). Під час написання сервлета визначається інтерфейс бізнес-класів, які потрібно створити (конструктори, методи). Це стосується випадків, коли ці бізнес-класи ще не створені. Якщо вони вже існують, то сервлет повинен адаптуватися до існуючого інтерфейсу.
- Код сервлета буде скомпільовано.
- Ми напишемо каркас бізнес-класів, необхідних для сервлета. Наприклад, якщо сервлет використовує об’єкт типу proxyArticles і цей клас повинен мати метод getCodes, що повертає список (ArrayList) символьних рядків, то на першому етапі можна обмежитися написанням:
public ArrayList getCodes(){
String[] codes= {"code1","code2","code3"};
ArrayList aCodes=new ArrayList();
for(int i=0;i<codes.length;i++){
aCodes.add(codes[i]);
}
return aCodes;
}
- Тепер можна перейти до тестування сервлета.
- Необхідно створити файл конфігурації web.xml для додатка. Він повинен містити всю інформацію, яку очікує метод init сервлета (<init-param>). Крім того, встановлюємо URL, через який буде здійснюватися доступ до головного сервлета (<servlet-mapping>).
- Усі необхідні класи (сервлети, бізнес-класи) розміщуються в WEB-INF/classes.
- Усі необхідні бібліотеки класів (.jar) розміщуються в WEB-INF/lib. Ці бібліотеки можуть містити бізнес-класи, драйвери JDBC тощо.
- Види JSP розміщуються в кореневому каталозі додатка або в окремій папці. Те саме робиться з іншими ресурсами (html, зображення, аудіо, відео тощо)
- Після цього додаток тестується, а перші помилки виправляються. Наприкінці цього етапу архітектура додатка стає працездатною. Цей етап тестування може виявитися складним, оскільки в Tomcat немає інструментів налагодження. Для цього Tomcat сам повинен бути інтегрований у середовище розробки (JBuilder Developer, Sun One Studio тощо). Можна скористатися командами System.out.println("...."), які виводять інформацію у вікно Tomcat. Перше, що слід перевірити, — чи метод init правильно отримує всі дані з файлу web.xml. Для цього можна вивести значення цих даних у вікно Tomcat. Таким самим чином слід перевірити, чи методи doGet та doPost правильно отримують параметри різних форм HTML додатка.
Напишемо бізнес-класи, необхідні сервлету. Зазвичай це класична розробка класу Java, який найчастіше є незалежним від будь-якого веб-додатку. Спочатку його протестують поза цим середовищем, наприклад, за допомогою консольного додатка. Після написання бізнес-класу його можна інтегрувати в архітектуру розгортання веб-додатку та перевірити правильність його інтеграції в нього. Таким чином діють для кожного бізнес-класу.
1.4. Підхід до розробки STRUTS
Розробники методології STRUTS прагнули визначити стандартний метод розробки, який би відповідав архітектурі MVC для веб-додатків, написаних на Java. Проєкт STRUTS має два аспекти:
- метод розробки. Ми побачимо, що він досить близький до того, що описано вище для сервлетів та сторінок JSP
- інструменти, які дозволяють нам застосовувати цей метод розробки. Це бібліотеки класів Java, які можна знайти на сайті фонду Apache (www.apache.org).
1.4.1. Метод розробки
Архітектура MVC, що використовується STRUTS, є такою:
![]() |
- контролер є серцевиною додатка. Усі запити клієнта проходять через нього. Це загальний сервлет, що надається STRUTS. У деяких випадках може знадобитися його похідна. У простих випадках це не потрібно. Цей загальний сервлет отримує необхідну інформацію з файлу, який найчастіше називається struts-config.xml.
- Якщо запит клієнта містить параметри форми, вони поміщаються в об’єкт Bean. Клас називається типом bean, якщо він дотримується правил побудови, які ми розглянемо трохи пізніше. Об’єкти bean, створені таким чином з часом, зберігаються в сесії або запиті клієнта. Цей параметр можна налаштувати. Їх не потрібно створювати заново, якщо вони вже були створені.
- У файлі конфігурації struts-config.html до кожного URL, який має оброблятися програмою (тобто не відповідає погляду JSP, який можна було б запитати безпосередньо), прив’язується певна інформація:
- ім'я класу типу Action, відповідального за обробку запиту. І в цьому випадку інстанційований об'єкт Action може зберігатися в сесії або в запиті.
- якщо запитуваний URL має параметри (наприклад, у разі надсилання форми до контролера), вказується ім’я біна, відповідального за збереження інформації з форми.
- Маючи цю інформацію, надану його конфігураційним файлом, при отриманні запиту URL від клієнта контролер здатний визначити, чи потрібно створювати bean і який саме. Після створення екземпляра bean може перевірити, чи є дані, які він зберіг і які походять із форми, дійсними чи ні. Контролер автоматично викликає метод біна під назвою validate. Бін створюється розробником. Отже, розробник розміщує в методі validate код, що перевіряє правильність даних форми. Якщо дані виявляються недійсними, контролер не продовжує обробку. Він передає управління представленню, ім’я якого знайде у своєму файлі конфігурації. На цьому обмін завершується. Слід зазначити, що розробник може вимагати, щоб валідність форми не перевірялася. Він робить це також у файлі struts-config.html. У цьому випадку контролер не викликає метод validate біна.
- Якщо дані біна правильні, або якщо перевірка не проводиться, або якщо біна немає, контролер передає управління об’єкту типу Action, пов’язаному з URL. Він робить це, вимагаючи виконання методу `execute` цього об’єкта, якому передає посилання на бін, який він, можливо, створив. Саме тут розробник виконує необхідні дії: йому, можливо, доведеться викликати бізнес-класи або класи доступу до даних. Після завершення обробки об’єкт `Action` повертає контролеру ім’я подання, яке той повинен надіслати у відповідь клієнту.
- Контролер надсилає цю відповідь. Обмін даними з клієнтом завершено.
Починає вимальовуватися методологія розробки STRUTS:
- визначення подання. Розрізняють подання, які є формами, та інші.
- Кожен вид-форма породжує визначення у файлі struts-config.xml. У ньому визначається така інформація:
- ім’я класу Bean, який міститиме дані форми, а також вказівку на те, чи мають дані перевірятися. Якщо їх потрібно перевіряти і вони виявляються недійсними, слід вказати, який вигляд слід надіслати клієнту у відповідь у цьому випадку.
- ім’я класу Action, відповідального за обробку форми;
- назви всіх подань, які можуть бути надіслані клієнту у відповідь після обробки запиту. Клас Action обере одне з них залежно від результату обробки.
- Кожна сторінка є об’єктом сторінки JSP. Ми побачимо, що в сторінках, зокрема у формах, іноді використовується бібліотека тегів, властива Struts.
- Кожен вид-форма породжує визначення у файлі struts-config.xml. У ньому визначається така інформація:
- Написання класів JavaBean, що відповідають формам
- написання класів Action, відповідальних за обробку форм
- написання можливих бізнес-класів або класів доступу до даних
1.4.2. Інструменти розробки STRUTS
Проєкт STRUTS є одним із проєктів Apache Software Foundation. Деякі з цих проєктів об’єднані під назвою Jakarta і доступні на сайті URL http://jakarta.apache.org:

Рекомендуємо ознайомитися з цією сторінкою. Багато проектів представляють інтерес для розробників Java. Якщо перейти за наведеним вище посиланням Struts, ми потрапимо на головну сторінку проекту:

Тут також рекомендується ознайомитися з головною сторінкою. Щоб завантажити Java-бібліотеки Struts, перейдіть за посиланням «Binaries», наведеним вище:

Для користувачів Windows слід скористатися посиланням 1.1.zip, а для користувачів Unix — 1.1.tar.gz (листопад 2003 р.). Після розпакування файлу 1.1.zip ми отримаємо таку структуру каталогів:

У цій структурі знаходяться бібліотеки класів Java, необхідні для розробки STRUTS. Вони містяться у файлах .jar або .war, аналогічних до файлів .zip. Їх можна відкрити за допомогою тих самих утиліт. Більшість необхідних бібліотек знаходяться у вищезазначеній папці lib:

Окрім бібліотек класів у форматі .jar, тут також містяться файли .dtd (Document Type Definition), які містять правила валідності файлів XML. Файл XML може у своєму вмісті посилатися на такий файл DTD. Програма (так званий парсер), яка аналізує вміст файлу XML, використовуватиме правила валідності, знайдені у файлі DTD, на який є посилання, щоб визначити, чи є файл XML синтаксично правильним. Так, наприклад, файл struts-config_1_1.dtd визначає правила побудови конфігураційного файлу struts-config.xml для версії 1.1 Struts.
Тепер розглянемо, де розміщувати різні елементи дерева Struts для розгортання Struts-додатку на сервері Tomcat.
1.5. Розгортання додатка Struts
Додаток Struts — це веб-додаток, як і будь-який інший. Тому він дотримується правил розгортання контейнера, в якому виконується. У цьому прикладі додаток, який ми назвемо strutspersonne, буде виконуватися на сервері Tomcat версії 4.x. У додатку наведено інструкцію з розгортання для Tomcat версії 5.x. Тут ми дотримуємося правил розгортання Tomcat 4.x:
- Ми визначаємо контекст strutspersonne у файлі конфігурації server.xml сервера Tomcat:
Після цього, за необхідності, перезапускаємо Tomcat, щоб він врахував новий контекст. Ми можемо перевірити правильність налаштування контексту, виконавши запит URL http://localhost:8080/strutspersonne :

Якщо не з’являється сторінка з помилками, це означає, що контекст налаштований правильно.
- У фізичній папці, пов’язаній із контекстом strutspersonne, створюємо підпапку WEB-INF.
- У папці WEB-INF додатка ми визначаємо файл конфігурації web.xml додатка:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
- Клас контролера (сервлета) додатка — це попередньо визначений клас Stuts, який називається ActionServlet. Він міститься у файлі struts.jar. Щоб Tomcat міг знайти цей клас, ми розмістимо файл struts.jar у папці <tomcat>\common\lib, яка є однією з папок, що перевіряються Tomcat під час пошуку класів. Фактично ми розмістимо там усі файли .jar, знайдені в папці <struts>\lib, де <struts> — це коренева папка дерева Struts.

- Також слід розмістити файли struts-el.jar та jstl.jar, що знаходяться в папці <struts>\contrib\struts-el\lib:

- Тут ми маємо доступ до веб-сервера. Це не завжди так. Якщо ми розгортаємо веб-додаток на Java у веб-контейнері, яким не керуємо самостійно, краще, щоб додаток містив усі необхідні бібліотеки. У такому разі їх слід розмістити у папці WEB-INF/lib, яку потрібно створити.
- Ми зазначили, що контролер потребує певної інформації, яку зазвичай він знаходить у файлі struts-config.xml, розміщеному в тій самій папці, що й web.xml. Насправді ім’я цього файлу можна налаштувати. Саме параметр config, наведений вище, визначає це ім’я.
- Тег <servlet-mapping> вказує, що до контролера можна буде звернутися через усі файли URL, що закінчуються суфіксом .do. Таке прив’язування є обов’язковим для Struts. Потім ці URL будуть відфільтровані контролером, який прийматиме лише ті URL, що зазначені в його конфігураційному файлі struts-config.xml
Наразі нашого файлу web.xml цілком достатньо.
- Ми запитаємо URL /main.do у додатку strutspersonne. Згідно з попереднім файлом web.xml, цей файл URL буде передано сервлету org.apache.struts.action. Буде створено екземпляр класу ActionServlet і викликано його метод init. Цей метод намагається прочитати файл конфігурації, визначений параметром config. Отже, цей файл має існувати. Ми створюємо такий файл struts-config.xml:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<action-mappings>
<action
path="/main"
parameter="/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
</struts-config>
Зауважимо, що файл DTD з struts-config.xml не є таким самим, як у файлі web.xml, що вказує на те, що вони мають різну структуру. Для кожного URL, який повинен обробляти контролер, нам потрібно визначити тег <action>. Він слугує для того, щоб вказати контролеру, що він повинен робити, коли йому надходить запит на цей URL. Тут ми вказуємо такі елементи:
- path="/main": визначає ім’я URL, налаштованого тегом <action>. Суфікс .do є неявним.
- type="org.apache.struts.actions.ForwardAction": визначає ім’я класу Action, який має обробити запит. Тут використовується клас Action, попередньо визначений у Struts. Він сам нічого не робить, а лише переадресовує запит клієнта до URL, вказаного в атрибуті parameter.
- parameter="/main.html": ім’я URL, якому має бути передано запит. У цьому випадку це статичний файл HTML.
Отже, коли користувач запитає файл URL /main.do, він отримає файл URL /main.html.
- Файл main.html матиме такий вигляд:
<html>
<head>
<title>Application strutspersonne</title>
</head>
<body>
Application strutspersonne active ....
</body>
</html>
Цей файл розміщений у папці додатка strutspersonne/vues:

Замовити його можна безпосередньо за номером URL http://localhost:8080/strutspersonne/main.html:

У цьому випадку контролер Struts додатка не втручався, оскільки він спрацьовує лише при запиті на файл URL з розширенням *.do. Однак у даному випадку було зроблено запит на файл URL /vues/main.html.
- Створений раніше файл struts-config.xml потрібно розмістити в тій самій папці WEB-INF, що й файл web.xml:

- Тепер ми перевіримо правильність роботи контролера додатка strutspersonne, звернувшись до файлів URL /main.do після того, як, за необхідності, перезапустимо Tomcat.

Тут спрацював контролер Struts, оскільки ми запросили URL типу *.do. Ми дійсно отримали очікувану сторінку (main.html). Отже, ми маємо основні елементи функціонування нашого додатка: контекст strutspersonne, конфігураційні файли web.xml та struts-config.xml, а також бібліотеки Struts.
Що б сталося, якби ми запросили URL типу /toto.do? Згідно з файлом web.xml додатка strutspersonne, для її обробки викликається контролер Struts. Він перевіряє свій файл конфігурації struts-config.html і не знаходить жодних налаштувань для запиту URL /toto. Що ж він робить у такому випадку? Спробуємо:

Ми отримуємо сторінку з помилками, що здається нормальним. Тепер ми можемо приступити до написання додатка.



