Skip to content

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-моделі. Нагадаємо його тут.

  1. Спочатку визначимо всі види додатка. Це веб-сторінки, що відображаються користувачеві. Тому при розробці видів ми будемо виходити з точки зору користувача. Вирізняємо три типи видів:
    • форма введення даних, призначена для отримання інформації від користувача. Зазвичай вона має кнопку для надсилання введених даних на сервер.
    • сторінка відповіді, яка служить виключно для надання інформації користувачеві. Вона часто має посилання, що дозволяє користувачеві продовжити роботу з додатком на іншій сторінці.
    • змішана сторінка: сервлет надіслав клієнту сторінку, що містить інформацію, яку він згенерував. Ця сама сторінка слугуватиме клієнту для надання сервлету іншої інформації.
  1. Кожен вигляд дасть початок сторінці JSP. Для кожної з них:
    • буде визначено зовнішній вигляд сторінки
    • буде визначено, які її частини є динамічними:
      • інформація, призначена для користувача, яку сервлет повинен передати у вигляді параметрів до подання JSP
      • дані введення, які повинні бути передані сервлету для обробки. Вони повинні бути частиною форми HTML.
  1. Можна схематично зобразити вхідні та вихідні дані кожного подання
    • вхідні дані — це дані, які сервлет повинен надати сторінці JSP у запиті (request) або сесії (session).
    • Виходи — це дані, які сторінка JSP повинна надати сервлету. Вони є частиною форми HTML, і сервлет отримає їх за допомогою операції типу request.getparameter(...).
  1. Ми напишемо код Java/JSP для кожного подання. Найчастіше він матиме такий вигляд:
<%@ page ... %>    // найчастіші імпорти класів
<%!
     // змінні екземпляру сторінки JSP (=глобальні)
     // потрібно лише в тому випадку, якщо сторінка JSP має методи, що використовують спільні змінні (рідко)     
    ...    
%>
<%
     // отримання даних, надісланих сервлетом
     // або у запиті (request), або у сесії (session)
    ...
%>

<html>
...
         // тут ми намагатимемося мінімізувати код Java
</html>
  1. Тепер можна перейти до перших тестів. Метод розгортання, описаний нижче, є специфічним для сервера 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 є синтаксично правильними.
  1. Далі ми напишемо код сервлета. Він має два чітко розмежовані методи:
    • метод init, який слугує для:
      • отримання параметрів конфігурації додатка з файлу web.xml
      • за необхідності створити екземпляри бізнес-класів, які їй знадобляться надалі
      • обробки можливого списку помилок ініціалізації, який буде надіслано майбутнім користувачам додатка. Ця обробка помилок може включати навіть надсилання електронного листа адміністратору додатка з метою попередження про збій у роботі
    • метод doGet або doPost залежно від того, як сервлет отримує параметри від клієнтів. Якщо сервлет обробляє кілька форм, бажано, щоб кожна з них надсилала інформацію, яка однозначно її ідентифікує. Це можна зробити за допомогою прихованого атрибута у формі типу <input type="hidden" name="action" value="...">. Сервлет може спочатку зчитати значення цього параметра, а потім делегувати обробку запиту внутрішньому приватному методу, призначеному для обробки цього типу запитів.
    • Слід максимально уникати розміщення бізнес-коду в сервлеті. Вона не призначена для цього. Сервлет — це свого роду керівник команди (контролер), який отримує запити від своїх клієнтів (веб-клієнтів) і доручає їх виконання найбільш підходящим особам (бізнес-класам). Під час написання сервлета визначається інтерфейс бізнес-класів, які потрібно створити (конструктори, методи). Це стосується випадків, коли ці бізнес-класи ще не створені. Якщо вони вже існують, то сервлет повинен адаптуватися до існуючого інтерфейсу.
    • Код сервлета буде скомпільовано.
  1. Ми напишемо каркас бізнес-класів, необхідних для сервлета. Наприклад, якщо сервлет використовує об’єкт типу 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;
}
  1. Тепер можна перейти до тестування сервлета.
    • Необхідно створити файл конфігурації 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.
  • Написання класів JavaBean, що відповідають формам
  • написання класів Action, відповідальних за обробку форм
  • написання можливих бізнес-класів або класів доступу до даних

1.4.2. Інструменти розробки STRUTS

Проєкт STRUTS є одним із проєктів Apache Software Foundation. Деякі з цих проєктів об’єднані під назвою Jakarta і доступні на сайті URL http://jakarta.apache.org:

Image

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

Image

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

Image

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

Image

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

Image

Окрім бібліотек класів у форматі .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:

  1. Ми визначаємо контекст strutspersonne у файлі конфігурації server.xml сервера Tomcat:
                <Context path="/strutspersonne" docBase="e:/data/serge/web/struts/personne" />

Після цього, за необхідності, перезапускаємо Tomcat, щоб він врахував новий контекст. Ми можемо перевірити правильність налаштування контексту, виконавши запит URL http://localhost:8080/strutspersonne :

Image

Якщо не з’являється сторінка з помилками, це означає, що контекст налаштований правильно.

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

Image

<?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.

Image

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

Image

  • Тут ми маємо доступ до веб-сервера. Це не завжди так. Якщо ми розгортаємо веб-додаток на Java у веб-контейнері, яким не керуємо самостійно, краще, щоб додаток містив усі необхідні бібліотеки. У такому разі їх слід розмістити у папці WEB-INF/lib, яку потрібно створити.
  • Ми зазначили, що контролер потребує певної інформації, яку зазвичай він знаходить у файлі struts-config.xml, розміщеному в тій самій папці, що й web.xml. Насправді ім’я цього файлу можна налаштувати. Саме параметр config, наведений вище, визначає це ім’я.
  • Тег <servlet-mapping> вказує, що до контролера можна буде звернутися через усі файли URL, що закінчуються суфіксом .do. Таке прив’язування є обов’язковим для Struts. Потім ці URL будуть відфільтровані контролером, який прийматиме лише ті URL, що зазначені в його конфігураційному файлі struts-config.xml

Наразі нашого файлу web.xml цілком достатньо.

  1. Ми запитаємо 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. Тут ми вказуємо такі елементи:

  1. path="/main": визначає ім’я URL, налаштованого тегом <action>. Суфікс .do є неявним.
  2. type="org.apache.struts.actions.ForwardAction": визначає ім’я класу Action, який має обробити запит. Тут використовується клас Action, попередньо визначений у Struts. Він сам нічого не робить, а лише переадресовує запит клієнта до URL, вказаного в атрибуті parameter.
  3. parameter="/main.html": ім’я URL, якому має бути передано запит. У цьому випадку це статичний файл HTML.

Отже, коли користувач запитає файл URL /main.do, він отримає файл URL /main.html.

  1. Файл main.html матиме такий вигляд:
<html>
    <head>
      <title>Application strutspersonne</title>
  </head>
  <body>
      Application strutspersonne active ....
  </body>
</html>

Цей файл розміщений у папці додатка strutspersonne/vues:

Image

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

Image

У цьому випадку контролер Struts додатка не втручався, оскільки він спрацьовує лише при запиті на файл URL з розширенням *.do. Однак у даному випадку було зроблено запит на файл URL /vues/main.html.

  1. Створений раніше файл struts-config.xml потрібно розмістити в тій самій папці WEB-INF, що й файл web.xml:

Image

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

Image

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

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

Image

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