Struts source new version for Struts-1.3.8-src.zip (12-mar-2007 00:06)
Learn notes using Struts-1.3.5-src.zip source code,
Download Address: http://archive.apache.org/dist/struts/source/
1. In Web.xml, all *.do are delivered to Actionservlet through the following definition
<!--Standard Action Servlet Configuration (with debugging)-->
<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,
/web-inf/struts-config-wildcard.xml
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!--Standard Action Servlet Mapping-->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2. The following research on the source of struts, because the servlet set the Load-on-startup, so Tomcat will start loading Actionservlet, that is, will perform Actionservlet In the init () method, theinitialization implementation of Struts is implemented here .
Note: due to the lifecycle of the servlet for Web container loading and instantiating class /init () Initialization/service ( ) request processing/Destroy ( ) Four phases, and the Init () method executes only once after Tomcat is started, so if you want to see the execution of the Init () method in actionservlet in debug mode after Tomcat starts, you can put the above < Load-on-startup>2</load-on-startup> comments are available (though they are needed for real development).
3. Some constants are defined in Actionservlet , as follows:
The default struts configuration file is/web-inf/struts-config.xml
Protected String config = "/web-inf/struts-config.xml"; ②initother (); ⑤initmoduleconfig () ;
Default chain (defines an sequentially executed process) configuration file
protected String chainconfig = "Org/apache/struts/chain/chain-config.xml";
④initchain ();
protected digester configdigester = null; ⑤initmoduleconfig ();
If Convertnull is a True,java wrapper class (such as Java.lang.Integer), the initial value is null
protected Boolean convertnull = false; ②initother ();
protected messageresources internal = null; ①initinternal ();
The default Struts-core-1.3.5.jar resource file in the package is actionresources.properties
protected String InternalName = "Org.apache.struts.action.ActionResources";
①initinternal ();
Some document type definitions used to verify that the appropriate configuration file, such as Struts-config.xml, is correct
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",
"-//apache Software foundation//dtd Struts Configuration 1.3//en",
"/org/apache/struts/resources/struts-config_1_3.dtd",
"-//sun Microsystems, INC.//DTD Web application 2.3//en",
"/org/apache/struts/resources/web-app_2_3.dtd"
}; ③initservlet ();
protected String servletmapping = null; ③initservlet ();
protected String servletname = null; ③initservlet ();
4. The init () method in Actionservlet executes the following procedure
① Internal Resource file initialization of the actionresources.properties initinternal ();
protected messageresources internal = null; ①initinternal ();
protected String InternalName = "Org.apache.struts.action.ActionResources"; ①initinternal ();
The Initinternal method gets a messageresources object from the following
Internal = messageresources.getmessageresources (InternalName);
This resource file mainly includes the definition of some message information, which can refer to the Actionresources.properties file under Org.apache.struts.action.
The Getmessageresources method in the Messageresources.java,
if (defaultfactory = = null) {
Defaultfactory = Messageresourcesfactory. createfactory (); ⑴
}
Return defaultfactory. createresources (config); Incoming InternalName//⑵
⑴
Messageresourcesfactory. createfactory () The work done:
protected static transient Class clazz = null;
protected static String Factoryclass =
"Org.apache.struts.util. propertymessageresourcesfactory";
Clazz = requestutils.applicationclass(factoryclass);
and Requestutils.applicationclass through the classLoader load a
Org.apache.struts.util. propertymessageresourcesfactory
⑵
Defaultfactory. createresources (config) the work done by:
This.factory = Factory;
("Org.apache.struts.util.PropertyMessageResourcesFactory")
this.config = config; ("org.apache.struts.action.ActionResources")
This.returnnull = Returnnull; (true)
Propertymessageresourcesfactory extends Messageresourcesfactory
Returns a messageresources object
② calls Initother (), and loads Actionservlet initialization parameters from Web.xml, including Config/convertnull
Protected String config = "/web-inf/struts-config.xml"; ②initother ();
protected Boolean convertnull = false; ②initother ();
Get the "config" parameter in Web.xml
String value;
Value = Getservletconfig (). Getinitparameter ("config");
if (value!= null) {
Config = value;
}
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name> <!--get "config" parameter-->
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>convertNull</param-name> <!--get "convertnull" parameter-->
<param-value>true</param-value>
</init-param>
.......
</servlet>
Gets the value of the Convertnull (TRUE/YES/ON/Y/1)
Getservletconfig (). Getinitparameter ("Convertnull");
If the value of this parameter is True (TRUE/YES/ON/Y/1), the numeric type (bigdecimal/biginteger/boolean/byte/character/double/float/integer/long/ Short), the initial value of the Java wrapper class (such as Java.lang.Integer) is null, rather than 0. Default value [FALSE]
The method to make the initial value null is as follows:
Log all converters off
Convertutils.deregister ();
Registers a translator for the specified type Clazz converter
Convertutils.register (new Bigdecimalconverter (null), Bigdecimal.class);
Convertutils.register (new Bigintegerconverter (null), Biginteger.class);
.......
Note: Convertutils usage is as follows
deregister () and deregister (Java.lang.Class clazz)
Unregister the converter, which logs out all the converters, and the latter only logs out the converter register corresponding to Clazz (Converter Converter, Java.lang.Class clazz)
Registers the converter converter for the specified type Clazz. If Clazz already has a corresponding converter, then converter overwrites the original converter.
③ calls Initservlet (), loads the Actionservlet initialization parameters such as Servlet-name from the Web.xml, loads the DTD file and puts it into the hashmap cache, reads and resolves the contents of the Web.xml
Remember our servlet name
Getservletconfig (). Getservletname ();
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name> <!--get "config" parameter-->
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>convertNull</param-name> <!--get "convertnull" parameter-->
<param-value>true</param-value>
</init-param>
.......
</servlet>
Prepare a digester to scan the Web application Deployment descriptor
Digester digester = new Digester ();
Puts the current Actionservlet object into the parsing stack
Digester.push (this);
Indicates that you want to consider namespaces
Digester.setnamespaceaware (TRUE);
The default value [FALSE], the parser simply checks to see if the XML is well-formed (well formed)
Digester.setvalidating (FALSE);
Register our local copy of the DTDs so we can find
Struts can use the DTD in the Struts-core-1.3.5.jar package to handle the struts configuration file, which can be applied to environments that are not connected to the Internet
for (int i = 0; i < registrations.length i + + 2) {
URL url = this.getclass (). GetResource (Registrations[i + 1]);
if (URL!= null) {
Read the DTD file and put it into the HashMap cache
Digester.register (Registrations[i], url.tostring ());
}
}
/************************************************************
Some document type definitions used to verify that the appropriate configuration file, such as Struts-config.xml, is correct
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",
"-//apache Software foundation//dtd Struts Configuration 1.3//en",
"/org/apache/struts/resources/struts-config_1_3.dtd",
"-//sun Microsystems, INC.//DTD Web application 2.3//en",
"/org/apache/struts/resources/web-app_2_3.dtd"
}; ③initservlet ();
************************************************************/
Configure the processing rules that we need
At run time, Digester calls the addservletmapping() method in Actionservlet and passes in two parameters
Digester.addcallmethod ("web-app/servlet-mapping", "addservletmapping", 2);
Digester.addcallparam ("Web-app/servlet-mapping/servlet-name", 0);
Digester.addcallparam ("Web-app/servlet-mapping/url-pattern", 1);
Get
<servlet-mapping>
<servlet-name>action</servlet-name>
<Url-pattern>*.do</url-pattern>
</servlet-mapping>
/************************************************************
To determine whether the current servlet name is a running servlet name, and, if so, Url-pattern as a servletmapping
public void addservletmapping(String servletname, String urlpattern) {
if (Servletname = = null) {
Return
}
if (Servletname.equals (This.servletname)) {
if (log.isdebugenabled ()) {
Log.debug ("Process servletname=" + servletname
+ ", urlpattern=" + Urlpattern);
}
this.servletmapping = Urlpattern;
}
}
************************************************************/
Read the contents of the configuration file Web.xml
InputStream input = Getservletcontext (). getResourceAsStream ("/web-inf/web.xml");
If the/web-inf/web.xml file is not found, the error
if (input = = null) {
Log.error (Internal.getmessage ("Configwebxml"));
throw new Servletexception (Internal.getmessage ("Configwebxml"));
}
/************************************************************
The error message is defined in the Org\apache\struts\action\actionresources.properties
Configwebxml=the/web-inf/web.xml is not found.
************************************************************/
Parses the input stream file, triggering an event every time a node element is read
Digester.parse (input);
Note: Digester is a DOM-based SAX implementation class that is triggered by events that convert XML files to arbitrary Java objects and support the processing of arbitrary XML documents by rules. Originally a part of the Struts project, it was later assigned to the Commons subproject for its versatility.
Store servletmapping in ServletContext with property name Globals.servlet_key ("Org.apache.struts.action.SERVLET_MAPPING")
if (servletmapping!= null) {
Getservletcontext (). setattribute (globals.servlet_key,servletmapping);
}
④ call Initchain (); Read the command chain file initial value in Web.xml chainconfig
protected String chainconfig = "Org/apache/struts/chain/chain-config.xml";
④initchain ();
If there is no chainconfig parameter, the default "Org/apache/struts/chain/chain-config.xml" is used
String value;
Value = Getservletconfig (). Getinitparameter ("Chainconfig");
if (value!= null) {
Chainconfig = value;
}
Configparser parser = new Configparser ();
List urls = splitandresolvepaths (chainconfig);
URL resource; <