Skip to content

8. مثال ۰۶ – جلسه

8.1. مفهوم جلسه

وقتی یک مرورگر کلاینت برای اولین بار به یک برنامه وب متصل می‌شود، یک توکن جلسه – یک رشته منحصربه‌فرد از کاراکترها – دریافت می‌کند که آن را با هر درخواست جدیدی که به برنامه وب ارسال می‌کند، بازمی‌فرستد. این امر به برنامه وب امکان می‌دهد تا مرورگر کلاینت را شناسایی کند. سپس برنامه وب می‌تواند داده‌ها را با این توکن جلسه مرتبط سازد. این داده‌ها متعلق به یک مرورگر کلاینت واحد هستند. بدین ترتیب، با هر درخواست بعدی مرورگر مشتری، یک سابقه شکل می‌گیرد.

همانطور که در بالا نشان داده شده است، هر کاربر (مرورگر) دارای حافظه خود است که به آن «سشن» (session) گفته می‌شود. این حافظه در تمام درخواست‌های یک کاربر یکسان مشترک است. همچنین یک حافظه سطح بالاتر وجود دارد که به آن «حافظه برنامه» (application memory) گفته می‌شود. این حافظه در تمام درخواست‌های تمام کاربران مشترک است. این حافظه عموماً فقط-خواندنی (read-only) است.

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>

خطوط ۲۷–۲۹ یک اقدام جدید، [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;
  }
  
}
  • خط ۷: کلاس [Confirmer] رابط SessionAware را پیاده‌سازی می‌کند. این رابط تنها یک متد دارد، متد setSession در خطوط ۲۵–۲۷. قبل از فراخوانی متد execute، یکی از interceptorهای درخواست از طریق متد setSession جلسهٔ کاربر را در قالب یک دیکشنری Map<String, Object> تزریق می‌کند (خط 25). ما انتخاب می‌کنیم که این دیکشنری را در فیلد session در خط ۱۲ ذخیره کنیم.
  • خطوط ۳۰–۳۴: متد execute اکشن. وقتی این متد اجرا می‌شود، فیلد session توسط یکی از interceptors مقداردهی اولیه شده و فیلد nom توسط interceptor دیگری مقداردهی شده است. این دیکشنری 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>
  • خط ۱۲: ما یک ویژگی value به تگ <s:textfield>. اضافه می‌کنیم. این ویژگی مقدار نمایش داده شده در فیلد ورودی را تعیین می‌کند. در صورت عدم وجود این ویژگی، value = name است. در اینجا مقدار ویژگی یک عبارت OGNL (زبان ناوبری گراف-شیء) به شکل %{expression_à_évaluer}. در اینجا، عبارت قابل ارزیابی #attr['nom'] است. ویژگی nom در عمل، صفحه، درخواست، جلسه و برنامه جاری، به ترتیب، جستجو خواهد شد. از آنجا که اقدام [Confirmer] ویژگی nom را در جلسه (session) تنظیم می‌کند، این ویژگی در آنجا یافت خواهد شد. این موضوع با پرس‌وجوی زیر نشان داده شده است:

در [1]، نام وارد شده ST بود. ما می‌دانیم که اکشن [Confirmer] این نام را در جلسه قرار داده است. لینک [2] ما را به URL و [3] هدایت می‌کند. نما [Saisie.JSP] نمایش داده می‌شود. برای فیلد ورودی، از ویژگی %{#attr['nom']} برای بازیابی نام از جلسه استفاده می‌شود.

  • خط ۱۴: دکمه [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;
  }
}
  • خط ۷: کلاس [Effacer] رابط [SessionAware] را پیاده‌سازی می‌کند، درست همان‌طور که اقدام [Confirmer] این کار را انجام داد.
  • خط ۱۳: اکشن [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:Delete=Delete

به اکشن URL [/actions/Confirmer.action] ارسال شد. Struts از این پارامتر برای پردازش داده‌های ارسال‌شده توسط اکشن [Effacer] استفاده می‌کند. این اکشن نام session را حذف می‌کند. صفحه [Saisie.JSP] پاسخ اقدامی است که در [Effacer] انجام می‌شود:


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

این اکشن، که نام جلسه را نمایش می‌دهد، سپس یک رشته خالی را بازمی‌گرداند: [3].

ما چندین مثال ساده نوشته‌ایم تا مفاهیم کلیدی Struts 2 را معرفی کنیم:

  • بین‌المللی‌سازی صفحات
  • تزریق پارامترهای ارسال‌شده به فیلدهای اکشن
  • مفهوم جلسات
  • رابطه بین اکشن‌ها و ویوها

پس از درک این مفاهیم، اکنون آماده‌ایم تا به سراغ مثال‌های پیچیده‌تر برویم. ابتدا به بررسی تگ‌های مختلفی می‌پردازیم که می‌توان در یک فرم از آن‌ها استفاده کرد.