8. Een plug-in maken
Het is mogelijk om applicaties, zogenaamde plug-ins, te maken die bij het opstarten van een Struts-applicatie worden geladen en bij het afsluiten ervan worden ontladen. Dit maakt het doorgaans mogelijk om initialisaties uit te voeren bij het opstarten van de applicatie en om bronnen vrij te geven bij het afsluiten ervan. Deze bewerkingen kunnen ook worden uitgevoerd door de klasse ActionServlet af te leiden van de controller, en dat is wat er in de vorige toepassing is gedaan. De plug-in is een alternatief voor deze oplossing. De plug-in kan een complexere toepassing zijn dan alleen het initialiseren van de omgeving. We hebben hier een voorbeeld van gezien in de les waarin de begrippen van declaratieve validatieregels werden geïntroduceerd. Een plug-in wordt gedeclareerd in het configuratiebestand van Struts. De plug-in ValidatorPlugIn werd dus als volgt gedeclareerd in het bestand struts-config.xml van de applicatie die er gebruik van maakte:
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property
property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"
/>
</plug-in>
We beschrijven nu een Struts-applicatie die gebruikmaakt van een plug-in.
8.1. Configuratie van de Struts-applicatie /plugin1
We stellen voor om de Struts-applicatie /plugin1 te bouwen, die als volgt is geconfigureerd:
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>
We zullen niet verder ingaan op dit standaardbestand.
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>
We hebben slechts één sectie toegevoegd, namelijk die voor de plug-in. De attributen van de <plug-in>-tag die hier worden gebruikt, zijn de volgende:
naam van de klasse van de plug-in | |
maakt het mogelijk de plug-in te initialiseren met (sleutel, waarde)-paren |
Het doel van deze toepassing is om te laten zien hoe de plug-in zijn initialisatieparameters kan ophalen en deze beschikbaar kan maken voor andere objecten die dezelfde applicatiecontext delen. We zullen een eenvoudige weergave JSP gebruiken om de initialisatiewaarden van de plug-in weer te geven, wat verklaart waarom er geen actie in het configuratiebestand staat.
8.2. De Java-klasse van de plug-in
Een Java-klasse die als plug-in voor een Struts-toepassing dient, moet de interface org.apache.struts.action.PlugIn implementeren. Deze implementatie bestaat uit het schrijven van twee methoden:
- public void init(ActionServlet servlet, ModuleConfig conf)
- public void destroy()
Wanneer de Struts-applicatie wordt geladen, zal de controller alle plug-ins instantiëren die zijn gedeclareerd in het bestand struts-config.xml. Vervolgens voert hij de methode init van elk van deze plug-ins uit. In deze methode voert de plug-in zijn initialisaties uit. Hier beperken we ons tot het inlezen van de initialisatieparameters van de plug-in en deze in de context van de applicatie te plaatsen, zodat ze beschikbaar zijn voor alle andere objecten daarin. Wanneer de applicatie wordt ontladen, voert de controller de methode destroy van elke geladen plug-in uit. Dit is het moment om overbodige bronnen vrij te geven. Hier hoeven we niets te doen.
De code van de klasse is als volgt:
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 wordt aangeroepen bij het verwijderen van de applicatiecontext
public void destroy() {
}
// methode aangeroepen bij het voor het eerst aanmaken van de applicatiecontext
public void init(ActionServlet servlet, ModuleConfig conf)
throws ServletException {
// naam van de klasse van dit object
String className=this.getClass().getName();
// lijst met plug-ins
PlugInConfig[] pluginConfigs = conf.findPlugInConfigs();
// doorzoeken van de plug-ins om degene te vinden
// die de naam van deze klasse draagt
boolean trouvé=false;
for (int i = 0; ! trouvé && i < pluginConfigs.length; i++) {
// naam van de plug-in
String pluginClassName=pluginConfigs[i].getClassName();
// als dit niet de juiste plug-in is, gaan we verder
if(! pluginClassName.equals(className)) continue;
// dit is de juiste – we slaan de eigenschappen ervan op in de context
servlet.getServletContext().setAttribute("initialisations",pluginConfigs[i].getProperties());
trouvé=true;
}//for i
} //init
} //klasse
Let op de volgende punten:
- de methode init ontvangt een parameter die hier conf wordt genoemd, van het type ModuleConfig, die toegang geeft tot de inhoud van het bestand struts-config.xml.
- Met de methode [ModuleConfig].findPlugInConfigs() kunnen alle <plug-in>-secties uit het Struts-configuratiebestand worden opgehaald in de vorm van een array van PlugInConfig-objecten.
- De klasse PluginConfig vertegenwoordigt een <plug-in>-sectie van het configuratiebestand. Met de methode [PlugInConfig].getProperties krijgen we toegang tot de <set-property>-elementen van de sectie in de vorm van een woordenboek java.util.Map.
- Het woordenboek met de eigenschappen van de plug-in wordt in de context van de applicatie geplaatst.
- Aangezien er meerdere plug-ins kunnen zijn, moeten we degene vinden die voor ons van belang is. Dit is de plug-in met dezelfde naam als de klasse die wordt uitgevoerd.
We hebben er hier de voorkeur aan gegeven om het volledige woordenboek in de context op te nemen. We hadden er ook gebruik van kunnen maken. De volgende codereeks illustreert een manier om dit te doen:
Map initialisations = pluginConfigs[i].getProperties();
// door de items in het woordenboek lopen
Iterator entrées = initialisations.entrySet().iterator();
while (entrées.hasNext()) {
// het huidige item (sleutel, waarde) ophalen
Map.Entry entrée = (Map.Entry) entrées.next();
String clé = (String) entrée.getKey();
String valeur = (String) entrée.getValue();
// (sleutel, waarde) verwerken
//...
}
8.3. De code van de weergave infos.jsp
De weergave infos.jsp is bedoeld om de inhoud van het eigenschappenwoordenboek van de plug-in weer te geven die in de context van de applicatie is geplaatst. Aangezien de weergave infos.jsp deel uitmaakt van deze context, heeft deze er toegang toe. De code ervan is als volgt:
<%@ 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>
Opmerkingen:
- we gebruiken de tagbibliotheken struts-logic en struts-bean
- met de tag <logic:iterate> kunnen we het initialisatiewoordenboek weergeven dat door de init-methode van de plug-in in de context is geplaatst. Het attribuut name geeft het object aan waarover moet worden geïtereerd. Dit moet iets zijn dat lijkt op een verzameling, een iterator, ... Het object wordt gezocht in alle scopes (pagina, verzoek, sessie, context). Hier wordt het gevonden in de context-scope. De parameter id wordt gebruikt om het huidige element van de verzameling tijdens de iteraties een naam te geven. Hier, in de body van de tag <logic:iterate>, vertegenwoordigt element het huidige element van een woordenboek. Dit wordt vertegenwoordigd door een object java.util.Map.Entry, dat grofweg een (sleutel, waarde)-paar uit het woordenboek is.
- In de body van de tag <logic:iterate> wordt de inhoud van het huidige element element weergegeven (<bean:write>). Dit wordt beschouwd als een object met twee eigenschappen (property): de sleutel key en de waarde value. Deze twee eigenschappen worden weergegeven.
8.4. Implementatie
De context van de applicatie wordt gedefinieerd in het Tomcat-configuratiebestand server.xml:
<Context path="/plugin11" reloadable="true" docBase="E:\data\serge\web\struts\plugins\1" />
De structuur van de applicatie is als volgt:
![]() ![]() | ![]() | |
![]() | ||
8.5. De tests
We starten Tomcat en roepen de URL-http://localhost:8080/plugin1/infos.jsp op:

We zien dat de weergave infos.jsp inderdaad toegang heeft gekregen tot de informatie die door de plug-in in de applicatiecontext is opgeslagen.
8.6. Conclusie
We hebben aangetoond dat het mogelijk is om een Struts-applicatie te initialiseren met behulp van een plug-in. Dit kan een alternatief zijn voor het afleiden van de klasse ActionServlet om hetzelfde te bereiken.



