在做struts應(yīng)用的時候,經(jīng)常學(xué)要修改struts-config.xml文件,在每次修改完之后只有重新啟動服務(wù)器才能讓修改生效。因此做了一個Listener,在應(yīng)用啟動的時候開始,每隔一段時間就去檢查一下struts-config.xml文件的最后修改時間,如果修改時間變化了,就重新讀取struts-config.xml,將對應(yīng)的配置放到ServletContext中去。 一.LoadResourceListener import java.util.Timer;
import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener;
import kick.utils.Constants;
public class LoadResourceListener implements ServletContextListener {
/* (non-Javadoc) * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) */ public void contextInitialized(ServletContextEvent event) { Timer loadResource = new Timer(); //獲取ServletContext ServletContext servletContext = event.getServletContext(); //創(chuàng)建一個LoadResourceTimerTask 的實(shí)例 LoadResourceTimerTask loadResourceTimerTask = new LoadResourceTimerTask(servletContext); //將剛創(chuàng)建的TimerTask的實(shí)例的運(yùn)行計(jì)劃訂為:馬上開始,每隔20×1000ms運(yùn)行一次 loadResource.schedule(loadResourceTimerTask,0,Constants.DELAY_UPDATE_TIME); }
/* (non-Javadoc) * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) */ public void contextDestroyed(ServletContextEvent arg0) { }
} 二.配置LoadResourceListener
在filter的配置下面添加上如下的配置 <listener> <listener-class>kick.load.resource.LoadResourceListener</listener-class> </listener> 三.LoadResourceTimerTask類 /* * Created on 2005-9-6 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package kick.load.resource;
import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.MissingResourceException; import java.util.Set; import java.util.TimerTask;
import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.UnavailableException; import javax.sql.DataSource;
import kick.utils.Constants;
import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.collections.FastHashMap; import org.apache.commons.digester.Digester; import org.apache.commons.digester.RuleSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.Globals; import org.apache.struts.config.ConfigRuleSet; import org.apache.struts.config.DataSourceConfig; import org.apache.struts.config.FormBeanConfig; import org.apache.struts.config.MessageResourcesConfig; import org.apache.struts.config.ModuleConfig; import org.apache.struts.config.ModuleConfigFactory; import org.apache.struts.util.MessageResources; import org.apache.struts.util.MessageResourcesFactory; import org.apache.struts.util.RequestUtils; import org.apache.struts.util.ServletContextWriter; import org.xml.sax.InputSource; import org.xml.sax.SAXException;
public class LoadResourceTimerTask extends TimerTask { private ServletContext context = null;
/** * <p> * The resources object for our internal resources. * </p> */ protected MessageResources internal = null;
/** * <p> * The Digester used to produce ModuleConfig objects from a Struts * configuration file. * </p> * * @since Struts 1.1 */ protected Digester configDigester = null;
/** * <p> * The Java base name of our internal resources. * </p> * * @since Struts 1.1 */ protected String internalName = "org.apache.struts.action.ActionResources";
/** * <p> * Commons Logging instance. * </p> * * @since Struts 1.1 */ protected static Log log = LogFactory.getLog(LoadResourceTimerTask.class);
private List initParams = null;
/** * <p> * The set of public identifiers, and corresponding resource names, for the * versions of the configuration file DTDs that we know about. There * <strong>MUST </strong> be an even number of Strings in this list! * </p> */ protected String registrations[] = { "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN", "/org/apache/struts/resources/struts-config_1_0.dtd", "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN", "/org/apache/struts/resources/struts-config_1_1.dtd", "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN", "/org/apache/struts/resources/struts-config_1_2.dtd", "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN", "/org/apache/struts/resources/web-app_2_2.dtd", "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN", "/org/apache/struts/resources/web-app_2_3.dtd" };
/** * <p> * The JDBC data sources that has been configured for this module, if any, * keyed by the servlet context attribute under which they are stored. * </p> */ protected FastHashMap dataSources = new FastHashMap();
/** * <p> * Comma-separated list of context-relative path(s) to our configuration * resource(s) for the default module. * </p> */ protected String config = "/WEB-INF/struts-config.xml";
private List resourcesName = new ArrayList();
private Set resourceFiles = new HashSet();
public LoadResourceTimerTask(ServletContext context) { this.context = context; try { initInternal(); parseWeb(); parseConfigFile(); parseResource(); // parseConfigFile(); } catch (ServletException e) { System.out.println(e.getMessage()); e.printStackTrace(); throw new RuntimeException(e); } }
/* * (non-Javadoc) * * @see java.util.TimerTask#run() */ public void run() { try { reLoadConfigFile(); reLoadResource(); } catch (Exception e) {
} }
/** * */ private void parseConfigFile() { InitParam initParam = null; for (int i = 0; i < initParams.size(); i++) { initParam = (InitParam) initParams.get(i); String name = initParam.getName(); if (!name.startsWith("config")) { continue; } String prefix = name.substring(6); String paths = initParam.getValue(); // Process each specified resource path while (paths.length() > 0) { // digester.push(config); String path = null; int comma = paths.indexOf(','); if (comma >= 0) { path = paths.substring(0, comma).trim(); paths = paths.substring(comma + 1); } else { path = paths.trim(); paths = ""; }
if (path.length() < 1) { break; } File file = new File(getServletContext().getRealPath(path)); StrutsConfig s = new StrutsConfig(); Digester d = new Digester(); d.push(s); d.setNamespaceAware(false); d.setValidating(false); for (int j = 0; j < registrations.length; j += 2) { URL url = this.getClass().getResource(registrations[j + 1]); if (url != null) { d.register(registrations[j], url.toString()); } } d.addObjectCreate("struts-config/message-resources", Resource.class); d.addSetProperties("struts-config/message-resources", "parameter", "parameter"); d.addSetNext("struts-config/message-resources", "addResource");
// d.addCallMethod("web-struts-config/message-resources", // "setParameter", 0); try { d.parse(file); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } // String resourcePath = // ((Resource)s.getResources()).toFilePaht(); List rs = s.getResources(); for (int ii = 0; ii < rs.size(); ii++) { resourcesName.add(((Resource) rs.get(ii)).toFilePaht()); } } } }
public void parseResource() { int index = 0; String dirName = ""; String resource = ""; String subFileName = "";
for (int i = 0; i < resourcesName.size(); i++) { resource = (String) resourcesName.get(i); index = resource.lastIndexOf("/"); dirName = resource.substring(0, index); subFileName = resource.substring(index + 1, resource.length()); File file = new File(getServletContext().getRealPath("/WEB-INF/classes/" + dirName)); if (file.isDirectory()) { String[] fileNames = file.list(); if (fileNames != null) { for (int j = 0; j < fileNames.length; j++) { if (fileNames[j] != null) { if (fileNames[j].trim().startsWith(subFileName.trim())) { resourceFiles.add(dirName + "/" + fileNames[j]); // System.out.println("The file Name : '" + // subFileName + "'"); // System.out.println("Add file name : '" + // fileNames[j] + "'"); } } } } } } }
private void reLoadConfigFile() { try { InitParam initParam = null; for (int i = 0; i < initParams.size(); i++) { initParam = (InitParam) initParams.get(i); String name = initParam.getName(); if (!name.startsWith("config")) { continue; } String prefix = name.substring(6); String paths = initParam.getValue(); // Process each specified resource path while (paths.length() > 0) { // digester.push(config); String path = null; int comma = paths.indexOf(','); if (comma >= 0) { path = paths.substring(0, comma).trim(); paths = paths.substring(comma + 1); } else { path = paths.trim(); paths = ""; }
if (path.length() < 1) { break; }
File file = new File(getServletContext().getRealPath(path)); if ((System.currentTimeMillis() - file.lastModified()) < Constants.DELAY_UPDATE_TIME) { log.debug("The struts-config.xml is changed,will be reload into context."); log.debug("The file name is : '" + path + "'"); log.debug("Refash the resource file config list!"); parseConfigFile(); log.debug("Refash the resource file list!"); parseResource(); ModuleConfig moduleConfig = initModuleConfig(prefix, path); initModuleMessageResources(moduleConfig); initModuleDataSources(moduleConfig); moduleConfig.freeze(); log.debug("Reload the config file success!"); } this.initModulePrefixes(this.getServletContext()); } } } catch (Exception e) {
} }
private void reLoadConfig(String prefix, String path) { try { ModuleConfig moduleConfig = initModuleConfig(prefix, path); initModuleMessageResources(moduleConfig); initModuleDataSources(moduleConfig); moduleConfig.freeze(); } catch (Exception e) {
} }
private void reLoadResource() { Iterator it = resourceFiles.iterator(); String fileName = ""; while (it.hasNext()) { fileName = (String) it.next(); File file = new File(this.getServletContext().getRealPath("/WEB-INF/classes/" + fileName)); if ((System.currentTimeMillis() - file.lastModified()) < Constants.DELAY_UPDATE_TIME) { log.debug("Update the '" + file.getName() + "' property file!"); updateConfigFile(); } } }
/** * */ private void updateConfigFile() { InitParam initParam = null; for (int i = 0; i < initParams.size(); i++) { initParam = (InitParam) initParams.get(i); String name = initParam.getName(); if (!name.startsWith("config")) { continue; } String prefix = name.substring(6); String paths = initParam.getValue(); // Process each specified resource path while (paths.length() > 0) { // digester.push(config); String path = null; int comma = paths.indexOf(','); if (comma >= 0) { path = paths.substring(0, comma).trim(); paths = paths.substring(comma + 1); } else { path = paths.trim(); paths = ""; }
if (path.length() < 1) { break; }
File file = new File(getServletContext().getRealPath(path)); file.setLastModified(System.currentTimeMillis()); } } }
/** * */ private void parseWeb() { InputStream input = getServletContext().getResourceAsStream("/WEB-INF/web.xml"); WebApp w = new WebApp(); Digester d = new Digester(); d.push(w); d.setNamespaceAware(false); d.setValidating(false); for (int i = 0; i < registrations.length; i += 2) { URL url = this.getClass().getResource(registrations[i + 1]); if (url != null) { d.register(registrations[i], url.toString()); } } d.addObjectCreate("web-app/servlet", Servlet.class); d.addSetNext("web-app/servlet", "addServlet"); d.addObjectCreate("web-app/servlet/init-param", InitParam.class); d.addSetNext("web-app/servlet/init-param", "addInitParams");
d.addCallMethod("web-app/servlet/init-param/param-name", "setName", 0); d.addCallMethod("web-app/servlet/init-param/param-value", "setValue", 0); try { d.parse(input); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); }
List l = w.getServlets(); if (l.size() > 0) { initParams = ((Servlet) l.get(0)).getInitParams(); } initParams = ((Servlet) ((List) w.getServlets()).get(0)).getInitParams(); try { input.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }
/** * <p> * Gracefully release any configDigester instance that we have created. * </p> * * @since Struts 1.1 */ protected void destroyConfigDigester() {
configDigester = null;
}
/** * <p> * Saves a String[] of module prefixes in the ServletContext under * Globals.MODULE_PREFIXES_KEY. <strong>NOTE </strong>- the "" prefix for * the default module is not included in this list. * </p> * * @param context * The servlet context. * @since Struts 1.2 */ protected void initModulePrefixes(ServletContext context) { ArrayList prefixList = new ArrayList();
Enumeration names = context.getAttributeNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); if (!name.startsWith(Globals.MODULE_KEY)) { continue; }
String prefix = name.substring(Globals.MODULE_KEY.length()); if (prefix.length() > 0) { prefixList.add(prefix); } }
String[] prefixes = (String[]) prefixList.toArray(new String[prefixList.size()]); context.setAttribute(Globals.MODULE_PREFIXES_KEY, prefixes); }
/** * <p> * Initialize the data sources for the specified module. * </p> * * @param config * ModuleConfig information for this module * * @exception ServletException * if initialization cannot be performed * @since Struts 1.1 */ protected void initModuleDataSources(ModuleConfig config) throws ServletException {
// :FIXME: Document UnavailableException?
if (log.isDebugEnabled()) { log.debug("Initializing module path '" + config.getPrefix() + "' data sources"); }
ServletContextWriter scw = new ServletContextWriter(getServletContext()); DataSourceConfig dscs[] = config.findDataSourceConfigs(); if (dscs == null) { dscs = new DataSourceConfig[0]; }
dataSources.setFast(false); for (int i = 0; i < dscs.length; i++) { if (log.isDebugEnabled()) { log.debug("Initializing module path '" + config.getPrefix() + "' data source '" + dscs[i].getKey() + "'"); } DataSource ds = null; try { ds = (DataSource) RequestUtils.applicationInstance(dscs[i].getType()); BeanUtils.populate(ds, dscs[i].getProperties()); ds.setLogWriter(scw);
} catch (Exception e) { log.error(internal.getMessage("dataSource.init", dscs[i].getKey()), e); throw new UnavailableException(internal.getMessage("dataSource.init", dscs[i].getKey())); } getServletContext().setAttribute(dscs[i].getKey() + config.getPrefix(), ds); dataSources.put(dscs[i].getKey(), ds); }
dataSources.setFast(true);
}
/** * <p> * Initialize the application <code>MessageResources</code> for the * specified module. * </p> * * @param config * ModuleConfig information for this module * * @exception ServletException * if initialization cannot be performed * @since Struts 1.1 */ protected void initModuleMessageResources(ModuleConfig config) throws ServletException {
MessageResourcesConfig mrcs[] = config.findMessageResourcesConfigs(); for (int i = 0; i < mrcs.length; i++) { if ((mrcs[i].getFactory() == null) || (mrcs[i].getParameter() == null)) { continue; } if (log.isDebugEnabled()) { log.debug("Initializing module path '" + config.getPrefix() + "' message resources from '" + mrcs[i].getParameter() + "'"); }
String factory = mrcs[i].getFactory(); MessageResourcesFactory.setFactoryClass(factory); MessageResourcesFactory factoryObject = MessageResourcesFactory.createFactory();
MessageResources resources = factoryObject.createResources(mrcs[i].getParameter()); resources.setReturnNull(mrcs[i].getNull()); getServletContext().setAttribute(mrcs[i].getKey() + config.getPrefix(), resources); }
}
/** * <p> * Initialize the module configuration information for the specified module. * </p> * * @param prefix * Module prefix for this module * @param paths * Comma-separated list of context-relative resource path(s) for * this modules's configuration resource(s) * * @exception ServletException * if initialization cannot be performed * @since Struts 1.1 */ protected ModuleConfig initModuleConfig(String prefix, String paths) throws ServletException {
// :FIXME: Document UnavailableException? (Doesn't actually throw // anything)
if (log.isDebugEnabled()) { log.debug("Initializing module path '" + prefix + "' configuration from '" + paths + "'"); }
// Parse the configuration for this module ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory(); ModuleConfig config = factoryObject.createModuleConfig(prefix);
// Configure the Digester instance we will use Digester digester = initConfigDigester();
// Process each specified resource path while (paths.length() > 0) { digester.push(config); String path = null; int comma = paths.indexOf(','); if (comma >= 0) { path = paths.substring(0, comma).trim(); paths = paths.substring(comma + 1); } else { path = paths.trim(); paths = ""; }
if (path.length() < 1) { break; }
this.parseModuleConfigFile(digester, path); }
getServletContext().setAttribute(Globals.MODULE_KEY + config.getPrefix(), config);
// Force creation and registration of DynaActionFormClass instances // for all dynamic form beans we wil be using FormBeanConfig fbs[] = config.findFormBeanConfigs(); for (int i = 0; i < fbs.length; i++) { if (fbs[i].getDynamic()) { fbs[i].getDynaActionFormClass(); } }
return config; }
/** * <p> * Create (if needed) and return a new <code>Digester</code> instance that * has been initialized to process Struts module configuration files and * configure a corresponding <code>ModuleConfig</code> object (which must * be pushed on to the evaluation stack before parsing begins). * </p> * * @exception ServletException * if a Digester cannot be configured * @since Struts 1.1 */ protected Digester initConfigDigester() throws ServletException {
// :FIXME: Where can ServletException be thrown?
// Do we have an existing instance? if (configDigester != null) { return (configDigester); }
// Create a new Digester instance with standard capabilities configDigester = new Digester(); configDigester.setNamespaceAware(true); configDigester.setValidating(false); configDigester.setUseContextClassLoader(true); configDigester.addRuleSet(new ConfigRuleSet());
for (int i = 0; i < registrations.length; i += 2) { URL url = this.getClass().getResource(registrations[i + 1]); if (url != null) { configDigester.register(registrations[i], url.toString()); } }
this.addRuleSets();
// Return the completely configured Digester instance return (configDigester); }
/** * <p> * Add any custom RuleSet instances to configDigester that have been * specified in the <code>rulesets</code> init parameter. * </p> * * @throws ServletException */ private void addRuleSets() throws ServletException {
String rulesets = null; if (rulesets == null) { rulesets = ""; }
rulesets = rulesets.trim(); String ruleset = null; while (rulesets.length() > 0) { int comma = rulesets.indexOf(","); if (comma < 0) { ruleset = rulesets.trim(); rulesets = ""; } else { ruleset = rulesets.substring(0, comma).trim(); rulesets = rulesets.substring(comma + 1).trim(); }
if (log.isDebugEnabled()) { log.debug("Configuring custom Digester Ruleset of type " + ruleset); }
try { RuleSet instance = (RuleSet) RequestUtils.applicationInstance(ruleset); this.configDigester.addRuleSet(instance); } catch (Exception e) { log.error("Exception configuring custom Digester RuleSet", e); throw new ServletException(e); } } }
/** * <p> * Parses one module config file. * </p> * * @param digester * Digester instance that does the parsing * @param path * The path to the config file to parse. * * @throws UnavailableException * if file cannot be read or parsed * @since Struts 1.2 */ protected void parseModuleConfigFile(Digester digester, String path) throws UnavailableException {
InputStream input = null; try { URL url = getServletContext().getResource(path);
// If the config isn't in the servlet context, try the class loader // which allows the config files to be stored in a jar if (url == null) { url = getClass().getResource(path); }
if (url == null) { String msg = internal.getMessage("configMissing", path); log.error(msg); throw new UnavailableException(msg); }
InputSource is = new InputSource(url.toExternalForm()); input = url.openStream(); is.setByteStream(input); digester.parse(is);
} catch (MalformedURLException e) { handleConfigException(path, e); } catch (IOException e) { handleConfigException(path, e); } catch (SAXException e) { handleConfigException(path, e); } finally { if (input != null) { try { input.close(); } catch (IOException e) { throw new UnavailableException(e.getMessage()); } } } }
/** * <p> * Simplifies exception handling in the <code>parseModuleConfigFile</code> * method. * <p> * * @param path * @param e * @throws UnavailableException * as a wrapper around Exception */ private void handleConfigException(String path, Exception e) throws UnavailableException {
String msg = internal.getMessage("configParse", path); log.error(msg, e); throw new UnavailableException(msg); }
/** * <p> * Initialize our internal MessageResources bundle. * </p> * * @exception ServletException * if we cannot initialize these resources */ protected void initInternal() throws ServletException {
// :FIXME: Document UnavailableException
try { internal = MessageResources.getMessageResources(internalName); } catch (MissingResourceException e) { log.error("Cannot load internal resources from '" + internalName + "'", e); throw new UnavailableException("Cannot load internal resources from '" + internalName + "'"); }
}
/** * @return */ private ServletContext getServletContext() { return (this.context); }
} 四.另外還有幾個Digester用來解析web.xml和struts-config.xml文件的類 /* * Created on 2005-9-6 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package kick.load.resource;
import java.util.ArrayList; import java.util.List;
public class WebApp { private List servlets = new ArrayList(); public void addServlet(Servlet servlet){ servlets.add(servlet); } /** * @return Returns the servlets. */ public List getServlets() { return servlets; } /** * @param servlets The servlets to set. */ public void setServlets(List servlets) { this.servlets = servlets; } public void print(){ for(int i = 0;i<servlets.size();i++){ ((Servlet)servlets.get(i)).print(); } } }
/* * Created on 2005-9-6 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package kick.load.resource;
import java.util.ArrayList; import java.util.List;
public class Servlet { private List initParams = new ArrayList(); public void addInitParams(InitParam i){ initParams.add(i); } public void print(){ for(int i = 0;i<initParams.size();i++){ ((InitParam)initParams.get(i)).print(); } } /** * @return Returns the initParams. */ public List getInitParams() { return initParams; } /** * @param initParams The initParams to set. */ public void setInitParams(List initParams) { this.initParams = initParams; } }
|
|