Skip to content

8. المثال 06 – الجلسة

8.1. مفهوم الجلسة

عندما يتصل متصفح العميل لأول مرة بتطبيق ويب، يتلقى رمز جلسة، وهو سلسلة أحرف فريدة يعيد إرسالها مع كل طلب جديد يوجهه إلى تطبيق الويب. وهذا يسمح للتطبيق بالتعرف على متصفح العميل. ويمكن للتطبيق عندئذ ربط البيانات برمز الجلسة هذا. وتخص هذه البيانات متصفح عميل واحد فقط. وهكذا، مع تراكم طلبات متصفح العميل، تتشكل ذاكرة.

في المثال أعلاه، يمتلك كل مستخدم (متصفح) ذاكرة خاصة به تُسمى «جلسة العمل». يتم مشاركة هذه الذاكرة بين جميع الطلبات الصادرة عن المستخدم نفسه. كما توجد ذاكرة أعلى مستوى تُسمى «ذاكرة التطبيق». يتم مشاركة هذه الذاكرة بين جميع الطلبات الصادرة عن جميع المستخدمين. وعادةً ما تكون هذه الذاكرة للقراءة فقط.

8.2. مشروع NetBeans

تم إنشاء المشروع [exemple-06] عن طريق نسخ المشروع [exemple-05]. سنقوم بتغيير بعض العناصر لكي

  • الاستفادة من جلسة عمل المستخدم.
  • إضافة إجراء جديد [Effacer] [1] لمسح حقل الإدخال.

8.3. Configuration

يتغير الملف [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>
  <!-- التدويل -->
  <constant name="struts.custom.i18n.resources" value="messages" />
  <!-- الحزمة الافتراضية -->
  <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>
  <!-- حزمة الإجراءات -->
  <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 إجراءً جديدًا [Effacer] مرتبطًا بفئة [Effacer]. والاستجابة لهذا الإجراء هي العرض [Saisie.jsp].

8.4. الإجراء [Confirmer]

تتطور على النحو التالي:


package actions;

import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;

public class Confirmer extends ActionSupport implements SessionAware{
  
  // القالب
  private String nom;
  // الجلسة
  private Map<String, Object> session;
  
  // أدوات الاسترجاع والتعيين

  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(){
    // يتم إدخال الاسم في الجلسة
    session.put("nom",nom);
    // التنقل
    return SUCCESS;
  }
  
}
  • السطر 7: الفئة [Confirmer] تُنفِّذ الواجهة SessionAware. تحتوي هذه الواجهة على طريقة واحدة فقط، وهي الطريقة setSession الموجودة في الأسطر 25-27. قبل استدعاء الطريقة execute، سيقوم أحد معترضات الطلب، عبر الطريقة setSession، بإدراج جلسة عمل المستخدم في شكل قاموس Map<String, Object> (السطر 25). نختار تخزين هذا القاموس في الحقل session في السطر 12.
  • الأسطر 30-34: الطريقة execute الخاصة بالإجراء. عند تنفيذها، تم تهيئة الحقل session بواسطة أحد المعترضات، وكذلك الحقل nom بواسطة معترض آخر. يُستخدم هذا القاموس session لتخزين الحقل nom فيه. وبذلك يصبح الاسم جزءًا من ذاكرة المستخدم ويكون متاحًا لجميع استعلاماته.

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_à_évaluer}. هنا، التعبير المطلوب تقييمه هو #attr['nom']. سيتم البحث عن السمة nom في الإجراء الحالي، ثم الصفحة، ثم الاستعلام، ثم الجلسة، ثم التطبيق، بهذا الترتيب. ونظرًا لأن الإجراء [Confirmer] يضع السمة nom في الجلسة، فسيتم العثور عليها هناك. وهذا ما يوضحه الاستعلام التالي:

في [1]، كان الاسم الذي تم إدخاله هو ST. نعلم أن الإجراء [Confirmer] قد أضاف هذا الاسم إلى الجلسة. الرابط [2] يقودنا إلى عنوان URL [3]. يتم عرض الصفحة [Saisie.jsp]. بالنسبة لحقل الإدخال، تسمح السمة %{#attr['nom']} باسترداد الاسم من الجلسة.

  • السطر 14: الزر [Effacer] الذي سيؤدي إلى تشغيل الإجراء [Effacer] وعرض العرض [Saisie.jsp]

<action name="Effacer" class="actions.Effacer">
      <result name="success">/vues/Saisie.jsp</result>
</action>

8.6. الإجراء [Effacer]

رمز الإجراء [Effacer] هو كما يلي:


package actions;

import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;

public class Effacer extends ActionSupport implements SessionAware{
  
  // الجلسة
  private Map<String, Object> session;
  
  @Override
  public String execute(){
    // يتم استرداد الاسم من الجلسة
    String nom=(String)session.get("nom");
    // نحذفه من الجلسة إذا لزم الأمر
    if(nom!=null){
      session.remove("nom");
    }
    // التنقل
    return SUCCESS;
  }

  @Override
  public void setSession(Map<String, Object> map) {
    this.session=map;
  }
}
  • السطر 7: الفئة [Effacer] تنفذ الواجهة [SessionAware] كما كانت تفعل الإجراء [Confirmer].
  • السطر 13: يجب أن تقوم الإجراء [Effacer] بمسح محتوى حقل إدخال الاسم في العرض [Saisie.jsp]. نعلم أن هذه العرضة ستسترد هذا الاسم من الجلسة. لذا يجب إزالة الاسم من الجلسة. وهذا ما تقوم به الطريقة execute.

لنرى النتيجة:

في [1]، نريد مسح حقل الإدخال. نضغط على الزر [Effacer].


<s:submit key="saisie.effacer" action="Effacer"/>

سيتم تنفيذ الإجراء [Effacer]. في [2]، نلاحظ أن عنوان URL الذي تم استدعاؤه هو عنوان الإجراء [Confirmer]. ويرجع ذلك إلى العلامة <s:form> في النموذج:


<s:form action="Confirmer">

التي تؤدي إلى إرسال النموذج إلى الإجراء [Confirmer]. عند النقر على الزر [Effacer]، يتم تعيين المعلمة

action:Effacer=Effacer

إلى عنوان URL [/actions/Confirmer.action]. يستخدم Struts هذا المعامل لمعالجة البيانات المرسلة بواسطة الإجراء [Effacer]. ويقوم هذا الإجراء بإزالة اسم الجلسة. الصفحة [Saisie.jsp] هي استجابة الإجراء [Effacer]:


<action name="Effacer" class="actions.Effacer">
      <result name="success">/vues/Saisie.jsp</result>
</action>

وهذه الصفحة، التي تعرض اسم الجلسة، تعرض سلسلة فارغة [3].

لقد كتبنا عدة أمثلة بسيطة لتقديم المفاهيم المهمة في Struts 2:

  • تدويل الصفحات
  • حقن المعلمات المرسلة في حقول الإجراءات
  • مفهوم الجلسة
  • الترابط بين الإجراءات (Actions) والعروض (Views)

وبعد استيعاب هذه المفاهيم، أصبح بإمكاننا الآن تناول أمثلة أكثر تعقيدًا. نبدأ بعرض العلامات المختلفة التي يمكن استخدامها في النموذج.