精灵王 
					 
				 
				
				
									- 注册日期2010-12-08
 
										- 发帖数640
 
										- QQ
 
										- 火币1103枚
 
										- 粉丝120
 
										- 关注75
 
									 
								
				
				
	
				
				
				
			 
		 | 
		
			
						
				
					阅读:5349回复:0
				 
				Struts 学习笔记2 -ActionServlet深入探讨-JSP教程,资料/其他
				
									
			 
						
			
				楼主# 
								更多
				
								发布于:2011-01-08 20:39				
			 
						
								
									 
				
				
								
								
				
					
				
				 
				
					  |  |   |    | java.lang.object   |   +--javax.servlet.genericservlet         |         +--javax.servlet.http.httpservlet               |               +--org.apache.struts.action.actionservlet
  struts提供了一个缺省版本的actionservlet类,你能继承这个类,覆盖其中的一些方法来达到你的特别处理的需要。actionservlet继承和javax.servlet.http.httpservlet,所以在本质上他和一个普通的servlet没有差别,你完万能把他当做一个servlet来看待,只是在其中完成的功能不同罢了。actionservlet主要完成如下功能:
  将一个来自客户端的uri映射到一个相应的action类
 - 如果是这个action类是第一次被调用,那么实例化一个并放入缓存
  - 如果在设置文件(struts-config.xml)中指定了相应的actionform,那么从request中抓取数据填充formbean
  - 调用这个action类的perform()方法,传入actionmapping的一个引用,对应的actionform、及由容器传给actionservlet的httpservletrequest、httpservletresponse对象。
  确省版本的actionservlet会从设置文件web.xml中读取如下初始化参数:
 - application
 应用使用的资源包(resources bundle)的基类
  - factory
 用于创建应用的messageresources对象的messageresourcesfactory的类名。确省是org.apache.struts.util.propertymessageresourcesfactory。
  - config
 struts的设置文件,确省是/web-inf/struts-config.xml。注意这儿是和应用context关联的相对路径。
  - content
 定义了确省的内容类型和编码格式,他会被自动地被设置到每个response中,如果jsp/servlet中没有明确的设置。确省是text/html。
  - debug
 调试信息的级别。默认为0,比当前级别高的调试信息会被log到日志文件中。
  - detail
 和debug的作用类似,只是这个detail是initmapping()时专用的。调试信息会被打印到system.out,而不是日志文件。
  - formbean
 actionformbean的实现类,确省为org.apache.struts.action.actionformbean
  - forward
 应用中使用的actionforward类,确省是org.apache.struts.action.actionforward。
  - locale
 指定了确省使用的locale对象。设为true,当得到一个session时,会自动在session中存储一个以action.locale_key标示的locale对象,如果session中还没有和action.locale_key绑定的locale对象。
  - mapping
 应用中使用的actionmapping类,确省是org.apache.struts.action.actionmapping。
  - multipartclass
 文件上传使用的mutipartrequesthandler的实现类。确省为org.apache.struts.upload.diskmultipartrequesthandler
  - nocache
 如果设为true,那么actionservlet会自动在每个到客户端的响应中添加nocache的html头,这样客户端就不会对应用中的页面进行缓存。确省为false
  - null
 如果设置为true,那么应用在得到一个未定义的message资源时,会返回null,而不是返回一个错误信息。确省是true。
  - maxfilesize
 文件上传的大小上限,确省为250m
  - buffersize
 文件上传时的缓冲区的大小,确省为4m
  - tempdir
 设置用于上传时的临时目录。工作目录会作为一个servlet环境(context)的属性提供。
  - validate
 are we using the new configuration file format?确省为true。
  - validating
  在解析设置xml文件是是否进行有效性的验证。确省为true
  actionservlet中应用了命令设计模式。
  一个servlet在由容器生成时,首先会调用init()方法进行初始化,在接到一个http请求时,调用相应的方法进行处理;比如get请求调用doget()方法,post请求调用dopost()方法。所以首先看看actionservlet的init()方法,你就会非常清晰为什么actionservlet能完成这些功能了。 init()在他的init()方法中,actionservlet依次调用如下protected的方法完成初始化:
 - 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中。
 -         string factory =getservletconfig().getinitparameter(“factory”);     
 -         string oldfacory = messageresourcesfactory.getfactoryclass(); 
 -         if (factory !=null) 
 -                 messageresourcesfactory.setfactoryclass(factory); 
 -         string value = getservletconfig().getinitparameter("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); 
 
  <li>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所有的<web-app/servlet-mapping>,寻找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); 
 
 
 
  - 更多黑客技术 黑客软件 计算机技术 编程技术 网站技术 qq技术 IT新闻 黑客基地 请访问 灯火安全联盟  灯火黑客 www.hack8888.com/bbs
  
  
  |  |    |  |   |   				 
							 
		 |