8. المثال 06 – الجلسة
8.1. مفهوم الجلسة
عندما يتصل متصفح العميل بتطبيق ويب لأول مرة، يتلقى رمز جلسة، وهو سلسلة فريدة من الأحرف يرسلها مع كل طلب جديد يوجهه إلى تطبيق الويب. وهذا يسمح لتطبيق الويب بالتعرف على متصفح العميل. يمكن لتطبيق الويب بعد ذلك ربط البيانات برمز الجلسة هذا. تنتمي هذه البيانات إلى متصفح عميل واحد. وبالتالي، مع قيام متصفح العميل بتوجيه الطلبات، يتم تكوين ذاكرة.
![]() |
كما هو موضح أعلاه، لكل مستخدم (متصفح) ذاكرته الخاصة، والتي تُعرف باسم جلسته. يتم مشاركة هذه الذاكرة بين جميع الطلبات الواردة من نفس المستخدم. هناك أيضًا ذاكرة أعلى مستوى تُسمى ذاكرة التطبيق. يتم مشاركة هذه الذاكرة بين جميع الطلبات الواردة من جميع المستخدمين. وهي عادةً ما تكون للقراءة فقط.
8.2. مشروع NetBeans
![]() |
تم إنشاء مشروع [example-06] عن طريق نسخ مشروع [example-05]. سنقوم بتغيير بعض العناصر
- للاستفادة من جلسة عمل المستخدم.
- أضف إجراءً جديدًا [Clear] [1] لمسح حقل الإدخال.
8.3. التكوين
يتغير ملف [struts.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>
<!-- internationalization -->
<constant name="struts.custom.i18n.resources" value="messages" />
<!-- default package -->
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index" />
<action name="index">
<result type="redirectAction">
<param name="actionName">Saisir</param>
<param name="namespace">/actions</param>
</result>
</action>
</package>
<!-- equity package -->
<package name="actions" namespace="/actions" extends="struts-default">
<action name="Saisir">
<result name="success">/vues/Saisie.jsp</result>
</action>
<action name="Confirmer" class="actions.Confirmer">
<result name="success">/vues/Confirmation.jsp</result>
</action>
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.jsp</result>
</action>
</package>
</struts>
تحدد الأسطر 27–29 إجراءً جديدًا [Delete] مرتبطًا بفئة [Delete]. والاستجابة لهذا الإجراء هي طريقة العرض [Input.jsp].
8.4. الإجراء [Confirm]
تتطور على النحو التالي:
package actions;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class Confirmer extends ActionSupport implements SessionAware{
// model
private String nom;
// session
private Map<String, Object> session;
// getters and setters
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
@Override
public void setSession(Map<String, Object> session) {
this.session=session;
}
@Override
public String execute(){
// put the name in the session
session.put("nom",nom);
// navigation
return SUCCESS;
}
}
- السطر 7: تُنفذ فئة [Confirm] واجهة SessionAware. تحتوي هذه الواجهة على طريقة واحدة فقط، وهي طريقة setSession في الأسطر 25–27. قبل استدعاء طريقة execute، سيقوم أحد معترضات الطلبات، عبر طريقة setSession، بإدخال جلسة عمل المستخدم في شكل قاموس Map<String, Object> (السطر 25). نختار تخزين هذا القاموس في حقل session في السطر 12.
- الأسطر 30–34: طريقة `execute` الخاصة بالإجراء. عند تنفيذها، يكون حقل session قد تم تهيئته بواسطة أحد المعترضات، وحقل name بواسطة معترض آخر. نستخدم قاموس الجلسة هذا لتخزين حقل name. وبالتالي، سيكون الاسم جزءًا من جلسة المستخدم ومتاحًا لجميع طلباته.
8.5. طرق العرض [Confirmation.jsp] و [Saisie.jsp]
تظل طريقة العرض [Confirmation.jsp] دون تغيير. تتغير طريقة العرض [Saisie.jsp] على النحو التالي:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><s:text name="saisie.titre1"/></title>
</head>
<body>
<h1><s:text name="saisie.titre2"/></h1>
<s:form action="Confirmer">
<s:textfield key="saisie.libelle" name="nom" value="%{#attr['nom']}"/>
<s:submit key="saisie.valider" action="Confirmer"/>
<s:submit key="saisie.effacer" action="Effacer"/>
</s:form>
</body>
</html>
- السطر 12: نضيف سمة `value` إلى العلامة `<s:textfield>`. تحدد هذه السمة القيمة التي سيتم عرضها في حقل الإدخال. إذا تم حذف هذه السمة، فإن `value` تكون `name` بشكل افتراضي. هنا، قيمة السمة هي تعبير OGNL (لغة التنقل بين الكائنات والرسوم البيانية) بالشكل `%{expression_to_evaluate}`. هنا، التعبير المراد تقييمه هو #attr['name']. سيتم البحث عن السمة name في الإجراء الحالي، والصفحة، والطلب، والجلسة، والتطبيق، بهذا الترتيب. نظرًا لأن الإجراء [Confirm] يضع السمة name في الجلسة، فسيتم العثور عليها هناك. يوضح ذلك الطلب التالي:
![]() |
في [1]، كان الاسم الذي تم إدخاله هو ST. ونعلم أن الإجراء [Confirm] وضع هذا الاسم في الجلسة. ينقلنا الرابط [2] إلى عنوان URL [3]. يتم عرض طريقة العرض [Saisie.jsp]. بالنسبة لحقل الإدخال، تسترد السمة %{#attr['name']} الاسم من الجلسة.
- السطر 14: زر [Clear]، الذي يؤدي إلى تنفيذ الإجراء [Clear] وعرض طريقة العرض [Saisie.jsp]
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.jsp</result>
</action>
8.6. إجراء [حذف]
فيما يلي كود الإجراء [حذف]:
package actions;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class Effacer extends ActionSupport implements SessionAware{
// session
private Map<String, Object> session;
@Override
public String execute(){
// retrieve the name from the session
String nom=(String)session.get("nom");
// remove it from the session if necessary
if(nom!=null){
session.remove("nom");
}
// navigation
return SUCCESS;
}
@Override
public void setSession(Map<String, Object> map) {
this.session=map;
}
}
- السطر 7: تنفذ فئة [Delete] واجهة [SessionAware]، تمامًا كما فعلت الإجراء [Confirm].
- السطر 13: يجب أن تقوم الإجراء [Delete] بمسح محتويات حقل إدخال الاسم في طريقة العرض [Input.jsp]. ونحن نعلم أن طريقة العرض هذه تسترد هذا الاسم من الجلسة. لذلك يجب علينا إزالة الاسم من الجلسة. وهذا ما تقوم به طريقة execute.
لنرى كيف يعمل هذا:
![]() |
في [1]، نريد مسح حقل الإدخال. نضغط على زر [مسح].
<s:submit key="saisie.effacer" action="Effacer"/>
سيتم تنفيذ الإجراء [Clear]. في [2]، نلاحظ أن عنوان URL الذي تم استدعاؤه هو عنوان الإجراء [Confirm]. وهذا يأتي من العلامة <s:form> في النموذج:
<s:form action="Confirmer">
مما يؤدي إلى إرسال النموذج إلى الإجراء [Confirm]. وعند النقر على زر [Clear]، يتم تعيين المعلمة
action:Delete=Delete
إلى عنوان URL [/actions/Confirm.action]. يستخدم Struts هذه المعلمة لمعالجة البيانات التي تم إرسالها بواسطة الإجراء [حذف]. يزيل هذا الإجراء اسم الجلسة. صفحة [Input.jsp] هي الاستجابة للإجراء [حذف]:
<action name="Effacer" class="actions.Effacer">
<result name="success">/vues/Saisie.jsp</result>
</action>
هذه، التي تعرض اسم الجلسة، ثم تعرض سلسلة فارغة [3].
لقد كتبنا عدة أمثلة بسيطة لتقديم المفاهيم المهمة في Struts 2:
- تدويل الصفحة
- إدخال المعلمات المرسلة في حقول الإجراءات
- مفهوم الجلسات
- العلاقة بين الإجراءات (Actions) وطرق العرض (Views)
الآن بعد أن أتقنا هذه المفاهيم، أصبحنا جاهزين للتعامل مع أمثلة أكثر تعقيدًا. سنبدأ بتقديم العلامات المختلفة التي يمكن استخدامها في النموذج.



