Skip to content

8. Erstellung eines Plugins

Es ist möglich, Anwendungen zu erstellen, die als Plugins bezeichnet werden und beim Start einer Struts-Anwendung geladen sowie beim Beenden der Anwendung entladen werden. Dies ermöglicht es in der Regel, beim Start der Anwendung Initialisierungen durchzuführen und beim Beenden der Anwendung Ressourcen freizugeben. Diese Vorgänge können auch durchgeführt werden, indem man die Klasse **ActionServlet vom Controller ableitet – genau das wurde in der vorherigen Anwendung getan. Das Plugin ist eine Alternative zu dieser Lösung. Das Plugin kann eine komplexere Anwendung sein als eine einfache Initialisierung der Umgebung. Ein Beispiel dafür haben wir in der Lektion gesehen, in der die Konzepte der deklarativen Validierungsregeln vorgestellt wurden. Ein Plugin wird in der Struts-Konfigurationsdatei deklariert. Das Plugin ValidatorPlugIn wurde somit in der Datei struts-config.xml** der Anwendung deklariert, die es verwendete:

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

Wir beschreiben nun eine Struts-Anwendung, die ein Plugin verwendet.

8.1. Konfiguration der Struts-Anwendung /plugin1

Wir beabsichtigen, die Struts-Anwendung /plugin1 mit folgender Konfiguration zu erstellen:

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>

Wir werden nicht näher auf diese Standarddatei eingehen.

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>

Wir haben nur einen Abschnitt eingefügt, nämlich den für das Plugin. Die hier verwendeten Attribute des <plug-in>-Tags lauten wie folgt:

className
Name der Plugin-Klasse
<set-property>
ermöglicht die Initialisierung des Plugins mit (Schlüssel, Wert)-Paaren

Das Ziel dieser Anwendung ist es, zu zeigen, wie das Plugin seine Initialisierungsparameter abrufen und sie anderen Objekten zur Verfügung stellen kann, die denselben Anwendungskontext teilen. Wir werden eine einfache Ansicht JSP verwenden, um die Initialisierungswerte des Plugins anzuzeigen, was erklärt, warum die Konfigurationsdatei keine Aktionen enthält.

8.2. Die Java-Klasse des Plugins

Eine Java-Klasse, die als Plugin für eine Struts-Anwendung dient, muss die Schnittstelle org.apache.struts.action.PlugIn implementieren. Diese Implementierung besteht darin, zwei Methoden zu schreiben:

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

Wenn die Struts-Anwendung geladen wird, instanziiert ihr Controller alle in der Datei struts-config.xml deklarierten Plugins. Anschließend führt er für jedes einzelne die Methode init aus. In dieser Methode führt das Plugin seine Initialisierungen durch. Hier beschränken wir uns darauf, die Initialisierungsparameter des Plugins auszulesen und diese in den Anwendungskontext zu übertragen, damit sie für alle anderen Objekte der Anwendung verfügbar sind. Wenn die Anwendung entladen wird, führt der Controller die Methode „destroy“ jedes der geladenen Plugins aus. Dies ist der Zeitpunkt, um nicht mehr benötigte Ressourcen freizugeben. Hier müssen wir nichts unternehmen.

Der Code der Klasse lautet wie folgt:

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 {

    // Methode, die beim Löschen des Anwendungskontexts aufgerufen wird
    public void destroy() {
    }

     // Methode, die bei der erstmaligen Erstellung des Anwendungskontexts aufgerufen wird
    public void init(ActionServlet servlet, ModuleConfig conf)
        throws ServletException {
         // Name der Klasse dieses Objekts
        String className=this.getClass().getName();
        // Liste der Plugins
        PlugInConfig[] pluginConfigs = conf.findPlugInConfigs();
         // Durchsuchen der Plugins, um dasjenige zu finden
         // das den Namen dieser Klasse trägt
        boolean trouvé=false;
        for (int i = 0; ! trouvé && i < pluginConfigs.length; i++) {
            // Name des Plugins
            String pluginClassName=pluginConfigs[i].getClassName();
             // Wenn es nicht das richtige Plugin ist, fahren wir fort
            if(! pluginClassName.equals(className)) continue;
            // Es ist das richtige – seine Eigenschaften werden im Kontext gespeichert
            servlet.getServletContext().setAttribute("initialisations",pluginConfigs[i].getProperties());
            trouvé=true;
        }//for i
    } //initialisieren
} //Klasse

Beachten Sie bitte folgende Punkte:

  • Die Methode „init“ erhält einen Parameter namens „conf“ vom Typ „ModuleConfig“, der Zugriff auf den Inhalt der Datei „struts-config.xml“ gewährt.
  • Die Methode [ModuleConfig].findPlugInConfigs() ermöglicht es, alle <plug-in>-Abschnitte der Struts-Konfigurationsdatei in Form eines Arrays von PlugInConfig-Objekten abzurufen.
  • Die Klasse PluginConfig repräsentiert einen <plug-in>-Abschnitt der Konfigurationsdatei. Die Methode [PlugInConfig].getProperties ermöglicht uns den Zugriff auf die <set-property>-Elemente des Abschnitts in Form eines java.util.Map-Wörterbuchs.
  • Das Wörterbuch der Plugin-Eigenschaften wird in den Anwendungskontext eingebunden.
  • Da es mehrere Plugins geben kann, müssen wir dasjenige finden, das uns interessiert. Es ist dasjenige, das denselben Namen wie die ausgeführte Klasse trägt.

Wir haben uns hier dafür entschieden, das gesamte Wörterbuch in den Kontext einzufügen. Wir hätten dieses auch nutzen können. Der folgende Codeabschnitt veranschaulicht eine Möglichkeit, dies zu tun:

            Map initialisations = pluginConfigs[i].getProperties();
             // die Einträge des Wörterbuchs durchlaufen
            Iterator entrées = initialisations.entrySet().iterator();
            while (entrées.hasNext()) {
                 // den aktuellen Eintrag (Schlüssel, Wert) abrufen
                Map.Entry entrée = (Map.Entry) entrées.next();
                String clé = (String) entrée.getKey();
                String valeur = (String) entrée.getValue();
                // (Schlüssel, Wert) auswerten
                //...
            }

8.3. Der Code der Ansicht infos.jsp

Die Ansicht infos.jsp dient dazu, den Inhalt des Eigenschaftswörterbuchs des Plugins anzuzeigen, das in den Anwendungskontext eingebunden wurde. Da die Ansicht infos.jsp Teil dieses Kontexts ist, hat sie Zugriff darauf. Ihr Code lautet wie folgt:

<%@ 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>

Hinweise:

  • Wir verwenden die Tag-Bibliotheken „struts-logic“ und „struts-bean“.
  • Das Tag <logic:iterate> ermöglicht es uns, das Initialisierungswörterbuch anzuzeigen, das durch die init-Methode des Plugins in den Kontext gesetzt wurde. Das Attribut „name“ bezeichnet das Objekt, über das iteriert werden soll. Dabei muss es sich um etwas handeln, das einer Sammlung, einem Iterator usw. ähnelt. Das Objekt wird in allen Gültigkeitsbereichen (Seite, Anfrage, Sitzung, Kontext) gesucht. Hier wird es im Kontext-Bereich gefunden. Der Parameter „id“ dient dazu, dem aktuellen Element der Sammlung im Verlauf der Iterationen einen Namen zu geben. Hier, im Hauptteil des Tags <logic:iterate>, steht „element“ für das aktuelle Element eines Wörterbuchs. Dieses wird durch ein Objekt „java.util.Map.Entry“ dargestellt, das grob gesagt ein (Schlüssel, Wert)-Paar des Wörterbuchs ist.
  • Im Hauptteil des <logic:iterate>-Tags wird der Inhalt des aktuellen Elements „element“ angezeigt (<bean:write>). Dieses wird als Objekt mit zwei Eigenschaften (property) betrachtet: dem Schlüssel „key“ und dem Wert „value“. Diese beiden Eigenschaften werden angezeigt.

8.4. Bereitstellung

Der Anwendungskontext wird in der Tomcat-Konfigurationsdatei server.xml definiert:

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

Die Verzeichnisstruktur der Anwendung sieht wie folgt aus:

 
 

8.5. Die Tests

Wir starten Tomcat und rufen die Seite URL http://localhost:8080/plugin1/infos.jsp auf:

Image

Wir stellen fest, dass die Ansicht infos.jsp tatsächlich auf die Informationen zugreifen konnte, die vom Plugin im Anwendungskontext gespeichert wurden.

8.6. Fazit

Wir haben gezeigt, dass sich eine Struts-Anwendung mithilfe eines Plugins initialisieren lässt. Dies kann eine Alternative zur Ableitung der Klasse ActionServlet sein, um dieselbe Aufgabe zu erfüllen.