Skip to content

8. Створення плагіна

Можна створювати додатки, які називаються плагінами, що завантажуються під час запуску додатка Struts і вивантажуються під час його завершення. Зазвичай це дозволяє виконувати ініціалізацію під час запуску додатка та звільнення ресурсів під час його завершення. Ці операції також можна виконати шляхом успадкування класу ActionServlet від контролера, і саме це було зроблено в попередньому додатку. Плагін є альтернативою цьому рішенню. Плагін може бути додатком, більш складним, ніж проста ініціалізація середовища. Ми розглядали приклад цього в уроці, де були представлені поняття декларативних правил валідації. Плагін оголошується у файлі конфігурації Struts. Так, плагін ValidatorPlugIn був оголошений у файлі struts-config.xml додатка, який його використовував:

    <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
        <set-property 
        property="pathnames" 
      value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"
    />
    </plug-in>

Тепер ми опишемо додаток Struts, що використовує плагін.

8.1. Налаштування додатка Struts /plugin1

Ми пропонуємо створити додаток Struts /plugin1, налаштований таким чином:

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    <servlet>
      <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
        <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <taglib>
      <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
  </taglib>
  <taglib>
      <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
  </taglib>

</web-app>

Ми не будемо зупинятися на цьому файлі, оскільки він є стандартним.

struts-config.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>

    <plug-in className="istia.st.struts.plugins.MyPlugin">
        <set-property property="passwdFileName" value="data/passwd"/>
        <set-property property="groupFileName" value="data/group"/>        
    </plug-in>

</struts-config>

Ми додали лише один розділ — розділ для плагіна. Атрибути тегу <plug-in>, що використовуються тут, такі:

className
назва класу плагіна
<set-property>
дозволяє ініціалізувати плагін за допомогою пар (ключ, значення)

Мета цього додатка — продемонструвати, як плагін може отримувати свої параметри ініціалізації та надавати їх іншим об’єктам, що використовують той самий контекст додатка. Ми використаємо простий вигляд JSP для відображення значень ініціалізації плагіна, що пояснює відсутність будь-яких дій у файлі конфігурації.

8.2. Клас Java плагіна

Клас Java, який використовується як плагін для додатка Struts, повинен реалізувати інтерфейс org.apache.struts.action.PlugIn. Ця реалізація полягає у написанні двох методів:

  • public void init(ActionServlet servlet, ModuleConfig conf)
  • public void destroy()

Під час завантаження додатка Struts його контролер створить екземпляри всіх плагінів, оголошених у файлі struts-config.xml. Потім він виконає метод init для кожного з них. Саме в цьому методі плагін виконує свої ініціалізації. Тут ми обмежимося тим, що зчитаємо параметри ініціалізації плагіна та помістимо їх у контекст додатка, щоб вони були доступні для всіх інших об’єктів додатка. Коли додаток буде вивантажено, контролер виконає метод destroy для кожного із завантажених плагінів. Це момент, коли слід звільнити ресурси, що стали непотрібними. Тут нам нічого робити не доведеться.

Код класу виглядає так:

package istia.st.struts.plugins;

import javax.servlet.ServletException;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.config.PlugInConfig;

public class MyPlugin implements PlugIn {

    // метод, що викликається під час видалення контексту додатка
    public void destroy() {
    }

     // метод, що викликається під час початкового створення контексту додатка
    public void init(ActionServlet servlet, ModuleConfig conf)
        throws ServletException {
         // ім'я класу цього об'єкта
        String className=this.getClass().getName();
        // список плагінів
        PlugInConfig[] pluginConfigs = conf.findPlugInConfigs();
         // пошук серед плагінів того,
         // який має назву цього класу
        boolean trouvé=false;
        for (int i = 0; ! trouvé && i < pluginConfigs.length; i++) {
            // назва плагіна
            String pluginClassName=pluginConfigs[i].getClassName();
             // якщо це не той плагін, продовжуємо пошук
            if(! pluginClassName.equals(className)) continue;
            // це той самий — запам'ятовуємо його властивості в контексті
            servlet.getServletContext().setAttribute("initialisations",pluginConfigs[i].getProperties());
            trouvé=true;
        }//for i
    } //init
} //клас

Зверніть увагу на наступні моменти:

  • метод init приймає параметр, який тут називається conf, типу ModuleConfig, що надає доступ до вмісту файлу struts-config.xml.
  • метод [ModuleConfig].findPlugInConfigs() дозволяє отримати всі розділи <plug-in> з конфігураційного файлу Struts у вигляді масиву об’єктів типу PlugInConfig.
  • Клас PluginConfig представляє розділ <plug-in> файлу конфігурації. Метод [PlugInConfig].getProperties дозволяє отримати доступ до елементів <set-property> секції у вигляді словника java.util.Map.
  • Словник властивостей плагіна розміщується в контексті додатка.
  • Оскільки плагінів може бути кілька, нам потрібно знайти той, що нас цікавить. Це той, який має таку саму назву, як і клас, що виконується.

Тут ми вирішили розмістити весь словник у контексті. Ми могли б скористатися саме ним. Наступний фрагмент коду ілюструє один із способів реалізації:

            Map initialisations = pluginConfigs[i].getProperties();
             // проходимо по елементах словника
            Iterator entrées = initialisations.entrySet().iterator();
            while (entrées.hasNext()) {
                 // отримати поточний елемент (ключ, значення)
                Map.Entry entrée = (Map.Entry) entrées.next();
                String clé = (String) entrée.getKey();
                String valeur = (String) entrée.getValue();
                // обробити (ключ, значення)
                //...
            }

8.3. Код подання infos.jsp

Вигляд infos.jsp призначений для відображення вмісту словника властивостей плагіна, який було додано до контексту додатка. Оскільки вигляд infos.jsp є частиною цього контексту, він має до нього доступ. Його код такий:

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<html>
    <head>
        <title>Plugin</title>
    </head>
    <body>
        <h3>Infos du plugin<br></h3>
        <table border="1">
            <tr>
                <th>Clé</th><th>Valeur</th>
            </tr>            
            <logic:iterate id="element" name="initialisations">
                <tr>
                    <td><bean:write name="element" property="key"/></td>
                    <td><bean:write name="element" property="value"/></td>
                </tr>
            </logic:iterate>
        </table>
    </body>
</html>

Важливі зауваження:

  • ми використовуємо бібліотеки тегів struts-logic та struts-bean
  • тег <logic:iterate> дозволяє нам відобразити словник initialisations, який був доданий до контексту методом init плагіна. Атрибут name вказує на об’єкт, по якому потрібно виконувати ітерацію. Це має бути щось на зразок колекції, ітератора тощо. Об’єкт шукається у всіх областях дії (page, request, session, context). У цьому випадку його буде знайдено в області контексту. Параметр id слугує для присвоєння імені поточному елементу колекції під час ітерацій. Тут, у тілі тегу <logic:iterate>, element представлятиме поточний елемент словника. Він представлений об’єктом java.util.Map.Entry, який, грубо кажучи, є парою (ключ, значення) словника.
  • У тілі тегу <logic:iterate> ми виводимо (<bean:write>) вміст поточного елемента element. Він розглядається як об’єкт із двома властивостями (property): ключем key та значенням value. Ці дві властивості виводяться на екран.

8.4. Розгортання

Контекст додатка визначається у файлі конфігурації server.xml Tomcat:

<Context path="/plugin11" reloadable="true" docBase="E:\data\serge\web\struts\plugins\1" />

Структура додатка виглядає наступним чином:

 
 

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

Ми запускаємо Tomcat і надсилаємо запит на URL http://localhost:8080/plugin1/infos.jsp:

Image

Ми бачимо, що представлення infos.jsp дійсно отримало доступ до інформації, збереженої в контексті додатка за допомогою плагіна.

8.6. Висновок

Ми продемонстрували, що можна ініціалізувати додаток Struts за допомогою плагіна. Це може бути альтернативним рішенням порівняно з похідним класом ActionServlet для виконання тієї самої задачі.