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 视图来显示插件的初始化值,这也解释了为何配置文件中没有 action 元素。

8.2. 插件的 Java 类

作为 Struts 应用程序插件的 Java 类必须实现 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 {

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

请注意以下几点:

  • init 方法接受一个名为 conf(类型为 ModuleConfig)的参数,该参数提供对 struts-config.xml 文件内容的访问。
  • [ModuleConfig].findPlugInConfigs() 方法会从 Struts 配置文件中检索所有 <plug-in> 部分,并以 PlugInConfig 对象数组的形式返回。
  • PlugInConfig 类表示配置文件中的一个 <plug-in> 部分。通过 [PlugInConfig].getProperties 方法,我们可以以 java.util.Map 字典的形式访问该部分中的 <set-property> 元素。
  • 插件的属性字典被放置在应用程序上下文中。
  • 由于可能存在多个插件,我们需要找到我们感兴趣的那个。它就是与正在执行的类同名的那个。

在此,我们选择将整个字典放入上下文中。我们本可以选择直接使用它。以下代码片段演示了一种实现方式:

            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. 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> 标签允许我们显示由插件的 init 方法放置在上下文中的初始化字典。name 属性指定要迭代的对象。该对象应为集合、迭代器等类型。系统将在所有作用域(页面、请求、会话、上下文)中搜索该对象。 在此示例中,该对象将在上下文作用域中被找到。id 参数用于在迭代过程中为集合的当前元素命名。在此,在 <logic:iterate> 标签的主体中,element 将代表字典的当前元素。该元素由一个 java.util.Map.Entry 对象表示,本质上是字典中的一个 (键, 值) 对。
  • <logic:iterate> 标签的正文中,我们通过 (<bean:write>) 显示当前元素 element 的内容。该元素被视为一个具有两个属性的对象:。这两个属性都会被显示出来。

8.4. 部署

应用程序上下文在 Tomcat 的 server.xml 配置文件中进行定义:

<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 类以实现相同结果的一种替代方案。