16. Приклад 13 — контекст дії
Ця програма має на меті продемонструвати, що дія має доступ:
- до параметрів запиту
- до атрибутів запиту
- до атрибутів сеансу користувача
![]() |
16.1. Проєкт NetBeans
![]() |
Проект NetBeans виглядає так:
- у [1], представлення [Context.JSP]
- у [2] — дія [Action1.java] та файл конфігурації Struts [example.xml]
16.2. Configuration
Налаштування проекту здійснюється у файлі [example.xml]:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" namespace="/example" extends="struts-default">
<action name="Action1" class="example.Action1">
<result name="success">/example/Context.JSP</result>
</action>
</package>
</struts>
- рядок 8: запит URL [/example/Action1] спричинить інстанціювання класу [example.Action]. Оскільки метод не вказано, буде виконано метод execute.
- рядок 9: допускається лише один ключ. Ключ success призводить до відображення подання [Context.JSP].
Спрощена архітектура обробки запиту буде такою:
![]() |
Запит оброблятиметься двома елементами веб-додатку: дією [Action1] [1] та поданням [Context.JSP] [2]. Ці два елементи мають доступ до даних різного типу:
- дані області дії Application, [3], c.a.d — дані, доступні для всіх запитів усіх користувачів. Вони майже завжди доступні лише для читання. У цих даних часто міститься початкова конфігурація додатка. У даному випадку доступ до цих даних мають [Action1] та [Context.JSP].
- Дані з областю дії Session, [4], c.a.d. Ці дані доступні для всіх запитів одного й того самого користувача. Вони доступні як для читання, так і для запису. Тут [Action1] використовуватиме сесію з правами на читання та запис, тоді як [Context.JSP] використовуватиме її лише для читання.
- дані області дії Requête [5], доступні для всіх елементів, що обробляють запит. Тут [Action1] запише дані в цю пам’ять, а [Context.JSP] їх отримає. Дані області дії «Запит» дозволяють елементу N передавати інформацію елементу N+1.
- Параметри запиту [6], надіслані клієнтом. Вони використовуються лише для читання елементами, що обробляють запит.
16.3. Дія [Action1]
Код класу [Action1] має такий вигляд:
package example;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import java.util.Set;
import org.apache.struts2.interceptor.ParameterAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;
public class Action1 extends ActionSupport implements SessionAware, RequestAware, ParameterAware {
// конструктор без параметрів
public Action1() {
}
// Сесія, запит, параметри
Map<String, Object> session;
Map<String, Object> request;
Map<String, String[]> parameters;
@Override
public String execute() {
// список параметрів
System.out.println("Paramètres...");
Set<String> clés = parameters.keySet();
for (String clé : clés) {
for (String valeur : parameters.get(clé)) {
System.out.println(String.format("[%s,%s]", clé, valeur));
}
}
// сесія
System.out.println("Session...");
if (session.get("compteur") == null) {
session.put("compteur", new Integer(0));
}
Integer compteur = (Integer) session.get("compteur");
compteur = compteur + 1;
session.put("compteur", compteur);
System.out.println(String.format("compteur=%s", compteur));
// запит
request.put("info1", "information1");
// відображення сторінки JSP
return SUCCESS;
}
// сесія
public void setSession(Map<String, Object> session) {
this.session = session;
}
// запит
public void setRequest(Map<String, Object> request) {
this.request = request;
}
// параметри
public void setParameters(Map<String, String[]> parameters) {
this.parameters = parameters;
}
}
- рядок 10: клас реалізує такі інтерфейси
- SessionAware: для доступу до словника атрибутів сесії (рядок 16). Цей інтерфейс має лише один метод, який міститься в рядку 46.
- RequestAware: для доступу до словника атрибутів запиту (рядок 17). Цей інтерфейс має лише один метод, який міститься в рядку 51.
- ParameterAware: для доступу до словника параметрів запиту (рядок 18). Слід зауважити, що кожному ключу (назва параметра) відповідає масив значень. Це необхідно для врахування полів введення, які передають кілька значень, наприклад, список із можливістю множинного вибору. Інтерфейс ParameterAware має лише один метод, який міститься у рядку 56.
- рядок 21: метод execute, який виконується при виклику дії [Action1]. На момент його виконання перехоплювачі вже виконали свою роботу:
- був викликаний метод setParameters (рядок 56), а словник parameters у рядку 18 містить усі параметри запиту.
- був викликаний метод setSession (рядок 46), а словник session у рядку 16 містить усі атрибути сеансу.
- був викликаний метод setRequest (рядок 51), а словник request у рядку 17 містить усі атрибути запиту.
- рядки 31–38: значення, пов’язане з ключем compteur, записується в сесію
- рядки 32–34: у сесії шукається ключ compteur. Якщо його там немає, його додають із цілочисельним значенням 0.
- рядки 35–37: у сесії шукається ключ compteur, його значення збільшується, після чого ключ знову записується в сесію.
- рядок 38: відображається значення, пов’язане з ключем compteur. Оскільки інкремент виконується при кожному запиті до дії [Action1], ми повинні бачити, як значення лічильника зростає у міру надходження запитів.
- рядок 40: у словник атрибутів запиту вставляється атрибут із ключем info1 та значенням information1. Атрибути запиту відрізняються від його параметрів. Параметри надсилаються клієнтом веб-додатку. Атрибути запиту, у свою чергу, забезпечують взаємодію між різними елементами веб-додатку, які його обробляють. Таким чином, після виконання [Action1] буде відображено представлення [Context.JSP]. Ми побачимо, що воно здатне отримувати атрибути запиту.
- рядок 42: метод execute повертає ключ succes.
16.4. Файл повідомлень
Файл [messages.properties] має такий вигляд:
Context.titre=Contexte de l''action
Context.message=Contexte de l''action
Context.parameters=Param\u00E8tres de l''action
Context.session=Elements de session
Context.request=Attributs de requ\u00EAte
16.5. Вигляд [Context.JSP]
Вигляд [Context.JSP] призначений для відображення:
- деякі параметри запиту
- значення ключа compteur у сесії
- значення ключа info1 у запиті
Його код такий:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:text name="Context.titre"/></title>
<s:head/>
</head>
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="Context.message"/></h2>
<h3><s:text name="Context.parameters"/></h3>
<s:iterator value="#parameters['nom']" var="nom">
nom : <s:property value="nom"/><br/>
</s:iterator>
<s:iterator value="#parameters['prenom']" var="prenom">
prenom : <s:property value="prenom"/><br/>
</s:iterator>
<s:iterator value="#parameters['age']" var="age">
âge : <s:property value="age"/><br/>
</s:iterator>
<h3><s:text name="Context.session"/></h3>
compteur : <s:property value="#session['compteur']"/>
<h3><s:text name="Context.request"/></h3>
info1 : <s:property value="#request['info1']"/>
</body>
</html>
- рядки 12–14: відображають усі значення, пов’язані з параметром nom
- рядки 15–17: відображають усі значення, пов’язані з параметром prenom
- рядки 18–20: відображають усі значення, пов’язані з параметром age
- рядок 22: відображає значення, пов’язане з ключем compteur у сесії
- рядок 24: відображає значення, пов’язане з ключем info1 у запиті
16.6. Тестування
![]() |
- у [1] запит Action1 подано без параметрів
- у [2], [Context.JSP] не знайдено параметрів
- у [3], [Context.JSP] знайдено ключ compteur у сесії
- у [4], [Context.JSP] знайшов ключ info1 у запиті
Давайте проведемо ще один тест:
![]() |
- в [1], Action1 запитується з параметрами
- у [2], [Context.JSP] відображає ці параметри
- у [3], [Context.JSP] знайшов ключ compteur у сесії. Лічильник дійсно збільшився на 1, що свідчить про те, що між двома запитами дійсно відбулося збереження даних.
- у [4], [Context.JSP] знайшов ключ info1 у запиті
Нагадаємо, що метод [Action1.execute] виводив інформацію на консоль веб-сервера. Ось приклад:
16.7. Conclusion
Слід пам’ятати про наступне:
- щоб зберегти інформацію, яка має бути спільною для всіх запитів усіх користувачів, ми будемо використовувати пам'ять додатка. Незабаром ми наведемо приклад цього.
- для збереження інформації, яка має бути спільною для всіх запитів одного й того самого користувача, ми використовуватимемо сесію цього користувача.
- для збереження інформації, яка має бути спільною для всіх елементів, що обробляють запит, використовується пам’ять запиту.




