您的位置:首页 > 编程语言 > Java开发

深入浅出学习Struts框架(七):分析Struts框架实例2

2012-04-04 10:03 357 查看
在上一篇博客中讲到ActionServlet是如何初始化的以及web.xml的配置信息的具体作用。今天我们讲继续讲解ActionServlet在初始化的时候如何读取/WEB-INF/struts-config.xml信息到内存中,如何将这些从配置文件读取的信息以Actionmapping的形式展现在内存中的。

由于这部分内容是比较繁琐的,所以我对这部分的深入分析也不能太详细,但是具体实现流程我会讲清晰,如果有兴趣研究的童鞋们希望能够继续深入,研究的非常透彻的时候,可以给我发邮件或Q我。

下面来开始今天的博客,我们先从ActionServlet源代码的init方法开始。因为ActionServlet就是一个Servlet,它也是具有典型的那几个方法init、doget、dopost等方法。既然是初始化,那么我们就要看init方法。Init方法的源代码如下:

/**
* <p>Initialize this servlet.  Most of the processing has been factored into
* support methods so that you can overrideparticular functionality at a
* fairly granular level.</p>
*
* @exception ServletException if we cannotconfigure ourselves correctly
*/
publicvoidinit() throwsServletException {

// Wraps the entire initialization in a try/catch tobetter handle
// unexpected exceptions and errors to provide better feedback
// to the developer
try {
initInternal();
initOther();
initServlet();

getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);
initModuleConfigFactory();
// Initialize modules as needed
ModuleConfig moduleConfig =initModuleConfig("", config);
initModuleMessageResources(moduleConfig);
initModuleDataSources(moduleConfig);
initModulePlugIns(moduleConfig);
moduleConfig.freeze();

Enumeration names =getServletConfig().getInitParameterNames();
while (names.hasMoreElements()) {
String name = (String)names.nextElement();
if (!name.startsWith("config/")) {
continue;
}
String prefix =name.substring(6);
moduleConfig = initModuleConfig
(prefix,getServletConfig().getInitParameter(name));
initModuleMessageResources(moduleConfig);
initModuleDataSources(moduleConfig);
initModulePlugIns(moduleConfig);
moduleConfig.freeze();
}

this.initModulePrefixes(this.getServletContext());

this.destroyConfigDigester();
} catch (UnavailableException ex) {
throw ex;
} catch (Throwable t) {

// The follow error message is not retrieved from internal message
// resources as they may not have been able to have been
// initialized
log.error("Unable to initialize Struts ActionServlet due to an "
+ "unexpected exception or error thrown, so marking the "
+ "servlet as unavailable.  Mostlikely, this is due to an "
+ "incorrect or missing library dependency.", t);
throw new UnavailableException(t.getMessage());
}
}


在解释这段代码的流程和意思之前,有必要说一句,就是当我们在eclipse里面看代码的时候,尤其是看一段生疏的很长的代码的时候,希望能够经常使用Ctrl键(多余的不解释)。

下面开始讲解这段代码的流程和具体每一步的含义,如果有不正确的地方,希望指正。

首先映入眼帘的是initInternal()方法。这个方法的实现代码是:

代码段一:

/**
* <p>Initialize our internal MessageResourcesbundle.</p>
*
* @exception ServletException if we cannotinitialize these resources
*/
protectedvoidinitInternal() throwsServletException {

// :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+ "'");
}

}


代码段二:

/**
* Create and return an instance of <code>MessageResources</code> for the
* created by the default <code>MessageResourcesFactory</code>.
*
* @param config Configuration parameterfor this message bundle.
*/
publicsynchronizedstaticMessageResources getMessageResources(String config) {

if (defaultFactory == null) {
defaultFactory =MessageResourcesFactory.createFactory();
}

return defaultFactory.createResources(config);
}


代码段三:

/**
* Create and return a <code>MessageResourcesFactory</code> instance ofthe
* appropriate class, which can be used tocreate customized
* <code>MessageResources</code>instances.  If no such factory can be
* created, return <code>null</code> instead.
*/
publicstaticMessageResourcesFactory createFactory(){

// Construct a new instance of the specified factory class
try {
if (clazz == null)
clazz = RequestUtils.applicationClass(factoryClass);
MessageResourcesFactory factory =
(MessageResourcesFactory) clazz.newInstance();
return (factory);
} catch (Throwable t) {
LOG.error("MessageResourcesFactory.createFactory",t);
return (null);
}

}


这个方法的具体作用就是初始化MessageResources,具体实现是工厂模式,首先判断defaultFactory是否存在,不存在则创建工厂,

defaultFactory = MessageResourcesFactory.createFactory(),在通过工厂创建资源类defaultFactory.createResources(config);存在则直接创建资源类。

initOther()的方法,主要是初始化其它的配置,获取我们自己的struts-config配置文件的路径,
而它的默认路径就是web-inf/struts-config.xml,另外这个方法还会注册一些转换类的。具体源代码是:

/**
* <p>Initialize other global characteristics ofthe controller servlet.</p>
*
* @exception ServletException if we cannotinitialize these resources
*/
protectedvoidinitOther() throwsServletException {

String value = null;
value =getServletConfig().getInitParameter("config");
if (value != null) {
config = value;
}

// Backwards compatibility for form beans of Java wrapper classes
// Set to true for strict Struts 1.0 compatibility
value =getServletConfig().getInitParameter("convertNull");
if ("true".equalsIgnoreCase(value)
|| "yes".equalsIgnoreCase(value)
|| "on".equalsIgnoreCase(value)
|| "y".equalsIgnoreCase(value)
|| "1".equalsIgnoreCase(value)) {

convertNull = true;
}

if (convertNull) {
ConvertUtils.deregister();
ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
ConvertUtils.register(new BigIntegerConverter(null), BigInteger.class);
ConvertUtils.register(new BooleanConverter(null), Boolean.class);
ConvertUtils.register(new ByteConverter(null), Byte.class);
ConvertUtils.register(new CharacterConverter(null), Character.class);
ConvertUtils.register(new DoubleConverter(null), Double.class);
ConvertUtils.register(new FloatConverter(null), Float.class);
ConvertUtils.register(new IntegerConverter(null), Integer.class);
ConvertUtils.register(new LongConverter(null), Long.class);
ConvertUtils.register(new ShortConverter(null), Short.class);
}

}


initServlet()方法是利用digester读取web.xml文件并且放到servletContext中。具体实现源代码:

/**
* <p>Initialize the servlet mapping under which our controller servlet
* is being accessed.  This will be used in the <code>&html:form></code>
* tag to generate correct destination URLs for form submissions.</p>
*
* @throws ServletException if error happens while scanning web.xml
*/
protected void initServlet() throws ServletException {

// Remember our servlet name
this.servletName = getServletConfig().getServletName();

// Prepare a Digester to scan the web application deployment descriptor
Digester digester = new Digester();
digester.push(this);
digester.setNamespaceAware(true);
digester.setValidating(false);

// Register our local copy of the DTDs that we can find
for (int i = 0; i < registrations.length; i += 2) {
URL url = this.getClass().getResource(registrations[i+1]);
if (url != null) {
digester.register(registrations[i], url.toString());
}
}

// Configure the processing rules that we need
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);

// Process the web application deployment descriptor
if (log.isDebugEnabled()) {
log.debug("Scanning web.xml for controller servlet mapping");
}

InputStream input =
getServletContext().getResourceAsStream("/WEB-INF/web.xml");

if (input == null) {
log.error(internal.getMessage("configWebXml"));
throw new ServletException(internal.getMessage("configWebXml"));
}

try {
digester.parse(input);

} catch (IOException e) {
log.error(internal.getMessage("configWebXml"), e);
throw new ServletException(e);

} catch (SAXException e) {
log.error(internal.getMessage("configWebXml"), e);
throw new ServletException(e);

} finally {
try {
input.close();
} catch (IOException e) {
log.error(internal.getMessage("configWebXml"), e);
throw new ServletException(e);
}
}

// Record a servlet context attribute (if appropriate)
if (log.isDebugEnabled()) {
log.debug("Mapping for servlet '" + servletName + "' = '" +
servletMapping + "'");
}

if (servletMapping != null) {
getServletContext().setAttribute(Globals.SERVLET_KEY, servletMapping);
}

}


这篇博客先介绍这几个方法,随着这些方法具体作用和具体实现的慢慢的我们就知道init方法的作用,也慢慢的就解开了当我们实例化ActionServlet的时候,digester是如何读取/WEB-INF/struts-config.xml的文件内容,并且放到了ActionMapping中。敬请期待!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: