16. المثال 13 - سياق الإجراء
يهدف هذا التطبيق إلى توضيح أن الإجراء يمكنه الوصول إلى:
- معلمات الطلب
- سمات الطلب
- سمات جلسة عمل المستخدم

16.1. مشروع NetBeans
![]() |
مشروع NetBeans هو كما يلي:
- في [1]، العرض [Context.jsp]
- في [2]، الإجراء [Action1.java] وملف تكوين Struts [example.xml]
16.2. التكوين
يتم تعريف تكوين المشروع في [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]. يتمتع هذان المكونان بإمكانية الوصول إلى أنواع مختلفة من البيانات:
- بيانات نطاق التطبيق [3]، أي البيانات التي يمكن الوصول إليها من قبل جميع الطلبات من جميع المستخدمين. وهي غالبًا ما تكون للقراءة فقط. غالبًا ما تحتوي هذه البيانات على التكوين الأولي للتطبيق. هنا، يمكن لـ [Action1] و [Context.jsp] الوصول إلى هذه البيانات.
- بيانات نطاق الجلسة [4]، أي البيانات التي يمكن الوصول إليها من جميع الطلبات من نفس المستخدم. هذه البيانات قابلة للقراءة/الكتابة. هنا، سيستخدم [Action1] الجلسة في وضع القراءة/الكتابة، بينما سيستخدمها [Context.jsp] في وضع القراءة فقط.
- بيانات نطاق الطلب [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 {
// constructor without parameters
public Action1() {
}
// Session, Request, Parametres
Map<String, Object> session;
Map<String, Object> request;
Map<String, String[]> parameters;
@Override
public String execute() {
// parameter list
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));
}
}
// session
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
request.put("info1", "information1");
// display page JSP
return SUCCESS;
}
// session
public void setSession(Map<String, Object> session) {
this.session = session;
}
// request
public void setRequest(Map<String, Object> request) {
this.request = request;
}
// settings
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)، ويحتوي قاموس المعلمات في السطر 18 على جميع معلمات الطلب.
- تم استدعاء طريقة setSession (السطر 46)، ويحتوي قاموس الجلسة في السطر 16 على جميع سمات الجلسة.
- تم استدعاء طريقة setRequest (السطر 51)، ويحتوي قاموس الطلب في السطر 17 على جميع سمات الطلب.
- الأسطر 31–38: يتم كتابة القيمة المرتبطة بمفتاح `compteur` إلى الجلسة
- الأسطر 32-34: يتم البحث عن مفتاح `compteur` في الجلسة. إذا لم يتم العثور عليه، يتم إضافته بالقيمة الصحيحة 0.
- الأسطر 35-37: يتم البحث عن مفتاح `counter` في الجلسة، ويتم زيادة قيمته، ثم يتم إعادة المفتاح إلى الجلسة.
- السطر 38: يتم عرض القيمة المرتبطة بمفتاح counter. نظرًا لأن الزيادة تتم مع كل طلب على الإجراء [Action1]، يجب أن نرى زيادة قيمة العداد مع إجراء الطلبات.
- السطر 40: يتم إدراج سمة بالمفتاح `info1` والقيمة `information1` في قاموس سمات الطلب. تختلف سمات الطلب عن معلمات الطلب. يتم إرسال المعلمات بواسطة عميل تطبيق الويب. من ناحية أخرى، تتيح سمات الطلب الاتصال بين المكونات المختلفة لتطبيق الويب التي تعالج الطلب. وبالتالي، بعد تنفيذ [Action1]، سيتم عرض طريقة العرض [Context.jsp]. سنرى أنه قادر على استرداد سمات الطلب.
- السطر 42: تُرجع طريقة execute المفتاح "success".
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] مسؤول عن عرض:
- معلمات طلب معينة
- قيمة مفتاح العداد في الجلسة
- قيمة مفتاح 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: عرض جميع القيم المرتبطة بالمعلمة "name"
- الأسطر 15-17: عرض جميع القيم المرتبطة بالمعلمة 'first_name'
- الأسطر 18-20: عرض جميع القيم المرتبطة بالمعلمة age
- السطر 22: يعرض القيمة المرتبطة بمفتاح العداد في الجلسة
- السطر 24: يعرض القيمة المرتبطة بمفتاح info1 في الاستعلام
16.6. الاختبارات
![]() |
- في [1]، يتم استدعاء Action1 بدون معلمات
- في [2]، لم يعثر [Context.jsp] على أي معلمات
- في [3]، عثرت [Context.jsp] على مفتاح العداد في الجلسة
- في [4]، عثرت [Context.jsp] على المفتاح info1 في الطلب
دعونا نجري اختبارًا آخر:
![]() |
- في [1]، تم طلب Action1 مع المعلمات
- في [2]، يعرض ملف [Context.jsp] هذه المعلمات
- في [3]، عثرت [Context.jsp] على المفتاح "compteur" في الجلسة. وقد تمت زيادة العداد بالفعل بمقدار 1، مما يدل على أن البيانات تم الاحتفاظ بها بنجاح بين الطلبين.
- في [4]، عثرت [Context.jsp] على المفتاح "info1" في الطلب
تذكر أن طريقة [Action1.execute] كتبت إلى وحدة تحكم خادم الويب. وإليك مثال على ذلك:
16.7. الخلاصة
ضع النقاط التالية في اعتبارك:
- لتخزين المعلومات التي سيتم مشاركتها عبر جميع الطلبات من جميع المستخدمين، سنستخدم ذاكرة التطبيق. سنعرض مثالاً على ذلك بعد قليل.
- لتخزين المعلومات التي سيتم مشاركتها بين جميع الطلبات من نفس المستخدم، سنستخدم جلسة عمل ذلك المستخدم.
- لتخزين المعلومات التي سيتم مشاركتها بين جميع المكونات التي تعالج الطلب، سنستخدم نطاق الطلب.



