Skip to content

17. Приклад 15 — Інтеграція Struts 2 / Spring

У попередньому прикладі у нас не було даних з областю дії Application, спільних для всіх запитів усіх користувачів. Тут ми наведемо такий приклад. Для його реалізації ми використовуємо фреймворк Spring [http://www.springsource.org/]. Spring — це надзвичайно цінний інструмент. У цьому прикладі ми показуємо лише незначну його частину. У наступному прикладі ми використаємо його більш інтенсивно.

Мета цього додатка — відобразити дані діапазону Application.

17.1. Проєкт NetBeans

Проект NetBeans для цього додатка має таку назву:

  • у [1]:
    • [web.xml], який налаштовує веб-додаток, зазнає змін порівняно з попередніми версіями
    • [applicationContext.xml] — це файл конфігурації Spring
  • на [2]: представлення [Context.JSP], яке відображатиме дані з області Application
  • у [3]:
    • файл повідомлень [messages.properties]
    • головний файл конфігурації Struts [struts.xml]. Буде змінюватися порівняно з попередніми додатками.
  • у [4]:
    • дія Struts [Action1.java]
    • клас [Config.java], який зберігатиме дані в області дії додатка
    • додатковий файл конфігурації Struts [example.xml]
  • у [5]: бібліотека Struts 2
  • у [6]:
    • архіви, необхідні для Spring — [spring-core, spring-context, spring-beans, spring-web, commons-logging]
    • архів плагіна Spring для Struts 2. Дозволяє інтегрувати Spring із Struts 2 [struts2-spring-plugin]

Щодо попередніх версій:

  • необхідно додати архіви до проєкту
  • відредагувати файли [web.xml] та [struts.xml]

17.2. Configuration

17.2.1. Файл [web.xml]

Файл [web.xml] змінюється наступним чином:


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>Exemple 14</display-name>
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <URL-pattern>/*</URL-pattern>
  </filter-mapping>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

Зміна відбувається у рядках 12–14. До веб-додатку додається файл listener. Під час запуску веб-додатку буде створено екземпляр класу, що реалізує цей файл listener. Це клас Spring. Цей клас використовуватиме файл [WEB-INF/applicationContext.xml]. Він має такий вигляд:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
  
  <!-- конфігурація бінів на рівні додатка -->
  <bean id="config" class="example.Config" >
    <property name="nbMaxUsers" value="10"/>
  </bean>

</beans>
  • конфігураційний файл Spring має кореневий тег <beans> (рядки 2 та 11). beans можна перекласти як «об’єкти». Spring створить екземпляри всіх об’єктів (bean), знайдених у цьому файлі конфігурації. Це відбувається лише один раз, під час запуску Spring при запуску веб-додатку.
  • рядки 7–9: визначають бін із назвою config (id). Бін config пов’язаний із класом (class) [example.Config]. Spring створить екземпляр цього класу.
  • рядок 8: визначає властивість класу [example.Config]. Spring викличе метод [example.Config].setNbMaxUsers(10). Отже, метод setNbMaxUsers повинен існувати в класі. Він має такий вигляд:

package example;

public class Config {

  private int nbMaxUsers;

  public int getNbMaxUsers() {
    return nbMaxUsers;
  }

  public void setNbMaxUsers(int nbMaxUsers) {
    this.nbMaxUsers = nbMaxUsers;
  }
  
}

Цей клас визначає лише одне поле nbMaxUsers разом із його get та set. Якщо ви правильно зрозуміли викладене, під час запуску веб-додатку створюється екземпляр класу [Config] із значенням 10 для його поля nbMaxUsers. Ми визначили лише одне поле, але цього достатньо для нашої демонстрації. Ми хочемо показати, що це поле, яке може представляти максимальну кількість користувачів, є даними області дії Application, доступними для всіх дій. Саме це ми продемонструємо за допомогою дії [Action1].

17.2.2. Файл [struts.xml]

Основний файл конфігурації Struts має такий вигляд:


<?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" />
  <!-- інтеграція Spring -->
  <constant name="struts.objectFactory.spring.autoWire" value="name" />

  <include file="example/example.xml"/>

  <package name="default" namespace="/" extends="struts-default">
    <default-action-ref name="index" />
    <action name="index">
      <result type="redirectAction">
        <param name="actionName">Action1</param>
        <param name="namespace">/example</param>
      </result>
    </action>
  </package>

</struts>

Лише рядок 10 відрізняється від попередніх версій цього файлу. Він визначає константу Struts. Об’єкти, інстанційовані Spring, можуть бути введені в інші об’єкти. Це є основою роботи Spring. У даному випадку посилання на об’єкт типу [Config], створений Spring, може бути введено в об’єкти Struts. Саме тут задіюється плагін Spring для Struts 2, який забезпечує інтеграцію Spring у Struts.

У рядку 10 вказано, що ін’єкція об’єктів Spring в об’єкт Struts відбуватиметься автоматично (autowire) за іменем (value). Повернемося до файлу конфігурації [applicationContext.xml]:


<!-- конфігурація бінів на рівні додатка -->
  <bean id="config" class="example.Config" >
    <property name="nbMaxUsers" value="10"/>
  </bean>

Те, що Struts 2 називає іменем біна, насправді тут є id. Отже, тут інстанційований бін типу [Config] має ім’я config.

Акція [Action1.java] виглядає так:


package example;

import com.opensymphony.xwork2.ActionSupport;
...
public class Action1 extends ActionSupport implements SessionAware, RequestAware, ParameterAware {

  // конструктор без параметрів
  public Action1() {
  }
  
  // Сесія, запит, параметри
  private Map<String, Object> session;
  private Map<String, Object> request;
  private Map<String, String[]> parameters;
  private Config config;

  @Override
  public String execute() {
  ....
    // запит
    request.put("nbMaxUsers", config.getNbMaxUsers());

    // відображення сторінки JSP
    return SUCCESS;
  }
...
  public Config getConfig() {
    return config;
  }

  public void setConfig(Config config) {
    this.config = config;
  }
}

Дія [Action1] ідентична тій, що була в попередньому додатку, за винятком таких деталей:

  • рядок 15: додано поле config. Оскільки воно має ім’я біна, інстанційованого Spring, це поле автоматично отримає посилання на цей об’єкт. Таким чином, дія має доступ до конфігурації додатка або, загалом, до даних області дії Application.
  • рядок 31: Spring створить екземпляр поля config за допомогою свого методу set. Тому цей метод має бути присутнім.
  • рядок 21: дія отримує доступ до інформації з області дії Application. У запит вказується максимальна кількість користувачів nbMaxUsers, щоб представлення [Context.JSP] могло її відобразити.

17.2.3. Файл [example.xml]

Додатковий файл конфігурації Struts ідентичний файлу попередньої версії:


<?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>

17.3. Вигляд [Context.JSP]

Вигляд [Context.JSP] має такий вигляд:


<%@ 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>
    nom : <s:property value="#parameters['nom']"/><br/>
    age : <s:property value="#parameters['age']"/>
    <h3><s:text name="Context.session"/></h3>
    compteur : <s:property value="#session['compteur']"/>
    <h3><s:text name="Context.request"/></h3>
    nbMaxUsers : <s:property value="#request['nbMaxUsers']"/>
  </body>
</html>

17.4. Тестування

Приклад виконання виглядає так: