8. Criação de um plugin
É possível criar aplicações chamadas plugins que são carregadas quando uma aplicação Struts é iniciada e descarregadas quando esta é encerrada. Isto permite, normalmente, a inicialização quando a aplicação é iniciada e a libertação de recursos quando esta é encerrada. Estas operações também podem ser realizadas através da extensão da classe ActionServlet do controlador, que foi o que se fez na aplicação anterior. O plugin é uma alternativa a esta solução. Um plugin pode ser uma aplicação mais complexa do que uma simples inicialização do ambiente. Vimos um exemplo disso na lição em que foram introduzidas as regras de validação declarativas. Um plugin é declarado no ficheiro de configuração do Struts. O ValidatorPlugIn foi declarado no ficheiro struts-config.xml da aplicação que o utilizou da seguinte forma:
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property
property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"
/>
</plug-in>
Vamos agora descrever uma aplicação Struts utilizando um plugin.
8.1. Configuração da aplicação Struts /plugin1
Propomos construir a aplicação Struts /plugin1 configurada da seguinte forma:
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>
Não nos vamos deter neste ficheiro, uma vez que é padrão.
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>
Adicionámos apenas uma secção, a do plugin. Os atributos da tag <plug-in> aqui utilizada são os seguintes:
nome da classe do plugin | |
permite que o plugin seja inicializado com pares (chave, valor) |
O objetivo desta aplicação é demonstrar como o plugin pode recuperar os seus parâmetros de inicialização e disponibilizá-los a outros objetos que partilham o mesmo contexto de aplicação. Utilizaremos uma vista JSP simples para apresentar os valores de inicialização do plugin, o que explica a ausência de uma ação no ficheiro de configuração.
8.2. A classe Java do plugin
Uma classe Java que funciona como um plugin para uma aplicação Struts deve implementar a interface org.apache.struts.action.PlugIn. Esta implementação envolve a escrita de dois métodos:
- public void init(ActionServlet servlet, ModuleConfig conf)
- public void destroy()
Quando a aplicação Struts é carregada, o seu controlador instanciará todos os plugins declarados no ficheiro struts-config.xml. Em seguida, executará o método init para cada um deles. É dentro deste método que o plugin realiza a sua inicialização. Aqui, iremos simplesmente ler os parâmetros de inicialização do plugin e colocá-los no contexto da aplicação, para que fiquem disponíveis para todos os outros objetos na aplicação. Quando a aplicação for descarregada, o controlador executará o método destroy para cada um dos plugins carregados. Este é o momento de libertar os recursos que já não são necessários. Aqui, não teremos nada a fazer.
O código da classe é o seguinte:
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 {
// method called when application context is deleted
public void destroy() {
}
// method called on initial creation of application context
public void init(ActionServlet servlet, ModuleConfig conf)
throws ServletException {
// class name of this object
String className=this.getClass().getName();
// plug-in list
PlugInConfig[] pluginConfigs = conf.findPlugInConfigs();
// explore plugins to find the right one
// which is named after this class
boolean trouvé=false;
for (int i = 0; ! trouvé && i < pluginConfigs.length; i++) {
// plugin name
String pluginClassName=pluginConfigs[i].getClassName();
// if it's not the right plugin, continue
if(! pluginClassName.equals(className)) continue;
// it's the right one - you memorize its properties in context
servlet.getServletContext().setAttribute("initialisations",pluginConfigs[i].getProperties());
trouvé=true;
}//for i
} //init
} //class
Tenha em atenção os seguintes pontos:
- O método init recebe um parâmetro chamado conf (do tipo ModuleConfig) que fornece acesso ao conteúdo do ficheiro struts-config.xml.
- O método [ModuleConfig].findPlugInConfigs() recupera todas as secções <plug-in> do ficheiro de configuração do Struts sob a forma de uma matriz de objetos PlugInConfig.
- A classe PluginConfig representa uma secção <plug-in> do ficheiro de configuração. O método [PlugInConfig].getProperties permite-nos aceder aos elementos <set-property> da secção sob a forma de um dicionário java.util.Map.
- O dicionário de propriedades do plugin é colocado no contexto da aplicação.
- Uma vez que podem existir vários plugins, precisamos de encontrar aquele que nos interessa. É aquele com o mesmo nome que a classe que está a ser executada.
Aqui, optámos por colocar o dicionário completo no contexto. Poderíamos ter optado por utilizá-lo. O seguinte fragmento de código ilustra uma forma de o fazer:
Map initialisations = pluginConfigs[i].getProperties();
// iterate over dictionary entries
Iterator entrées = initialisations.entrySet().iterator();
while (entrées.hasNext()) {
// retrieve current input (key,value)
Map.Entry entrée = (Map.Entry) entrées.next();
String clé = (String) entrée.getKey();
String valeur = (String) entrée.getValue();
// exploit (key,value)
//...
}
8.3. O código da vista infos.jsp
A vista infos.jsp é responsável por exibir o conteúdo do dicionário de propriedades do plugin, que foi colocado no contexto da aplicação. Uma vez que a vista infos.jsp faz parte deste contexto, tem acesso ao mesmo. O seu código é o seguinte:
<%@ 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>
Notas:
- Utilizamos as bibliotecas de tags struts-logic e struts-bean
- A tag <logic:iterate> permite-nos apresentar o dicionário de inicializações que foi colocado no contexto pelo método init do plugin. O atributo name especifica o objeto sobre o qual se irá iterar. Este deve ser algo como uma coleção, um iterador, etc. O objeto é procurado em todos os âmbitos (página, pedido, sessão, contexto). Aqui, será encontrado no âmbito do contexto. O parâmetro id é utilizado para nomear o elemento atual da coleção à medida que a iteração avança. Aqui, dentro do corpo da tag <logic:iterate>, element representará o elemento atual de um dicionário. Isto é representado por um objeto java.util.Map.Entry, que é essencialmente um par (chave, valor) do dicionário.
- No corpo da tag <logic:iterate>, exibimos (<bean:write>) o conteúdo do elemento atual element. Este é tratado como um objeto com duas propriedades: a chave e o valor. Ambas as propriedades são exibidas.
8.4. Implantação
O contexto da aplicação é definido no ficheiro de configuração server.xml do Tomcat:
<Context path="/plugin11" reloadable="true" docBase="E:\data\serge\web\struts\plugins\1" />
A estrutura de diretórios da aplicação é a seguinte:
![]() ![]() | ![]() | ||
![]() | |||
8.5. Testes
Iniciamos o Tomcat e acedemos à URL http://localhost:8080/plugin1/infos.jsp:

Verificamos que a página infos.jsp acedeu com sucesso às informações armazenadas no contexto da aplicação através do plugin.
8.6. Conclusão
Demonstrámos que uma aplicação Struts pode ser inicializada utilizando um plugin. Isto pode servir como alternativa à derivação da classe ActionServlet para alcançar o mesmo resultado.



