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> که در اینجا استفاده شده به شرح زیر است:
نام کلاس پلاگین | |
امکان راهاندازی افزونه با جفتهای (کلید، مقدار) را فراهم میکند |
هدف این برنامه نشان دادن نحوه بازیابی پارامترهای راهاندازی توسط پلاگین و در دسترس قرار دادن آنها برای سایر اشیاء با اشتراکگذاری همان زمینه برنامه است. ما از یک نمای ساده، JSP، برای نمایش مقادیر راهاندازی پلاگین استفاده خواهیم کرد، که دلیل عدم وجود هیچ اقدامی در فایل پیکربندی را توضیح میدهد.
8.2. کلاس جاواِ افزونه
یک کلاس جاوا که بهعنوان افزونه برای یک برنامه 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;
}//برای 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 افزونه در `context` قرار گرفته است، نمایش دهیم. ویژگی `name` شیئی را که باید روی آن ایتریشن (iterate) انجام شود، مشخص میکند. این باید چیزی شبیه به یک مجموعه (collection)، یک ایتراتور (iterator) و غیره باشد. شیء در تمام دامنهها (page, request, session, context) جستجو میشود. در اینجا، این مورد در دامنهٔ زمینه (context) یافت میشود. پارامتر id برای اختصاص نام به عنصر فعلی مجموعه در حین تکرار استفاده میشود. در اینجا، در داخل بدنه تگ `<logic:iterate>`, `element` نماینده عنصر فعلی یک دیکشنری خواهد بود. این عنصر توسط یک شیء `java.util.Map.Entry` نمایش داده میشود که در واقع یک جفت (کلید، مقدار) از دیکشنری است.
- درون بدنه تگ <logic:iterate>، محتوای عنصر جاری نمایش داده میشود (<bean:write>). این محتوا بهعنوان یک شیء با دو ویژگی در نظر گرفته میشود: کلید و مقدار. هر دو ویژگی نمایش داده میشوند.
8.4. استقرار
شاهدگاه برنامه در فایل پیکربندی Tomcat به نام server.xml تعریف شده است:
<Context path="/plugin11" reloadable="true" docBase="E:\data\serge\web\struts\plugins\1" />
ساختار دایرکتوری برنامه به شرح زیر است:
![]() ![]() | ![]() | |
![]() | ||
8.5. آزمایش
ما تامکت را راهاندازی میکنیم و http://localhost:8080/plugin1/infos.jsp را درخواست میکنیم:

میتوانیم ببینیم که نمای infos.jsp با موفقیت به اطلاعات ذخیرهشده در زمینهٔ برنامه از طریق افزونه دسترسی پیدا کرده است.
8.6. نتیجهگیری
ما نشان دادهایم که یک برنامه Struts میتواند با استفاده از یک پلاگین راهاندازی شود. این میتواند جایگزینی برای گسترش کلاس ActionServlet برای دستیابی به همان نتیجه باشد.



