Skip to content

16. مثال ۱۳ – زمینه یک اکشن

این برنامه کاربردی با هدف نشان دادن دسترسی یک اکشن به موارد زیر است:

  • پارامترهای درخواست
  • به ویژگی‌های درخواست
  • ویژگی‌های جلسه کاربر
 

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>
  • خط ۸: درخواست URL [/example/Action1] باعث ایجاد نمونه از کلاس [example.Action] خواهد شد. از آنجا که هیچ متدی مشخص نشده است، متد execute اجرا خواهد شد.
  • خط ۹: تنها یک کلید پذیرفته می‌شود. کلید 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;
  }
}
  • خط ۱۰: کلاس رابط‌های زیر را پیاده‌سازی می‌کند
    • SessionAware: برای دسترسی به فرهنگ لغت ویژگی جلسه (خط 16). این رابط تنها یک متد دارد، متد موجود در خط 46.
    • RequestAware: برای دسترسی به فرهنگ لغت ویژگی‌های درخواست (خط 17). این رابط تنها یک متد دارد، متد موجود در خط 51.
    • ParameterAware: برای دسترسی به فرهنگ لغت پارامترهای پرس‌وجو (خط ۱۸). توجه داشته باشید که هر کلید (نام پارامتر) با یک آرایه از مقادیر مطابقت دارد. این امر برای پشتیبانی از فیلدهای ورودی که مقادیر متعددی را ارسال می‌کنند، مانند لیست چندگزینه‌ای، ضروری است. رابط ParameterAware تنها یک متد دارد، که در خط 56 قرار دارد.
  • خط ۲۱: متد execute که هنگام درخواست اقدام [Action1] اجرا می‌شود. تا زمانی که این متد اجرا شود، interceptors کار خود را به پایان رسانده‌اند:
    • متد setParameters (خط ۵۶) فراخوانی شده است و دیکشنری «پارامترها» در خط ۱۸ حاوی تمام پارامترهای درخواست است.
    • متد setSession (خط ۴۶) فراخوانی شده و دیکشنری `session` در خط ۱۶ حاوی تمام ویژگی‌های جلسه است.
    • متد setRequest (خط ۵۱) فراخوانی شده است و دیکشنری `request` در خط ۱۷ شامل تمام ویژگی‌های درخواست است.
  • خطوط ۳۱–۳۸: مقدار مرتبط با کلید compteur در جلسه نوشته می‌شود
  • خطوط ۳۲–۳۴: کلید compteur در جلسه جستجو می‌شود. اگر پیدا نشود، با مقدار عددی ۰ به جلسه اضافه می‌شود.
  • خطوط ۳۵–۳۷: کلید compteur در جلسه جستجو می‌شود؛ مقدار آن افزایش می‌یابد و سپس کلید مجدداً در جلسه ذخیره می‌شود.
  • خط ۳۸: مقدار مرتبط با کلید compteur نمایش داده می‌شود. از آنجا که مقدار با هر فراخوانی اکشن [Action1] افزایش می‌یابد، مقدار شمارنده باید در هر فراخوانی بعدی افزایش یابد.
  • خط ۴۰: یک ویژگی با کلید 'info1' و مقدار 'information1' در دیکشنری ویژگی‌های درخواست درج می‌شود. ویژگی‌های یک درخواست با پارامترهای آن متفاوت هستند. پارامترها توسط کلاینت وب‌اپلیکیشن ارسال می‌شوند. از سوی دیگر، ویژگی‌های درخواست ارتباط بین اجزای مختلف برنامه وب که آن را پردازش می‌کنند را ممکن می‌سازند. بنابراین، پس از اجرای [Action1]، نما [Context.JSP] نمایش داده خواهد شد. خواهیم دید که این نما قادر به بازیابی ویژگی‌های درخواست است.
  • خط ۴۲: متد 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>
  • خطوط ۱۲–۱۴: نمایش تمام مقادیر مرتبط با پارامتر nom
  • خطوط ۱۵–۱۷: نمایش تمام مقادیر مرتبط با پارامتر prenom
  • خطوط ۱۸–۲۰: نمایش تمام مقادیر مرتبط با پارامتر age
  • خط ۲۲: مقدار مرتبط با کلید 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 را در جلسه یافت. شمارنده واقعاً یک واحد افزایش یافته است، که نشان می‌دهد داده‌ها واقعاً بین دو درخواست ذخیره شده بودند.
  • در [4]، [Context.JSP] کلید info1 را در درخواست یافت

همان‌طور که به یاد داریم، متد [Action1.execute] به کنسول وب‌سرور نوشت. در اینجا یک مثال آورده شده است:

1
2
3
4
5
6
7
Paramètres...
[prenom,y]
[prenom,y2]
[age,z]
[nom,x]
Session...
compteur=2

16.7. Conclusion

نکات زیر را در نظر داشته باشید:

  • برای ذخیره اطلاعاتی که باید در تمام درخواست‌های همه کاربران به اشتراک گذاشته شود، از حافظهٔ برنامه استفاده خواهیم کرد. به زودی مثالی از این موضوع را نشان خواهیم داد.
  • برای ذخیره‌سازی اطلاعاتی که باید بین تمام درخواست‌های یک کاربر مشترک باشد، از جلسه (session) آن کاربر استفاده خواهیم کرد.
  • برای ذخیره اطلاعاتی که باید توسط همه مؤلفه‌های پردازش‌کننده یک درخواست به اشتراک گذاشته شود، از دامنه درخواست استفاده خواهیم کرد.