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;
  
  // методи getter та setter

  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 (Object-Graph Navigation Language) у формі %{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:

  • інтернаціоналізація сторінок
  • введення параметрів, надісланих у полях дій
  • поняття сесії
  • взаємодія між діями та поданнями

Опанувавши ці поняття, ми тепер можемо перейти до більш складних прикладів. Почнемо з огляду різних тегів, які можна використовувати у формі.