java action和servlet_ActionServlet深入探讨

initActions() -     大家可能还曾有这个疑问:Struts为什么可以找到一个请求URI对应的action类呢?答案就在这儿,ActionServlet有一个actions属性,类型为org.apache.struts.util.FastHashMap,用于存储以类的全名为key的已实例化的Action类。在init()时首先调用的就是initActions()方法,在这个方法中只是简单的清除map中的所有的名值对,

synchronized (actions) {

actions.setFast(false);

actions.clear();

actions.setFast(true);

}

首先把actions设为slow模式,这时对FastHashMap的访问是线程同步的,然后清除actions中的所有的已存在的名/值对,最后再把actions的模式设为fast。由于FastHashMap是struts在java.util.HashMap的基础上的一个扩展类,是为了适应多线程、并且对HashMap的访问大部分是只读的特殊环境的需要。大家知道java.util.HashMap是非线程安全的,所以HashMap一般适用于单线程环境下。org.apache.struts.FastHashMap就是继承于java.util.HashMap,在其中添加多线程的支持产生的。在fast模式下的工作方式是这样的:读取是非线程同步的;写入时首先克隆当前map,然后在这个克隆上做写入操做,完成后用这个修改后的克隆版本替换原来的map。那么在什么时候会把Actions类添加到这个map中呢?我们已经提到了struts是动态的生成Action类的实例的,在每次ActionServlet接收到一个GET或POST的HTTP请求时,会在这个map中查找对应的Action类的实例,如果不存在,那么就实例化一个,并放入map中。可见这个actions属性起到了对Action类实例的缓存的作用。

initInternal() -     初始化ActionServlet内部使用的资源包MessageResources,使用MessageResources.getMessageResources(internalName)得到    internalName为"org.apache.struts.action.ActionResources"对应的ActionResources.properties文件。这个资源包主要用于ActionServlet处理过程中的用到的提示信息,这儿不展开讨论。

initDebug() -     从web.xml中读取本应用的debug级别参数getServletConfig().getInitParameter("debug"),然后赋给debug属性。

initApplication()-    初始化应用资源包,并放置入ServletContext中。

if (factory !=null)

MessageResourcesFactory.setFactoryClass(factory);

"application");

MessageResourcesFactory factoryObject =

MessageResourcesFactory.createFactory();

application = factoryObject.createResources(value);

MessageResourcesFactory.setFactory(oldFactory);

getServletContext().setAttribute(Action.MESSAGES_KEY, application);

说明:文中引用的代码片断可能会省略了一些例外检查等非主线的内容,敬请注意。

首先从配置文件中读取factory参数,如果这个参数不为空,那么就在MessageResourcesFactory中使用这个指定的Factory类;否则,使用默认的工厂类org.apche.struts.util.PropertyMessageResourceFactory。然后调用MessageResourcesFactory的静态createFactory()方法,生成一个具体的MessageResourceFactory对象(注意:MessageResourcesFactory是抽象类)。这样就可以调用这个具体的MessageResourceFactory的createResource()方法得到配置文件(web.xml)中定义的资源文件了。

上面的application对象类型为MessageResources。在web.xml中在配置ActionServlet时可以指定一个特定的工厂类。不能直接MessageResourcesFactory的createResources()方法,因为这个方法是abstract的。创建factoryObject的过程如下:

MessageResourceFactory factoryObject=

MessageResourcesFactory.createFactory();

application = factoryObject.createResources(value);

initMapping() -    为应用初始化mapping信息ActionServlet有一个protected的属性:mapping,封装了一个ActionMapping的对象集合,以便于管理、查找ActionMapping。mappings是org.apache.struts.action.ActionMappings类的实例。主要有两个方法:addMapping(ActionMapping mapping)和findMapping(String path)。ActionMapping也是使用上面提到的org.apache.struts.util.FastHashMap类来存储所有的ActionMapping对象。

mappings.setServlet(this);

……

// Initialize the name of our ActionFormBean implementation class

value = getServletConfig().getInitParameter("formBean");

if (value != null)

formBeanClass = value;

// Initialize the name of our ActionForward implementation class

value = getServletConfig().getInitParameter("forward");

if (value != null)

forwardClass = value;

// Initialize the name of our ActionMapping implementation class

value = getServletConfig().getInitParameter("mapping");

if (value != null)

mappingClass = value;

在initMapping()中,首先链接mappings对象到本servlet实例。其实这句话的作用很简单,在ActionMappings中会有一个ActionServlet类型的属性,这个属性就界定了这个ActionMappings对象所属的ActionServlet。Struts的实现比较灵活,其中的ActionFormBean、ActionForward、ActionMapping类你完全可以使用自己实现的子类,来定制Struts的工作方式。上面的代码就从配置文件(web.xml)中读取formBean、forward、mapping参数,这些参数就是你定制的ActionFormBean、ActionForward、ActionMapping类名。

// Initialize the context-relative path to our configuration resources

value = getServletConfig().getInitParameter("config");

if (value != null)

config = value;

// Acquire an input stream to our configuration resource

InputStream input = getServletContext().getResourceAsStream(config);

Digester digester = null;

digester = initDigester(detail);

try {

formBeans.setFast(false);

forwards.setFast(false);

mappings.setFast(false);

digester.parse(input);

mappings.setFast(true);

forwards.setFast(true);

formBeans.setFast(true);

} catch (SAXException e) {

throw new ServletException

(internal.getMessage("configParse", config), e);

} finally {

input.close();

}

从web.xml读取Struts的配置文件的位置。使用org.apache.struts.digester.Digester解析config参数标示的配置文件,通常为“/WEB-INF/struts-config.xml”,解析出所有的data-source、form-bean、action-mapping、forward。从上面的程序片断看到,Digester仅仅调用了一个parse()方法,那么,Digester是怎样把解析struts-config.xml文件并把解析的结果form-bean等信息存储到属性变量formBeans等中的呢?你可以注意到在调用digester.parse(InputStream)之前,首先调用了initDigester()方法:

Digester digester = new Digester();

digester.push(this);

digester.addObjectCreate("struts-config/action-mappings/action",

mappingClass, "className");

digester.addSetProperties("struts-config/action-mappings/action");

digester.addSetNext("struts-config/action-mappings/action",

"addMapping",

"org.apache.struts.action.ActionMapping");

digester.addSetProperty

("struts-config/action-mappings/action/set-property",

"property", "value");

在这个方法中首先生成一个Digester对象,然后设置解析的规则和回调,如果你对XML、SAX不是很熟,这儿不必纠缠太深。要注意的是addSetNext()方法,设置了每一个要解析元素的Set Next回调方法,而这个方法就是由digester解析器的父提供的。上面的片断中的“addMapping”就是ActionServlet本身定义的一个方法,将由Digester回调。Digester就是籍此把解析出的每一个FormBean、ActionForward、ActionMapping等存储到属性变量formBeans、forwards、mappings等中的。

initUpload() -    初始化有关Upload的一些参数,比如:bufferSize、tempDir。

initDataSource() -取出在initMapping()中从配置文件中读取的每一个DataSource,设置LogWriter,如果为GenericDataSource的实例,则打开数据源。然后,把每个dataSource放入Context中。

dataSource.setLogWriter(scw);

((GenericDataSource)dataSource).open();

getServletContext().setAttribute(key,dataSource);

initOther() -        设置其它尚未初始化的的参数(content、locale、nocache),并发布formBeans、forwards、mappings到Context:

getServletContext().setAttribute(Action.FORM_BEANS_KEY, formBeans);

getServletContext().setAttribute(Action.FORWARDS_KEY, forwards);

getServletContext().setAttribute(Action.MAPPINGS_KEY, mappings);

initServlet() -    初始化Controller Servlet的Servlet Mapping。这儿也使用了Digester工具,扫描web.xml所有的,寻找servlet-name与当前Servlet相同的mapping,置入Context。代码如下;

Digester digester = new Digester();

digester.push(this);

digester.setDebug(debug);

digester.setValidating(validating);

digester.addCallMethod(“web-appservlet-mapping”,“addServletMapping”, 2);

digester.addCallParm(“web-appservlet-mappingservlet-name”, 0);

digester.addCallParm(“web-appservlet-mappingurl-pattern”, 1);

InputStream is = getServletContext().getResourceAsStream(“/WEB-INFweb.xml”);

digester.parse(is);

getServletContext().setAttribute(Action.SERVLET_KEY,servletMapping);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值