Struts as J2EE's MVC framework has achieved great success, and a few articles will be submitted to the structure of the Struts source program. The first Struts initialization Struts's core class is org.apache.struts.Action.ActionServlet, which will be initialized as servlet when Struts is used for the first time and stores Tomcat containers. Obviously, initialization will call the init method to initialize the corresponding data. INITINTERNAL () Method: Generate a MessageResources class by calling the MessageResources (InternalName) method, GetMessageResources is implemented by calling MessageResourcesFactory. Createresources (config). As for MessageResourcesFactory is an Abstract class, any inheritance is to implement the Createresources method from its class to generate the MessageResources object. MessageResourcesFactory entire program generated using the following techniques: MessageResourcesFactory.factoryClass = factoryClass; MessageResourcesFactory.clazz = null; will first be defined by the full name of a class factoryClass, then the class is generated by ClassLoader.loadClass (factoryClass) method, and assigned to clazz , Then generate an object by NewInstance. In this program, generating a MessageResources object is actually initializing the following properties: this.Factory = Factory; ("org.apache.struts.util.propertyMessageResourcesFactory) this.config = config; (" org.apache.struts. Action.ActionResources ") this.Returnnne = ReturnNun (true / false) The role of the MessageResources class is based on different locate to format the corresponding String. Or store the string you need to change into the array, then format it through the getMessage (Locale Locale, String Key, Object Args []) method. Then store the format String into the HashMap so that you can reuse later. The key here is useless locale.toString () "." KEY to use the LoadLocale method in PropertyMessageResources to read the initialization information of Resource. First it will detect this localkey-related Message if it has been initialized by a HashMap, if it is initialized, the method of detecting is LOCALES.GET (LocaleKey)! = NULL.
Then reads a document as follows: org / apache / struts / action / ActionResources_ (localKey) .properties, then proceed as follows: Properties props = new Properties (); ClassLoader classLoader = Thread.currentThread () getContextClassLoader (); is. = ClassLoader.getResourceAsStream (Name); ProPs.Load (IS); item name = props.keyset (). Iterator (); while (names.hasnext ()) {string key = (String) Names.next (); if (log.isTraceEnabled ()) {log.trace ( "Saving message key '" messageKey (localeKey, key));} messages.put (messageKey (localeKey, key), props.getProperty (key));} PropertyMessageResources is Look with Locale Locale, String Key, with Locale Locale, and Locale.toString (), then localekey = localekey.substring (0, underscore), then defaultlocale, then defaultlocale, then KEY. Finally, the structure of the Resource class is as follows: PropertyMessageResources Extends MessageResource Extends MessageResourcesFactory EXTENDS MessageResourcesFactory II, INITOTHER () Method: Get two parameters of CONFIG and DEBUG from the servlet, then initialize the ConvertUtIls object. Since the initialization of ConvertUTILS.DEREGISTER (), all Converter has an initial value, so Struts will set these initial values to null, ie, return NULL, not the initial value. The reason for using the ConvertUTILS class is that since Form is transmitted from Form, we have to convert them into corresponding types. Refer to several techniques: * public boolean isindexed () {if (type == null) {return (false); // Tips: Decision is an Array class method} Else if (Type.isaRray ()) { Return (True); // Tips 2: Determine whether Type is a parent class or parent interface, or is the same class with List // If list is another primitive Type class, then Type must be this class. I will only // returns true, otherwise it is False.
Note that long.type and long.class are different} else if (list.class.IsassileFrom (type)) {return (true);}}} * // ComponentType is stored in the Array class Class componentType element category = indexedProperty.getClass () getComponentType ();. // generates a new Array Object newArray = Array.newInstance (componentType, (index 1)); System.arraycopy (indexedProperty, 0, newArray, 0 , length); indexedProperty = newArray; set (name, indexedProperty); int newLength = Array.getLength (indexedProperty); for (int i = length; i It first uses the same method as generating MessageResourcesFactory: MessageResourcesFactory is an abstract class, each inheriting its class to implement the CreateModuleConfig (String Prefix) method. The default MessageResourcesFactory class used by this program is org.apache.struts.config.Impl.defaultModuleConfiguration, its CreateModuleConfig (String Prefix) method generates a ModuleConfigIMPL class. The ModuleConfigIMPL class is equivalent to a JavaBean that is used to store the configuration information required for a web module. Of course, a web module can have multiple moduleconfig, but the default is MODULECONIFG with a PREFIX length of 0. Each property is almost all consisting of HashMap, which describes whether the current ModuleConfig has been initialized by a Configured Boolean value, and the value is monitored when a property is stored. If it is initialized, it is necessary to change the attribute value in the inside, and the ILLEGALSTATEEXCEPTION ("Configuration IS Frozen") is reported, and now the properties of it are now simple to describe the following: * Protected hashmap actionconfigs: This hashmap is used to store the ActionConfig object. * Protected HashMap DataSource This hashmap is used to store DataSourceConfig objects. * Protected HashMap Exceptions This hashmap is used to store the ExceptionConfig object. * Protected HashMap Form Bemans This hashmap is used to store the FormBeanconfig object. * Protected HashMap Forwards This hashmap is used to store the ForwardConfig object. * Protected Hashmap MessageResources This hashmap is used to store the MessageResourceSconfig object. * Protected ArrayList Plugins This hashmap is used to store the PlugInConfig object. * Protected ControllerConfig ControllerConfig ControllerConfig Class * Protected Boolean Configured Symbol This moduleconfig is (true) No (false) configured. * Protected String Prefix is used to mark and distinguish the ModuleConfig class, and after initializing the corresponding resources in the use of the above CONFIG class, it is also different WEB modules to which they belong to this prefix. * Protected string anctions mappingclass = "org.apache.struts.Action.actionmapping" ActionMApping class name, default is org.apache.struts.Action.ActionMapping. The method of initializing ModuleConfig is as follows: first is to use GetServletConfig (). GetInitParameter ("mapping") to get the set ActionMApping class name and then generate a Digester by the initconfigster () method. Finally, use "," separate config, call ParsemoduleConfigfile (prefix, paths, config, digester, path) method for each piece. Note that this method actually only two parameters are meaningful: Path is the XML file we have to resolve, and config is used to initialize the completion to save to servletContext. If the formBeanconfig stored in ModuleConfig is a DYDAMIC type, call DynaActionformClass.createDynaActionformClass (FormBeanconfig) to initialize DynaActionformClass, and stored in Static HashMap of DynaActionformClass.Dynaclasses. The key in this is formbeanconfig.getName () moduleconfig.getprefix (). If the current ModuleConfig as the default ModuleConfig, it will call several methods as follows: defaultControllerConfig (config) defaultMessageResourcesConfig (config) defaultFormBeansConfig (config) defaultForwardsConfig (config) defaultMappingsConfig (config) after struts1.1, this exception will be waste: defaultControllerConfig (config) is ControllerConfig by getInitParameter (s), such as the method initializes several properties: bufferSize, content, locale (true / false), maxFileSize, nocache (true / false), multipartClass, tempDir. DefaultMessageResourcesconfig (config) initializes the following attributes for MessageResourcesConfig through the GetITParameter (S) method: Application, Factory, Null (True / false). Several other methods are to get different objects and store them accordingly into the servlet. Care as follows: actionformbeans => formbeanconfig, actionforwards => ForwardConfig, ActionMappings => ActionConfig. Six, initModuleMessageResources (ModuleConfig config) by MessageResourcesConfig ModuleConfig of objects stored in, one by one MessageResource initialization, initialization and then stored in the ServletContext MessageResources good, attributeName is MessageResourcesConfig.getKey () ModuleConfig.getPrefix (). Seven, initModuledataSources (ModuleConfig Config) initializes DataSource by stored in the DataSourceConfig object stored in ModuleConfig. The properties are then initialized for each dates.populate (DS, DSCS [i] .GetProperties ()) method for each Datesource. The initialized datesource is stored in servletContext, attributename is DataSourceConfig.getKey () ModuleConfig.getPrefix (). At the same time, it is also stored in Fasthashmap in the List Datasource, and Key is DataSourceConfig.getKey (). This will also be called the genericDataSource.Open () method based on whether the generated datesource object is the genericDataSource type. GenericDataSource is a very simple database connection pool. Its Open () method is used to initialize the connection pool, generate the minimum gnericconnection, where the open () method determines if the String Driver variable is NULL to determine if it has been initialized. It is necessary to carefully explain the getConnection () method, which first removes the genericConnection object from the connection pool, then check if it is linked, if you return, otherwise, continue to be removed while activeCount-1. If you are not taken, you will check if the currently used generconnection reaches the maximum value (active ", if not, call the CreateConnection () method sound into a new genericconnection, then check if it is a link, if you can return . The ReturnConnection (GenericConnection Conn method is by putting the genericconnection to the connection pool, then ActiveCount-1. This method uses the servletContextWriter class, and Datesource's log information is written through this class. The description of this class is as follows: it inherits from PrintWriter, while PrintWriter inherits from Writer. The Writer class is to call the Abstract method in the case of synchronization: Abstract Public Void Write (CHAR CBUF [], INT OFF, INT LEN), this method will be implemented by the caller according to the needs of the caller. PrintWriter first checks if there is a written object in this class (Writer class or its subclass) in this class via the EnSureOpen () method, if there is a Write method of this write object according to different situations (Out.write (... ).