﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Sung in Blog-文章分类-Ｓｔｒｕｔｓ</title><link>http://www.blogjava.net/qq13367612/category/4133.html</link><description>&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font class="subhead" size=3&gt;&lt;b&gt;一些技术文章 &amp; 一些生活杂碎&lt;/b&gt;&lt;/font&gt;</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 08:38:57 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 08:38:57 GMT</pubDate><ttl>60</ttl><item><title>深入Struts 1.1(分离struts配置文件)</title><link>http://www.blogjava.net/qq13367612/articles/18978.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 09 Nov 2005 06:16:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/18978.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/18978.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/18978.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/18978.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/18978.html</trackback:ping><description><![CDATA[<BLOCKQUOTE>作为基于MVC模式的Web应用最经典框架，Struts已经正式推出了1.1版本，该版本在以往版本的基础上，提供了许多激动人心的新功能。本文就将带你走进Struts 1.1去深入地了解这些功能。</BLOCKQUOTE>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">说明：</B>希望本文的读者能有一定的Struts使用基础。 </P>
<P><A name=1><SPAN class=atitle2>Model 2</SPAN></A><BR></P>
<P>Struts是基于Model 2之上的，而Model 2是经典的MVC（模型－视图－控制器）模型的Web应用变体，这个改变主要是由于网络应用的特性--HTTP协议的无状态性引起的。Model 2的目的和MVC一样，也是利用控制器来分离模型和视图，达到一种层间松散耦合的效果，提高系统灵活性、复用性和可维护性。在多数情况下，你可以将Model 2与MVC等同起来。</P>
<P>下图表示一个基于Java技术的典型网络应用，从中可以看出Model 2中的各个部分是如何对应于Java中各种现有技术的。</P>
<P><A name=N1004E><B></B></A><BR><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-struts1-1/image001.gif" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P>在利用Model 2之前，我们是把所有的表示逻辑和业务逻辑都集中在一起（比如大杂烩似的JSP），有时也称这种应用模式为Model 1，Model 1的主要缺点就是紧耦合，复用性差以及维护成本高。</P>
<P><A name=2><SPAN class=atitle2>Struts 1.1 和Model 2</SPAN></A><BR></P>
<P>既然Struts 1.1是基于Model 2之上，那它的底层机制也就是MVC，下面是Struts 1.1中的MVC实现示意图：</P>
<P><A name=N10068><B></B></A><BR><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-struts1-1/image002.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">图解说明：其中不同颜色代表MVC的不同部分：红色（控制器）、紫色（模型）和绿色（视图） </I>
<P>首先，控制器（ActionServlet）进行初始化工作，读取配置文件（struts-config.xml），为不同的Struts模块初始化相应的ModuleConfig对象。比如配置文件中的Action映射定义都保存在ActionConfig集合中。相应地有ControlConfig集合、FormBeanConfig集合、ForwardConfig集合和MessageResourcesConfig集合等。</P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"><B>提示：</B>模块是在Struts 1.1中新提出的概念，在稍后的内容中我们将详细介绍，你现在可以简单地把模块看作是一个子系统，它们共同组成整个应用，同时又各自独立。Struts 1.1中所有的处理都是在特定模块环境中进行的。模块的提出主要是为了解决Struts 1.0中单配置文件的问题。 </I></P>
<P>控制器接收HTTP请求，并从ActionConfig中找出对应于该请求的Action子类，如果没有对应的Action，控制器直接将请求转发给JSP或者静态页面。否则控制器将请求分发至具体Action类进行处理。</P>
<P>在控制器调用具体Action的execute方法之前，ActionForm对象将利用HTTP请求中的参数来填充自己（可选步骤，需要在配置文件中指定）。具体的ActionForm对象应该是ActionForm的子类对象，它其实就是一个JavaBean。此外，还可以在ActionForm类中调用validate方法来检查请求参数的合法性，并且可以返回一个包含所有错误信息的ActionErrors对象。如果执行成功，ActionForm自动将这些参数信息以JavaBean（一般称之为form bean）的方式保存在Servlet Context中，这样它们就可以被其它Action对象或者JSP调用。</P>
<P>Struts将这些ActionForm的配置信息都放在FormBeanConfig集合中，通过它们Struts能够知道针对某个客户请求是否需要创建相应的ActionForm实例。</P>
<P>Action很简单，一般只包含一个execute方法，它负责执行相应的业务逻辑，如果需要，它也进行相应的数据检查。执行完成之后，返回一个ActionForward对象，控制器通过该ActionForward对象来进行转发工作。我们主张将获取数据和执行业务逻辑的功能放到具体的JavaBean当中，而Action只负责完成与控制有关的功能。遵循该原则，所以在上图中我将Action对象归为控制器部分。</P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"><B>提示：</B>其实在Struts 1.1中，ActionMapping的作用完全可以由ActionConfig来替代，只不过由于它是公共API的一部分以及兼容性的问题得以保留。ActionMapping通过继承ActionConfig来获得与其一致的功能，你可以等同地看待它们。同理，其它例如ActionForward与ForwardConfig的关系也是如此。 </I></P>
<P>下图给出了客户端从发出请求到获得响应整个过程的图解说明。</P>
<P><A name=N1009B><B></B></A><BR><IMG alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-struts1-1/image003.jpg" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"> </P>
<P>下面我们就来详细地讨论一下其中的每个部分，在这之前，先来了解一下模块的概念。</P>
<P><A name=3><SPAN class=atitle2>模块</SPAN></A><BR></P>
<P>我们知道，在Struts 1.0中，我们只能在web.xml中为ActionServlet指定一个配置文件，这对于我们这些网上的教学例子来说当然没什么问题，但是在实际的应用开发过程中，可能会有些麻烦。因为许多开发人员都可能同时需要修改配置文件，但是配置文件只能同时被一个人修改，这样肯定会造成一定程度上的资源争夺，势必会影响开发效率和引起开发人员的抱怨。</P>
<P>在Struts 1.1中，为了解决这个并行开发的问题，提出了两种解决方案： 
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>多个配置文件的支持 
<LI>模块的支持 </LI></OL>
<P></P>
<P>支持多个配置文件，是指你能够为ActionServlet同时指定多个xml配置文件，文件之间以逗号分隔，比如Struts提供的MailReader演示例子中就采用该种方法。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
  &lt;!-- Action Servlet Configuration --&gt;
  &lt;servlet&gt;
	&lt;servlet-name&gt;action&lt;/servlet-name&gt;
	&lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt;
	&lt;init-param&gt;
		&lt;param-name&gt;config&lt;/param-name&gt;
		&lt;param-value&gt;/WEB-INF/struts-config.xml, /WEB-INF/struts-config-registration.xml&lt;/param-value&gt;
	&lt;/init-param&gt; 
	&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
  &lt;/servlet&gt;

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这种方法可以很好地解决修改冲突的问题，不同的开发人员可以在不同的配置文件中设置自己的Action、ActionForm等等（当然不是说每个开发人员都需要自己的配置文件，可以按照系统的功能模块进行划分）。但是，这里还是存在一个潜在的问题，就是可能不同的配置文件之间会产生冲突，因为在ActionServlet初始化的时候这几个文件最终还是需要合并到一起的。比如，在struts-config.xml中配置了一个名为success的&lt;forward&gt;，而在struts-config-registration.xml中也配置了一个同样的&lt;forward&gt;，那么执行起来就会产生冲突。</P>
<P>为了彻底解决这种冲突，Struts 1.1中引进了模块（Module）的概念。一个模块就是一个独立的子系统，你可以在其中进行任意所需的配置，同时又不必担心和其它的配置文件产生冲突。因为前面我们讲过，ActionServlet是将不同的模块信息保存在不同的ModuleConfig对象中的。要使用模块的功能，需要进行以下的准备工作：</P>
<P>1、为每个模块准备一个配置文件</P>
<P>2、配置web.xml文件，通知控制器</P>
<P>决定采用多个模块以后，你需要将这些信息告诉控制器，这需要在web.xml文件进行配置。下面是一个典型的多模块配置：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;init-param&gt;
	&lt;param-name&gt;config&lt;/param-name&gt;
	&lt;param-value&gt;/WEB-INF/struts-config.xml&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
	&lt;param-name&gt;config/customer&lt;/param-name&gt; 
	&lt;param-value&gt;/WEB-INF/struts-config-customer.xml&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt; 
	&lt;param-name&gt;config/order&lt;/param-name&gt;
	&lt;param-value&gt;/WEB-INF/struts-config-order.xml&lt;/param-value&gt;
&lt;/init-param&gt;

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>要配置多个模块，你需要在原有的一个&lt;init-param&gt;（在Struts 1.1中将其对应的模块称为缺省模块）的基础之上，增加模块对应的&lt;init-param&gt;。其中&lt;param-name&gt;表示为config/XXX的形式，其中XXX为对应的模块名，&lt;param-value&gt;中还是指定模块对应的配置文件。上面这个例子说明该应用有三个模块，分别是缺省模块、customer和order，它们分别对应不同的配置文件。</P>
<P>3、准备各个模块所需的ActionForm、Action和JSP等资源</P>
<P>但是要注意的是，模块的出现也同时带来了一个问题，即如何在不同模块间进行转发？有两种方法可以实现模块间的转发，一种就是在&lt;forward&gt;（全局或者本地）中定义，另外一种就是利用org.apache.struts.actions.SwitchAction。</P>
<P>下面就是一个全局的例子：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
    ... 
    &lt;struts-config&gt;
	... 
	&lt;global-forwards&gt;
		&lt;forward name="toModuleB"
			contextRelative="true"  
			path="/moduleB/index.do" 
		redirect="true"/&gt;   
	... 
	&lt;/global-forwards&gt;  
	...   
    &lt;/struts-config&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>可以看出，只需要在原有的path属性前加上模块名，同时将contextRelative属性置为true即可。此外，你也可以在&lt;action&gt;中定义一个类似的本地&lt;forward&gt;。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
  &lt;action-mappings&gt;
	&lt;!-- Action mapping for profile form --&gt;
	&lt;action path="/login" 
	type="com.ncu.test.LoginAction"  
	name="loginForm"     
	scope="request"      
	input="tile.userLogin"
	validate="true"&gt;     
	&lt;forward name="success" contextRelative="true" path="/moduleA/login.do"/&gt; 
	&lt;/action&gt; 
  &lt;/action-mappings&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>如果你已经处在其他模块，需要转回到缺省模块，那应该类似下面这样定义，即模块名为空。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;forward name="success" contextRelative="true" path="/login.do"/&gt;

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>此外，你也可以使用org.apache.struts.actions.SwitchAction，例如：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
    ...
    &lt;action-mappings&gt; 
	&lt;action path="/toModule" 
	type="org.apache.struts.actions.SwitchAction"/&gt;  
	...    
    &lt;/action-mappings&gt;  
    ...
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=4><SPAN class=atitle2>ActionServlet</SPAN></A><BR></P>
<P>我们首先来了解MVC中的控制器。在Struts 1.1中缺省采用ActionServlet类来充当控制器。当然如果ActionServlet不能满足你的需求，你也可以通过继承它来实现自己的类。这可以在/WEB-INF/web.xml中来具体指定。</P>
<P>要掌握ActionServlet，就必须了解它所扮演的角色。首先，ActionServlet表示MVC结构中的控制器部分，它需要完成控制器所需的前端控制及转发请求等职责。其次，ActionServlet被实现为一个专门处理HTTP请求的Servlet，它同时具有servlet的特点。在Struts 1.1中它主要完成以下功能： 
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>接收客户端请求 
<LI>根据客户端的URI将请求映射到一个相应的Action类 
<LI>从请求中获取数据填充Form Bean（如果需要） 
<LI>调用Action类的execute()方法获取数据或者执行业务逻辑 
<LI>选择正确的视图响应客户 </LI></UL>
<P></P>
<P>此外，ActionServlet还负责初始化和清除应用配置信息的任务。ActionServlet的初始化工作在init方法中完成，它可以分为两个部分：初始化ActionServlet自身的一些信息以及每个模块的配置信息。前者主要通过initInternal、initOther和initServlet三个方法来完成。</P>
<P>我们可以在/WEB-INF/web.xml中指定具体的控制器以及初始参数，由于版本的变化以及Struts 1.1中模块概念的引进，一些初始参数被废弃或者移入到/WEB-INF/struts-config.xml中定义。下面列出所有被废弃的参数，相应地在web.xml文件中也不鼓励再使用。</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>application 
<LI>bufferSize 
<LI>content 
<LI>debug 
<LI>factory 
<LI>formBean 
<LI>forward 
<LI>locale 
<LI>mapping 
<LI>maxFileSize 
<LI>multipartClass 
<LI>nocache 
<LI>null 
<LI>tempDir </LI></UL>
<P>ActionServlet根据不同的模块来初始化ModuleConfig类，并在其中以XXXconfig集合的方式保存该模块的各种配置信息，比如ActionConfig，FormBeanConfig等。</P>
<P>初始化工作完成之后，ActionServlet准备接收客户请求。针对每个请求，方法process(HttpServletRequest request, HttpServletResponse response)将被调用。该方法指定具体的模块，然后调用该模块的RequestProcessor的process方法。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
protected void process(HttpServletRequest request, 
		HttpServletResponse response) 
		throws IOException, ServletException {

	RequestUtils.selectModule(request, getServletContext());        
	getRequestProcessor(getModuleConfig(request)).process(request, response);
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>RequestProcessor包含了Struts控制器的所有处理逻辑，它调用不同的processXXX方法来完成不同的处理。下表列出其中几个主要的方法：</P>
<P>
<TABLE border=1>
<TBODY>
<TR>
<TD>方法</TD>
<TD>功能</TD></TR>
<TR>
<TD>processPath</TD>
<TD>获取客户端的请求路径</TD></TR>
<TR>
<TD>processMapping</TD>
<TD>利用路径来获得相应的ActionMapping</TD></TR>
<TR>
<TD>processActionForm</TD>
<TD>初始化ActionForm（如果需要）并存入正确的scope中</TD></TR>
<TR>
<TD>processActionCreate</TD>
<TD>初始化Action</TD></TR>
<TR>
<TD>processActionPerform</TD>
<TD>调用Action的execute方法</TD></TR>
<TR>
<TD>processForwardConfig</TD>
<TD>处理Action返回的ActionForward</TD></TR></TBODY></TABLE></P>
<P><A name=5><SPAN class=atitle2>ActionForm</SPAN></A><BR></P>
<P>对于ActionForm你可以从以下几个方面来理解它： 
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>ActionForm表示HTTP窗体中的数据，可以将其看作是模型和视图的中介，它负责保存视图中的数据供模型或者视图使用。Struts 1.1文档中把它比作HTTP和Action之间的防火墙，这体现了ActionForm具有的过滤保护的作用，只有通过ActionForm验证的数据才能够发送到Action处理。 
<LI>ActionForm是与一个或多个ActionConfig关联的JavaBean，在相应的action的execute方法被调用之前，ActionForm会自动利用请求参数来填充自己（初始化属性）。 
<LI>ActionForm是一个抽象类，你必须通过继承来实现自己的类。 </LI></OL>
<P></P>
<P>ActionForm首先利用属性的getter和setter方法来实现初始化，初始化完毕后，ActionForm的validate方法被调用，你可以在其中来检查请求参数的正确性和有效性，并且可以将错误信息以ActionErrors的形式返回到输入窗体。否则，ActionForm将被作为参数传给action的execute方法以供使用。</P>
<P>ActionForm bean的生命周期可以设置为session（缺省）和request，当设置为session时，记得在reset方法中将所有的属性重新设置为初始值。</P>
<P>由于ActionForm对应于HTTP窗体，所以随着页面的增多，你的ActionForm将会急速增加。而且可能同一类型页面字段将会在不同的ActionForm中出现，并且在每个ActionForm中都存在相同的验证代码。为了解决这个问题，你可以为整个应用实现一个ActionForm或者至少一个模块对应于一个ActionForm。</P>
<P>但是，聚合的代价就是复用性很差，而且难维护。针对这个问题，在Struts 1.1中提出了DynaActionForm的概念。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">DynaActionForm类</B> </P>
<P>DynaActionForm的目的就是减少ActionForm的数目，利用它你不必创建一个个具体的ActionForm类，而是在配置文件中配置出所需的虚拟ActionForm。例如，在下表中通过指定&lt;form-bean&gt;的type为"org.apache.struts.action.DynaActionForm"来创建一个动态的ActionForm--loginForm。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;form-beans&gt;
	&lt;form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm"&gt;  
		&lt;form-property name="actionClass" type="java.lang.String"/&gt;
		&lt;form-property name="username" type="java.lang.String"/&gt;
		&lt;form-property name="password" type="java.lang.String"/&gt; 
	&lt;/form-bean&gt; 
&lt;/form-beans&gt;

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>动态的ActionForm的使用方法跟普通的ActionForm相同，但是要注意一点。普通的ActionForm对象需要为每个属性提供getter和setter方法，以上面的例子而言，我们需要提供getUsername() 和 setUsername()方法取得和设置username属性，同样地有一对方法用于取得和设置password属性和actionClass属性。</P>
<P>如果使用DynaActionForm，它将属性保存在一个HashMap类对象中，同时提供相应的get(name) 和 set(name)方法，其中参数name是要访问的属性名。例如要访问DynaActionForm中username的值，可以采用类似的代码：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
String username = (String)form.get("username")；

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>由于值存放于一个HashMap对象，所以要记得对get()方法返回的Object对象做强制性类型转换。正是由于这点区别，如果你在Action中非常频繁地使用ActionForm对象，建议还是使用普通的ActionForm对象。</P>
<P>在Struts 1.1中，除了DynaActionForm以外，还提供了表单输入自动验证的功能，在包org.apache.struts.validator中提供了许多有用的类，其中最常见的就是DynaValidatorForm类。</P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">DynaValidatorForm类</B> </P>
<P>DynaValidatorForm是DynaActionForm的子类，它能够提供动态ActionForm和自动表单输入验证的功能。和使用DynaActionForm类似，你必须首先在配置文件中进行配置：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;form-beans&gt;
	&lt;form-bean name="loginForm" type="org.apache.struts.validator.DynaValidatorForm"&gt; 
		&lt;form-property name="actionClass" type="java.lang.String"/&gt;     
		&lt;form-property name="username" type="java.lang.String"/&gt; 
		&lt;form-property name="password" type="java.lang.String"/&gt;  
	&lt;/form-bean&gt;
&lt;/form-beans&gt;

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>同时要定义验证的插件：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
  &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
	&lt;set-property property="pathnames"  
	value="/WEB-INF/validator-rules.xml,  
	/WEB-INF/validation.xml"/&gt;
  &lt;/plug-in&gt;

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>其中的validator.xml和validator-rules.xml分别表示验证定义和验证规则的内容（可以合并在一起），比如针对上例中的DynaValidatorForm，我们有如下验证定义（validator.xml）：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
&lt;!DOCTYPE form-validation PUBLIC  
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"  
"http://jakarta.apache.org/commons/dtds/validator_1_0.dtd"&gt;
&lt;!--    Validation Rules    $Id: validation.xml--&gt;

&lt;form-validation&gt;  
&lt;!-- ========== Default Language Form Definitions ===================== --&gt;
&lt;formset&gt;  
	&lt;form name="loginForm"&gt;     
		&lt;field property="username" depends="required, minlength,maxlength"&gt; 
			&lt;arg0   key="prompt.username"/&gt;          
			&lt;arg1   key="${var:minlength}" name="minlength" resource="false"/&gt;       
			&lt;arg2   key="${var:maxlength}" name="maxlength" resource="false"/&gt;              
			&lt;var&gt;                
				&lt;var-name&gt;maxlength&lt;/var-name&gt;    
				&lt;var-value&gt;16&lt;/var-value&gt;         
			&lt;/var&gt;          
			&lt;var&gt;      
				&lt;var-name&gt;minlength&lt;/var-name&gt;     
				&lt;var-value&gt;3&lt;/var-value&gt;         
			&lt;/var&gt;       
		&lt;/field&gt;     
		&lt;field property="password" depends="required, minlength,maxlength" bundle="alternate"&gt;          
			&lt;arg0   key="prompt.password"/&gt;   
			&lt;arg1   key="${var:minlength}" name="minlength" resource="false"/&gt;          
			&lt;arg2   key="${var:maxlength}" name="maxlength" resource="false"/&gt;  
			&lt;var&gt;              
				&lt;var-name&gt;maxlength&lt;/var-name&gt;     
				&lt;var-value&gt;16&lt;/var-value&gt;        
			&lt;/var&gt;          
			&lt;var&gt;      
				&lt;var-name&gt;minlength&lt;/var-name&gt; 
				&lt;var-value&gt;3&lt;/var-value&gt;       
			&lt;/var&gt;        
		&lt;/field&gt;    
	&lt;/form&gt;   
&lt;/formset&gt;
&lt;/form-validation&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>从上述定义中，我们可以看到对于字段username有三项验证：required, minlength, maxlength，意思是该字段不能为空，而且长度在3和16之间。而validator-rules.xml文件则可以采用Struts提供的缺省文件。注意在&lt;form-bean&gt;中定义的form是如何与validation.xml中的form关联起来的。最后，要启动自动验证功能，还需要将Action配置的validate属性设置为true。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>

&lt;action path="/login"  
type="com.ncu.test.LoginAction"
name="loginForm"          
scope="request"         
input="tile.userLogin"validate="true"&gt;

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>此时，Struts将根据xml配置文件中的定义来检验表单输入，并将不符合要求的错误信息输出到页面。但是你可能会想：这个功能虽然好，可是什么检验都跑到服务器端执行，效率方面和用户易用性方面是不是有些问题？你可能会怀念起那简单的JavaScript客户端验证。</P>
<P>不用担心，在Struts 1.1中也支持JavaScript客户端验证。如果你选择了客户端验证，当某个表单被提交以后，Struts 1.1启动客户端验证，如果浏览器不支持JavaScript验证，则服务器端验证被启动，这种双重验证机制能够最大限度地满足各种开发者的需要。JavaScript验证代码也是在validator-rules.xml文件中定义的。要启动客户端验证，你必须在相应的JSP文件中做如下设置： 
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>为&lt;html:form&gt;增加onsubmit属性 
<LI>设置Javascript支持 </LI></OL>
<P></P>
<P>下表中列出了一JSP文件的示例代码，红字部分为Javascript验证所需代码。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&gt;
&lt;table bgcolor="#9AFF9A" cellspacing="0" cellpadding="10" border="1" width="100%"&gt;
	&lt;tr&gt;
	&lt;td&gt; 
	&lt;table cellspacing="0" cellpadding="0" border="0" width="100%"&gt; 
	&lt;tr bgcolor="#696969"&gt; 
		&lt;td align="center"&gt;     
		&lt;font color="#FFFFFF"&gt;Panel 3: Profile&lt;/font&gt;  
		&lt;/td&gt;
		&lt;/tr&gt; 
	&lt;tr&gt;  
		&lt;td&gt;&lt;br&gt; 
		&lt;html:errors/&gt;  
		&lt;html:form action="/login.do" focus="username"  onsubmit="return validateLoginForm(this);"&gt;  
		&lt;html:hidden property="actionClass"/&gt;   
		&lt;center&gt;      
		&lt;table&gt;      
			&lt;tr&gt;        
			&lt;td&gt;UserName:&lt;/td&gt;   
			&lt;td&gt;&lt;html:text property="username" size="20"/&gt;&lt;/td&gt; 
			&lt;/tr&gt; 
			&lt;tr&gt;  
			&lt;td&gt;Password:&lt;/td&gt;   
			&lt;td&gt;&lt;html:password property="password" size="20"/&gt;&lt;/td&gt;    
			&lt;/tr&gt;  
			&lt;tr&gt;  
			&lt;td colspan=2&gt;&lt;html:submit property="submitProperty" value="Submit"/&gt;&lt;/td&gt;     
		&lt;/table&gt;   
		&lt;/center&gt;  
		&lt;/html:form&gt; 
		&lt;html:javascript formName="loginForm" dynamicJavascript="true" staticJavascript="false"/&gt;  
	
	&lt;script language="Javascript1.1" src="staticJavascript.jsp"&gt;&lt;/script&gt;  
	&lt;/td&gt; 
	&lt;/tr&gt; 
	&lt;/table&gt;
	&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>其中onsubmit的值为"return validateLoginForm(this);"，它的语法为：</P>
<P>return validate + struts-config.xml中定义的form-bean名称 + (this);</P>
<P>staticJavascript.jsp的内容为：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;%@ page language="java" %&gt;
&lt;%-- set document type to Javascript (addresses a bug in Netscape according to a web resource --%&gt;
&lt;%@ page contentType="application/x-javascript" %&gt;
&lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&gt;
&lt;html:javascript dynamicJavascript="false" staticJavascript="true"/&gt;


</CODE></PRE></TD></TR></TBODY></TABLE>
<P>如果validator-rules.xml中定义的基本验证功能不能满足你的需求，你可以自己添加所需的验证类型。</P>
<P><A name=6><SPAN class=atitle2>Action</SPAN></A><BR></P>
<P>我们通过继承Action类来实现具体的执行类。具体Action类的功能一般都在execute（以前是perform方法）方法中完成，其中主要涉及到以下几个方面： 
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>辅助ActionForm进行一些表单数据的检查。 
<LI>执行必要的业务逻辑，比如存取数据库，调用实体bean等。 
<LI>更新服务器端的bean数据，后续对象中可能会用到这些数据，比如在JSP中利用bean:write来获得这些数据。 
<LI>根据处理结果决定程序的去处，并以ActionForward对象的形式返回给ActionServlet。 </LI></OL>
<P></P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/"><B>提示：</B>由于在Action和ActionForm中都可以实现验证方法，那么如何来安排它们之间的分工呢？一般来说，我们秉着MVC分离的原则，也就是视图级的验证工作放在ActionForm来完成，比如输入不能为空，email格式是否正确，利用ValidatorForm可以很轻松地完成这些工作。而与具体业务相关的验证则放入Action中，这样就可以获得最大ActionForm重用性的可能。 </I></P>
<P>前面我们提到过，我们主张将业务逻辑执行分离到单独的JavaBean中，而Action只负责错误处理和流程控制。而且考虑到重用性的原因，在执行业务逻辑的JavaBean中不要引用任何与Web应用相关的对象，比如HttpServletRequest，HttpServletResponse等对象，而应该将其转化为普通的Java对象。关于这一点，可以参考Petstore中WAF框架的实现思路。</P>
<P>此外，你可能还注意到execute与perform的一个区别：execute方法简单地掷出Exception异常，而perform方法则掷出ServletException和IOException异常。这不是说Struts 1.1在异常处理功能方面弱化了，而是为了配合Struts 1.1中一个很好的功能--宣称式异常处理机制。</P>
<P><A name=7><SPAN class=atitle2>宣称式异常处理</SPAN></A><BR></P>
<P>和EJB中的宣称式事务处理概念类似，宣称式异常处理其实就是可配置的异常处理，你可以在配置文件中指定由谁来处理Action类中掷出的某种异常。你可以按照以下步骤来完成该功能： 
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:dw="http://www.ibm.com/developerworks/">
<LI>实现org.apache.struts.action.ExceptionHandler的子类，覆盖execute方法，在该方法中处理异常并且返回一个ActionForward对象 
<LI>在配置文件中配置异常处理对象，你可以配置一个全局的处理类或者单独为每个Action配置处理类 </LI></OL>
<P></P>
<P>下表就定义了一个全局的处理类CustomizedExceptionHandler，它被用来处理所有的异常。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;global-exceptions&gt; 
&lt;exception 
	handler="com.yourcorp.CustomizedExceptionHandler" 
	key="global.error.message" 
	path="/error.jsp"    
	scope="request"    
	type="java.lang.Exception"/&gt;
&lt;/global-exceptions&gt;

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>其中具体的参数含义，可以参考ExceptionHandler.java源文件。</P>
<P><A name=8><SPAN class=atitle2>taglib</SPAN></A><BR></P>
<P>讲完了模型和控制器，接下来我们要涉及的是视图。视图的角色主要是由JSP来完成，从JSP的规范中可以看出，在视图层可以"折腾"的技术不是很多，主要的就是自定义标记库的应用。Struts 1.1在原有的四个标记库的基础上新增了两个标记库--Tiles和Nested。</P>
<P>其中Tiles除了替代Template的基本模板功能外，还增加了布局定义、虚拟页面定义和动态页面生成等功能。Tiles强大的模板功能能够使页面获得最大的重用性和灵活性，此外可以结合Tiles配置文件中的页面定义和Action的转发逻辑，即你可以将一个Action转发到一个在Tiles配置文件中定义的虚拟页面，从而减少页面的数量。比如，下表中的Action定义了一个转发路径，它的终点是tile.userMain，而后者是你在Tiles配置文件中定义的一个页面。</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;!-- ========== Action Mapping Definitions ============================== --&gt;
&lt;action-mappings&gt;  
&lt;!-- Action mapping for profile form --&gt; 
	&lt;action path="/login"   
		type="com.ncu.test.LoginAction"      
		name="loginForm"    
		scope="request"     
		input="tile.userLogin"
		validate="true"&gt;     
		&lt;forward name="success" path="tile.userMain"/&gt;   
	&lt;/action&gt; 
&lt;/action-mappings&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>Tiles配置文件：tiles-defs.xml</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;!DOCTYPE tiles-definitions PUBLIC 
"-//Apache Software Foundation//DTD Tiles Configuration//EN"       "http://jakarta.apache.org/struts/dtds/tiles-config.dtd"&gt;
&lt;tiles-definitions&gt;  
&lt;!-- =======================================================  --&gt; 
&lt;!-- Master definitions                                       --&gt;
&lt;!-- =======================================================  --&gt; 
&lt;!-- Page layout used as root for all pages. --&gt; 

&lt;definition name="rootLayout" path="/tiles-layouts/rootLayout.jsp"&gt; 
	&lt;put name="titleString" value="CHANGE-ME"/&gt;   
	&lt;put name="topMenu" value="/tiles-components/topMenu.jsp"/&gt; 
	&lt;put name="leftMenu" value="/tiles-components/panel1.jsp"/&gt;  
	&lt;put name="body" value="CHANGE-ME"/&gt;   
	&lt;put name="footer" value="/tiles-components/footer.jsp"/&gt; 
&lt;/definition&gt; 

&lt;!-- =======================================================  --&gt; 
&lt;!-- Page definitions 					--&gt;  
&lt;!-- =======================================================  --&gt; 

&lt;!-- User Login page --&gt; 
&lt;definition name="tile.userLogin" extends="rootLayout"&gt; 
	&lt;put name="titleString" value="User Login"/&gt;  
	&lt;put name="body" value="/src/userLogin.jsp"/&gt; 
&lt;/definition&gt;  
&lt;!-- User Main page --&gt; 
&lt;definition name="tile.userMain" extends="rootLayout"&gt; 
	&lt;put name="titleString" value="User Main"/&gt;  
	&lt;put name="body" value="/src/userMain.jsp"/&gt; 
&lt;/definition&gt;
&lt;/tiles-definitions&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>而Nested标记库的作用是让以上这些基本标记库能够嵌套使用，发挥更大的作用。</P>
<P><A name=9><SPAN class=atitle2>Commons Logging 接口</SPAN></A><BR></P>
<P>所谓的Commons Logging接口，是指将日志功能的使用与日志具体实现分开，通过配置文件来指定具体使用的日志实现。这样你就可以在Struts 1.1中通过统一的接口来使用日志功能，而不去管具体是利用的哪种日志实现，有点于类似JDBC的功能。Struts 1.1中支持的日志实现包括：Log4J，JDK Logging API， LogKit，NoOpLog和SimpleLog。</P>
<P>你可以按照如下的方式来使用Commons Logging接口（可以参照Struts源文中的许多类实现）：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
package com.foo;
// ...
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//...
	public class Foo {    
	// ...    
	private static Log log = LogFactory.getLog(Foo.class);
	// ...    
	public void setBar(Bar bar) {       
		if (log.isTraceEnabled()) {         
			log.trace("Setting bar to " + bar);   
		}      
	this.bar = bar;   
	}
// ...
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>而开启日志功能最简单的办法就是在WEB-INF/classes目录下添加以下两个文件：</P>
<P>commons-logging.properties文件：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
# Note: The Tiles framework now uses the commons-logging package to output different information or debug statements. 
Please refer to this package documentation to enable it. The simplest way to enable logging is to create two files in 
WEB-INF/classes:
# commons-logging.properties
# org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
# simplelog.properties
# # Logging detail level,
# # Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
#org.apache.commons.logging.simplelog.defaultlog=trace
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>simplelog.properties文件：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
# Logging detail level,
# Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
org.apache.commons.logging.simplelog.defaultlog=fatal

</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这里我们采用的日志实现是SimpleLog，你可以在simplelog.properties文件指定日志明细的级别：trace，debug，info，warn，error和fatal，从trace到fatal错误级别越来越高，同时输出的日志信息也越来越少。而这些级别是和org.apache.commons.logging.log接口中的方法一一对应的。这些级别是向后包含的，也就是前面的级别包含后面级别的信息。</P><img src ="http://www.blogjava.net/qq13367612/aggbug/18978.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-09 14:16 <a href="http://www.blogjava.net/qq13367612/articles/18978.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Validator检查你的表单</title><link>http://www.blogjava.net/qq13367612/articles/17646.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Tue, 01 Nov 2005 02:29:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17646.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17646.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17646.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17646.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17646.html</trackback:ping><description><![CDATA[<P><SPAN class=italicbodycopy><B><EM><FONT face=Arial size=2>用Validator（验证器）提供的丰富的内置验证方法简化Struts的开发过程。</FONT></EM></B></SPAN> </P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>Struts框架的一个主要好处是它提供了对接收到的表单数据进行验证的内置界面。如果有任何验证失败，则应用程序都会重新显示HTML表单，这样就可以改正无效的数据了。如果验证成功，则处理过程会继续进行。Struts框架的简单验证界面会减少与处理数据验证有关的令人头疼的事情，这样你就可以把精力集中到验证代码上，而不是放到捕获数据、重新显示不完整或无效数据的技巧上。</FONT></SPAN></P>
<P class=bodycopy>但是，Struts内置的验证界面也有缺点。例如，在整个应用程序中验证代码常常会大量重复，因为许多域需要相同的验证逻辑。对一些相似字段的验证逻辑进行任何修改都要求在几个地方修改代码，还要重新编译受影响的代码。为了解决这个问题并增强Struts验证界面的功能，作为Struts的第三方附加件创建了Validator框架。后来，Validator被集成到核心Struts代码库中，并从Struts中分离出来，现在它是一个独立的Jakarta Commons项目。虽然Validator是一个独立的框架，但它仍能与其他程序封装在一起后提供，并与Struts无缝集成。</P>
<P><SPAN class=parahead1><STRONG><FONT face=Arial>Validator概述</FONT></STRONG></SPAN> </P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>没有Validator，你就不得不编写验证表单数据所需的全部代码，并把它放入Form Bean对象的validate( )方法中。对于想在其上进行数据验证的每个Form Bean域来说，都需要编写逻辑代码来实现验证。此外，你还必须编写代码来存储验证失败时的出错消息。 </FONT></SPAN></P>
<P class=bodycopy>有了Validator，你就不必在Form Bean中编写用于验证或存储错误消息的任何代码。相反，Form Bean提供了Validator的一个ActionForm子类，它提供验证或存储错误消息的功能。 </P>
<P class=bodycopy>可把Validator框架作为一个可用于Form Bean验证的可插入的验证例行程序系统来进行安装。每个验证例行程序都只是一个Java方法，负责执行特定类型的验证任务，验证可能通过，也可能失败。 默认情况下，Validator与几个有用的验证例行程序封装在一起来提供，这些例行程序能满足大多数情况下的验证要求。但是，如果Validator框架没有提供你需要的验证例行程序，那么你可以自己创建定制的验证例行程序，并将它插入到该框架中。此外，Validator还支持服务器端和客户端（JavaScript）的验证，而Form Bean只提供服务器端验证界面。 </P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>Validator使用两个XML配置文件来分别确定安装哪个验证例行程序和如何将它们应用于给定的应用程序。第一个配置文件validator-rules.xml说明应该被插入到框架中的验证例行程序，并提供每个验证的逻辑的名称。validator-rules.xml文件还定义了每个验证例行程序的客户端JavaScript代码。可以配置Validator让它把这个JavaScript代码发送到浏览器上，这样验证就可以在客户端和服务器端进行了。 </FONT></SPAN></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>第二个配置文件validation.xml确定哪个验证例行程序应用到哪个Form Bean。文件中的定义使用struts-config.xml文件给出的Form Bean的逻辑名称以及validator-rules.xml文件给出的验证例行程序的逻辑名称，以便把二者关联起来。</FONT></SPAN> </P>
<P class=bodycopy>使用Validator框架包括启用Validator插件、配置Validator的两个配置文件，以及创建提供Validator的ActionForm子类的Form Beans。下面详细解释如何配置和使用Validator。 </P>
<P><SPAN class=parahead1><STRONG><FONT face=Arial>启用Validator插件</FONT></STRONG></SPAN> </P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>虽然Validator框架是与Struts封装在一起提供的，但在默认状况下Validator并不被启用。为了启用Validator，要向你的应用程序的struts-config.xml文件中添加下面的插件定义。 </FONT></SPAN></P>
<P><FONT face=Arial size=2></FONT><PRE>&lt;!-- Validator Configuration --&gt;
&lt;plug-in className="org.apache.struts
.validator.ValidatorPlugIn"&gt;
  &lt;set-property property="pathnames"
               value="/WEB-INF/
  validator-rules.xml, /WEB-INF/

  validation.xml"/&gt;
&lt;/plug-in&gt;
</PRE>
<P></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>该定义告诉Struts为你的应用程序加载并初始化Validator插件。在初始化时，该插件装入由路径名属性指定的、用逗号分隔的Validator配置文件清单。每个配置文件的路径应该用与Web应用程序的相关的路径来指定，如前面的例子所示。 </FONT></SPAN></P>
<P class=bodycopy>请注意，你的应用程序的struts-config.xml文件必须与Struts Configuration Document Type Definition（Struts配置文档类型定义，DTD）一致，后者规定文件中元素出现的顺序。所以，你必须把Validator插件定义放到该文件的适当位置。确保文件中元素适当排列的最简便方法就是使用诸如Struts Console的工具，它自动格式化你的配置文件，以便与DTD保持一致。</P>
<P><SPAN class=parahead1><STRONG><FONT face=Arial>配置validator-rules.xml </FONT></STRONG></SPAN></P>
<P class=bodycopy>Validator框架可以设置为可插入系统，其验证例行程序仅仅是插入到该系统中执行具体验证的Java方法。validator-rules.xml文件说明性地插入Validator用于执行验证的验证例行程序中。Struts示例应用程序带有这个文件的预配置拷贝。在大多数情况下，你不必修改这个预配置拷贝，除非你要向该框架中添加自己定制的验证。</P>
<P><SPAN class=bodycopy><A href="http://www.oracle.com/global/cn/oramag/oracle/04-jan/o14dev_struts_l1.html" target=_blank><SPAN class=bodylink><FONT face=Arial color=#000000 size=2>清单1</FONT></SPAN></A><FONT face=Arial size=2> 是一个示例validator-rules.xml文件，说明如何将验证例行程序插入到Validator中。validator-rules.xml文件中的每个验证例行程序都有自己的定义，它用validator标记声明，利用name属性为该验证例行程序指定逻辑名，并指定该例行程序的类和方法。该例行程序的逻辑名称供该文件中的其他例行程序以及validation.xml文件中的验证定义用于引用该例行程序。</FONT></SPAN> </P>
<P class=bodycopy>请注意，validator标记放在javascript的标记中，javascript标记用于定义客户端JavaScript代码，以便在客户端执行与服务器端相同的验证。 </P>
<P class=parahead1>提供的验证程序</P>
<P class=bodycopy>默认情况下，Validator中包括几个基本验证例行程序，你可以用它们来处理大多数验证问题。这些例行程序具有逻辑名称，如required（用于输入要求的值）、CreditCard（用于输入信用卡号码值）、email（用于输入电子邮件地址值），等等。</P>
<P class=parahead1>创建Form Bean</P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>为了使用Validator，你的应用程序的Form Bean必须归到Validator的ActionForm的某一子类，而不是ActionForm本身。Validator的ActionForm子类提供了ActionForm的validate( )方法（它嵌入到Validator框架中）的实施过程。你不必从头编写验证代码并把它投入validate( )方法中，相反，可以完全忽略该方法，因为Validator为你提供了验证代码。 </FONT></SPAN></P>
<P class=bodycopy>与Struts提供的核心功能相类似，Validator提供给你两种可供选择的方法来创建Form Bean。 你可以选择的第一种方法就是像下面这样创建一个特定的Form Bean对象：</P>
<P><PRE>package com.jamesholmes.minihr;

import org.apache.struts.validator
.ValidatorForm;


public class LogonForm extends ValidatorForm {
  private String username;
  private String password;
  
  public String getUsername() {
    return username;
  }
  
  public void setUsername(String 
username) {
    this.username = username;
  }


  public String getPassword() {
    return password;
  }
public void setPassword(String 
password) {
    this.password = password;
  }
}
</PRE><SPAN class=bodycopy>
<P></P></SPAN>
<P class=bodycopy>这个类与你不是用Validator所创建的类相似，但它提供ValidatorForm而不是ActionForm。这个类也不提供ActionForm的空reset( )和validate( )方法的实施过程，因为ValidatorForm提供了相应过程。</P>
<P class=bodycopy>在struts-config.xml文件中配置这个特定Form Bean的方法与配置正则Form Bean的方法相同：</P>
<P><PRE>&lt;form-beans&gt;
  &lt;form-bean name="logonForm"
            type="com.jamesholmes
  .minihr.LogonForm"/&gt;
&lt;/form-beans&gt;
</PRE>
<P></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>用表单标记的name属性给特定Form Bean指定的逻辑名是在定义validation.xml文件中的验证时所使用的名称，如下所示：</FONT></SPAN></P>
<P><FONT face=Arial size=2></FONT><PRE>&lt;!DOCTYPE form-validation 
PUBLIC "-//Apache Software Foundation//
       DTD Commons Validator Rules
       Configuration 1.0//EN"
       "http://jakarta.apache.org/
      commons/dtds/validator_1_0.dtd"&gt;


&lt;form-validation&gt;
  &lt;formset&gt;
    &lt;form name="logonForm"&gt;
      &lt;field property="username" 
            depends="required"&gt;
        &lt;arg0 key="prompt.username"/&gt;
      &lt;/field&gt;
    &lt;/form&gt;
  &lt;/formset&gt;
&lt;/form-validation&gt;
</PRE>
<P></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>Validator使用该表单标记的name属性的值将验证定义与要应用这些定义的Form Bean的名称相匹配。 </FONT></SPAN></P>
<P class=bodycopy>创建Form Bean时可以选择的第二种方法是在struts-config.xml文件中定义一个动态Form Bean，如下所示：</P>
<P><PRE>&lt;form-beans&gt;
  &lt;form-bean name="logonForm"
            type="org.apache
.struts.validator.DynaValidatorForm"&gt;
    &lt;form-property name="username"
            type="java.lang.String"/&gt;
    &lt;form-property name="password"
            type="java.lang.String"/&gt;
  &lt;/form-bean&gt;
&lt;/form-beans&gt;
</PRE>
<P></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>动态Form Bean不要求创建特定的Form Bean对象；相反，要定义Form Bean应该具有的属性和类型，而Struts为你动态创建Form Bean。 Validator允许你使用这个概念，就像在核心Struts中使用这个概念一样。与使用Validator的惟一区别就是要指定Form Bean是org.apache.struts.validator.DynaValidatorForm类型，而不是org.apache.struts.action.DynaActionForm类型。</FONT></SPAN></P>
<P class=bodycopy>分配给动态Form Bean的逻辑名是在定义validation.xml文件中的验证时使用的名称。Validator使用与之相匹配的名称将这些验证与Form Bean联系在一起。 </P>
<P class=bodycopy>除了创建Form Bean的这两种标准方法之外，Validator还提供了一个高级特性，用于将多个验证定义与一个Form Bean定义联系起来。当你使用基于validatorForm或基于DynaValidatorForm的Form Bean时，Validator使用struts-config.xml文件中的Form Bean的逻辑名称，将Form Bean映射到validation.xml文件中的验证定义。这种机制在大多数情况下非常有用，但在某些时候，Form Bean要在多个操作中共享。 一个操作可能使用Form Bean的所有域（fields），而另一个操作可能只使用这些域的一个子集。因为验证定义被连接到Form Bean，所以只使用域的一个子集的操作就无法绕过对未使用域的验证。当验证Form Bean时，就会对未使用的域生成错误消息，因为Validator无从知道不去验证未使用的域，它只是简单地把它们看作缺失或无效。</P>
<P class=bodycopy>为了解决这个问题，Validator提供了两个附加的ActionForm子类，它使你能够将验证与操作相关联，而不是与Form Bean相关联。这样你就可以根据哪个操作正在使用Form Bean来指定把哪些验证用于该Form Bean了。对于特定的Form Bean，你要像下面这样声明org.apache.struts.validator.ValidatorActionForm子类：</P>
<P><PRE>public class AddressForm extends ValidatorActionForm {
  ...
}
</PRE>
<P></P>
<P class=bodycopy>对于动态Form Bean，在struts-config.xml文件中为Form Bean定义指定org.apache.struts.validator.DynaValidatorActionForm的类型，如下所示： </P>
<P><PRE>&lt;form-bean name="addressForm"
          type="org.apache.struts
.validator.DynaValidatorActionForm"&gt;
  ...
&lt;/form-bean&gt;
</PRE>
<P></P>
<P class=bodycopy>在validation.xml文件中，把一组验证映射到一个操作路径，而不是映射到Form Bean名，因为如果你定义了Create Address和Edit Address两个操作（它们使用同一个Form Bean），那么每个操作都会有一个惟一的操作名，如下所示： </P>
<P><PRE>&lt;action-mappings&gt;
  &lt;action path="/createAddress"
         type="com.jamesholmes
  .minihr.CreateAddressAction"
         name="addressForm"/&gt;
  &lt;action path="/editAddress"
         type="com.jamesholmes
  .minihr.EditAddressAction"
         name="addressForm"/&gt;

&lt;/action-mappings&gt;
</PRE>
<P></P>
<P class=bodycopy>下面的validation.xml文件片断显示了两组验证，它们用于同一个Form Bean，但却有不同的操作路径：</P>
<P><PRE>&lt;formset&gt;
  &lt;form name="/createAddress"&gt;
    &lt;field property="city"
          depends="required"&gt;
      &lt;arg0 key="prompt.city"/&gt;
    &lt;/field&gt;
  &lt;/form&gt;
  &lt;form name="/editAddress"&gt;
    &lt;field property="state"
          depends="required"&gt;
      &lt;arg0 key="prompt.state"/&gt;
    &lt;/field&gt;
  &lt;/form&gt;
&lt;/formset&gt;
</PRE>
<P></P>
<P class=bodycopy>因为Form Bean要么属于ValidatorActionForm子类，要么属于DynaValidatorActionForm子类，所以Validator知道用一个操作路径代替Form Bean的逻辑名称来找出用于Form Bean的验证。</P>
<P class=parahead1>配置validation.xml文件</P>
<P class=bodycopy>validation.xml文件用于声明将应用到Form Beans的一组验证。要验证的每个Form Bean在这个文件中都有自己的定义。在这个定义中，指定要应用到该Form Bean的各域的验证。下面是一个validation.xml文件的例子，说明如何定义验证：</P>
<P><PRE>&lt;!DOCTYPE form-validation 
PUBLIC "-//Apache Software Foundation//
       DTD Commons Validator Rules
       Configuration 1.0//EN"
       "http://jakarta.apache.org/
      commons/dtds/validator_1_0.dtd"&gt;

&lt;form-validation&gt;
  &lt;formset&gt;
    &lt;form name="logonForm"&gt;
      &lt;field property="username"
            depends="required"&gt;
        &lt;arg0 key="prompt.username"/&gt;

      &lt;/field&gt;
      &lt;field property="password"
            depends="required"&gt;
        &lt;arg0 key="prompt.password"/&gt;
      &lt;/field&gt;
    &lt;/form&gt;
  &lt;/formset&gt;
&lt;/form-validation&gt;
</PRE>
<P></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>validation.xml文件的第一个元素是form-validation。这个元素是该文件的主元素，而且只定义一次。在form-validation元素内定义form-set元素，它包括多个表单元素。一般来说，在文件中只定义一个form-set元素，但是如果要将验证国际化，那就要在每个地方单独使用一个form-set元素。</FONT></SPAN></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>每个表单元素使用name属性将名称与其所包含的域验证集关联起来。Validator使用这个逻辑名称将这些验证映射到在struts-config.xml文件中定义的一个Form Bean。根据要验证的Form Bean的类型，Validator力求将该名称与Form Bean的逻辑名称或操作路径相匹配。在表单元素内，field元素定义要应用到Form Bean的特定域的验证。field元素的property属性对应于特定Form Bean中的域名。depends属性利用validator-rules.xml文件指定验证例行程序的逻辑名称，这些例行程序将应用到域验证中。</FONT></SPAN> </P>
<P class=parahead1>配置ApplicationResources.properties </P>
<P class=bodycopy>Validator使用Struts的资源绑定（Resource Bundle）机制将错误消息具体化。不用在框架中对错误消息进行硬编码，Validator使你能在ApplicationResources.properties文件中为一个消息指定一个键值，如果验证失败则将返回该键值。validator-rules.xml文件中的每个验证例行程序都用validator标记的msg属性指定错误消息的键值，如下所示： </P>
<P><PRE>&lt;validator name="required"
          classname="org.apache

.struts.validator.FieldChecks"
          method="validateRequired"
          methodParams="java.lang
.Object, org.apache.commons.validator
.ValidatorAction, org.apache.commons
.validator.Field, org.apache.struts
.action.ActionErrors, javax.servlet
.http.HttpServletRequest"
          msg="errors.required"&gt;
</PRE>
<P></P>
<P class=bodycopy>如果在验证例行程序运行时验证失败，则返回与msg属性指定的键值对应的消息。</P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>下面的片段显示来自ApplicationResources.properties文件的验证出错时的默认消息集，它们由Struts示例应用程序提供。每个消息的键值对应于每个由validator-rules.xml文件中的验证例行程序所指定的消息，它们由Struts示例应用程序提供。</FONT></SPAN> </P>
<P><PRE># Error messages for Validator framework validations
errors.required={0} is required.
errors.minlength={0} cannot be less than {1} characters.
errors.maxlength={0} cannot be greater than {2} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.0.   errors.float={0} must be a float.

errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
</PRE>
<P></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>请注意，每条消息都有占位符，形式为{0}、{1}或{2}。在运行期间，占位符被另一个值代替，如所验证的域的名称。这一特性特别有用，它使你能够创建可被几个不同的域重复使用的通用验证错误消息。 </FONT></SPAN></P>
<P class=bodycopy>例如，下面给出required验证的错误消息errors.required： </P>
<P><PRE>errors.required={0} is required.
</PRE>
<P></P>
<P class=bodycopy>当你使用validation.xml文件中的该required验证时，必须定义用于替换该错误消息中的{0}的值，如下所示：</P>
<P><PRE>&lt;form name="auctionForm"&gt;
  &lt;field property="bid" depends="required"&gt;
    &lt;arg0 key="prompt.bid"/&gt;
  &lt;/field&gt;
&lt;/form&gt;
</PRE>
<P></P>
<P class=bodycopy>错误消息最多可以有4个占位符：{0}和{3}。这些占位符分别称为arg0到arg3，你可以通过使用arg0~arg3标记来指定它们。在上面的例子中，arg0标记指定了用于替换{0}占位符的值。该标记的key属性指定来自ApplicationResources.properties文件的一个消息键值，它的值用于替换占位符，如下所示： </P>
<P><PRE>prompt.bid=Auction Bid
</PRE>
<P></P>
<P class=bodycopy>使用消息键值代替占位符的值，这一方法使你不必在validation.xml文件中对替换值反复硬编码。但是，如果你不想使用Resource Bundle的键值/值机制来指定占位符的值，则可以使用arg0标记的如下语法显式地指定占位符的值：</P>
<P><PRE>&lt;arg0 key="Auction Bid" resource="false"/&gt;
</PRE>
<P></P>
<P class=bodycopy>在这个例子中，resource属性的值设为false，以便通知Validator要把该key属性指定的值作为占位符的值，而不要作为ApplicationResources.properties文件中消息的一个键值。</P>
<P class=parahead1>启用客户端验证 </P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>Validator除了提供了简化服务器端表单数据验证过程的框架外，它还提供了执行客户端验证时易于使用的方法。在validator-rules.xml文件中定义的每一个验证例行程序都可以随意指定JavaScript代码，这些代码可以在浏览器（客户端上的）中运行，从而执行与服务器端进行的验证相同的验证过程。在客户端进行验证时，除非所有表单都通过验证，否则这些表单不允许被提交。</FONT></SPAN></P>
<P><SPAN class=bodycopy><FONT face=Arial size=2>为了启用客户端验证，必须在每个需要验证的JSP中放上Struts HTML Tag Library（标记库）的javascript标记，如下所示：</FONT></SPAN> </P>
<P><PRE>&lt;html:javascript formName="logonForm"/&gt;
</PRE>
<P></P>
<P class=bodycopy>javascript标记要求使用formName属性来为想要对其执行验证的表单指定validation.xml文件中给出的表单定义名，如下所示： </P>
<P><PRE>&lt;form name="logonForm"&gt;
  &lt;field property="username"
        depends="required"&gt;
    &lt;arg0 key="prompt.username"/&gt;
  &lt;/field&gt;
  &lt;field property="password"
        depends="required"&gt;
    &lt;arg0 key="prompt.password"/&gt;
  &lt;/field&gt;
&lt;/form&gt;
</PRE>
<P></P>
<P class=bodycopy>为表单定义指定的服务器端的所有验证都将在客户端运行。由于客户端验证用JavaScript执行，所以可以有多种方法不去执行它。要确保验证过程总是能运行，不论你是否选择启用了客户端验证，Validator都在服务器端执行这些验证。</P>
<P><SPAN class=parahead1><STRONG><FONT face=Arial>结论</FONT></STRONG></SPAN> </P>
<P class=bodycopy>Validator框架针对表单数据的验证提供了可配置的系统，从而为核心Struts框架添加了很多有价值的功能。通过把Validator框架用于你的应用程序，你可以节约时间并简化Struts应用程序的开发过程。 </P><img src ="http://www.blogjava.net/qq13367612/aggbug/17646.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-11-01 10:29 <a href="http://www.blogjava.net/qq13367612/articles/17646.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>配置Struts应用</title><link>http://www.blogjava.net/qq13367612/articles/17079.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Thu, 27 Oct 2005 09:32:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17079.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17079.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17079.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17079.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17079.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Struts应用采用两个基于XML的配置文件来配置,分别是web.xml和struts-cofig.xml文件.web.xml文件是配置所有web应用的而struts-config.xml文件是struts专用的配置文件,事实上也是可以根据需要给这个配置文件起其他名称的.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Web应用的发布描述文件:web应用发布描述文件可以在应用开着者,发布者和组装者之间传递配置信息,Web容器在启动的时候从该文件中读取配置信息,根据它来装载和配置web应用.文档类型定义DTD对XML文档的格式做了定义,DTD吧XML文档划分为元素,属性,实体每一种XML文档都有独自的DTD文件.可以从网上下载.<WEB-APP>元素是web.xml的根元素,其他元素必须嵌入在<WEB-APP>元素之内.要注意的是子元素也是有顺序的比如必须是首先<SERVLET>,然后<SERVLET-MAPPING>最后<TAGLIB>.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>为<SPAN lang=EN-US>Struts应用配置Web.xml文件:首先最重要的一步是配置ActionServlet,这个用<SERVLET>标签的servlet-name属性起一个名字叫action,然后用servlet-class属性指定ActionServlet的类.然后用<SERVLET-MAPPING>标签的servlet-name属性指定action,在用url-pattern指定接收范围是*.do的请求.不管应用中包含了多少子应用,都只需要配置一个ActionServlet,类来出来应用中的不同的功能,其实者就是不必要的,因为Servlet本身就是多线程的,而且目前Struts只允许配置一个ActionServlet.声明ActionServlet的初始化参数:<SERVLET>的<INIT-PARAM>子元素用来配置Servlet的初始化参数.param-name设置config参数名.param-value设置struts-config.xml的路径参数值.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>配置欢迎使用清单<SPAN lang=EN-US>:如果客户访问Web的时候值是访问了WEB应用的根目录URL.没有具体的指定文件,Web会自动调用Web的欢迎文件.<WELCOME-FILE-LIST>元素来配置的.通过其中的<WELCOME-FILE>欢迎页面</WELCOME-FILE>来配置.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>配置错误处理<SPAN lang=EN-US>:尽管Struts框架功能强大的错误处理机制,但是不能保证处理所有的错误或者异常.当错误发生时,如果框架不能处理这种错误,把错误抛弃给Web容器,在默认的情况下web容器会想客户端返回错误信息.如果想避免让客户看到原始的错误信息,可以在Web应用发布描述文件中配置<ERROR-PAGE>元素.通过<ERROR-CODE>404来定义错误的类型.然后通过<LOCATION>要处理错误的JSP页面来对错误进行处理.还可以用<EXCEPTION-TYPE>来设置异常,然后通过<LOCATION>来处理异常的JSP页面来处理异常.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>配置<SPAN lang=EN-US>Struts标签库:这个就和以前学到的JSP自定义标签类似,配置元素为<TAGLIB>来配置.<TAGLIB-URI>这个指定标签库的uri,类似起一个名称.<TAGLIB-LOCATION>这个是标签库的位置也就是实际所在的路径.通过这样的方法引入一个标签库,然后在前台JSP页面就可以通过自己定义的URI来调用标签.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Struts配置文件:struts-config.xml文件.首先研讨一下org.apache.struts.config包,在struts应用启动的时候会把Struts配置文件信息读取到内存中,并把它们存放在config包中相关的JavaBean类的实例中.包中的每一个类都和struts配置文件中特定的配置元素对应,ModuleConfig在Struts框架中扮演了十分重要的角色,它是整个config包的核心,在Struts运行时来存放整个应用的配置信息.如果有多个子应用都会有一个ModuleConfig对象,它和Struts文件根元素的<STRUTS-CONFIG>对应.根元素中包含<FORM-BEAN><ACTION><FORWARD>等元素.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><STRUTS-CONFIG><FONT size=4>元素:时Struts配置文件的根元素,和它对应的配置类ModuleConfig类,<STRUTS-CONFIG>元素有8个子元素.他们的DTD定义是data-sources?form-bean? global-exception?global-forwards?action-mapping?controller?message-resources?plug-in*在Struts配置文件中,必须按照DTD指定的先手顺序来配置<STRUTS-CONFIG>元素的各个子元素,如果颠倒了这些子元素的顺序,会产生错误.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><DATA-SOURCES><FONT size=4>元素:用来配置应用所需要的数据源,数据源负责创建和特定的数据库的连接.许多数据源采用连接池的机制实现.以便提高数据库访问的性能.JAVA语言提供了javax.sql.DataSource接口,所有的数据源都必须实现这个接口.许多应用服务器和Web服务器都提供了数据源组件.很多数据库厂商也提供了数据源的实现.<DATA-SOURCES>元素包含多个<DATA-SOURCE>子元素永远配置特定的数据源.他们可以包含多个<SET-PROPERTY>子元素用于设置数据源的各种属性.配置了数据源以后,就可以在Action类中访问数据源,在Action中定义了getDataSource(HttpRequest)方法,用于获取数据源对象的引用.然后可以利用DataSource对象调用getConnection获取一个连接对象对数据库进行操作.在配置文件中声明多个数据源的时候需要为每一个数据源分配唯一的Key值,通过这个来表示特定的数据源.获取特定的数据源的时候可以用dataSource = getDataSource(reqeust,”A”);<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FORM-BEANS><FONT size=4>元素:用来配置多个ActionForm,包含一个或者N个<FORM-BEAN>子元素.每个<FORM-BEAN>元素都包含多个属性.className指定和<FORM-BEAN>匹配的类.name指定该ActionForm的唯一标识符,这个属性是必须的以后作为引用使用.type指定ActionForm类的完整类名,这个属性也是必须的.注意包名也要加上.<FORM-PROPERTY>是指定动态的Form的元素,以后会深入了解.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><GLOBAL-EXCEPTION><FONT size=4>元素:用于配置异常处理,元素可以包含一个或者多个<EXCEPTION>元素,用来设置JAVA异常和异常处理类ExceptionHandler之间的映射.className指定和元素对应的配置类,默认的不用动.handler指定异常处理类默认是ExceptionHandler.key指定在本地资源文件中异常的消息Key,path指定当前异常发生的时候转发的路径.scope指定ActionMessages实例存放的范围.type指定需要处理异常类的名字,必须的.bundle指定Resource Bundle.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><GLOBAL-FORWARDS><FONT size=4>元素:用来声明全局转发,元素可以有一个或者N个<FORWARD>元素组成,用于把一个逻辑名映射到特定的URL,通过这种方法Action类或者JSP页面无需指定URL,只要指定逻辑名称就可以实现请求转发或者重定向.这样可以减少控制组件和视图的聚合.易于维护.className对应的配置类.contextRelative如果为true表示当path属性以/开头的时候,给出的是对应的上下文URL默认是false.name转发路径的逻辑名,必须写.path转发或者重定向的URL,必须写必须是以/开头.redirect设置为true的时候表示执行重定向操作,此项为false的时候,表示执行请求转发操作.重定向与请求转发的区别以后就是重定向是把请求生成应答给客户端然后在重新发送给定向的URL,浏览器地址栏会有显示.而转发就是直接把请求转发给本应用的另一个文件,不生成应答所以客户端IE没显示.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><ACTION-MAPPING><FONT size=4>元素:包含一个或者N个<ACTION>元素,描述了从特定的请求路径到响应的Action的映射.在<ACTION>元素中可以包含多个<EXCEPTION>和<FORWARD>子元素,他们分别配置局部异常处理和局部转发.attribute设置Action关联的ActionForm在request或者session范围内的key.就是在request或者session共享内的名称.className对应配置元素的类.默认的是ActionMapping.forward指定转发URL路径include指定包含URL路径.input指定包含表单的URL,当表单验证失败的时候发送的URL.name,指定和该Action关联的Form名字.该名字必须是在form-bean中定义过的,可写可不写.path必须/开头的方位Action的路径.parameter指定Action配置参数.在Action的execute()方法中可以调用ActionMapping的getParameter()方法来读取匹配的参数.roles指定允许调用该Action的安全角色,多个角色之间逗号格开.scope指定Form的存在范围.默认是session.tyep指定Action的完整类名.unknown如果是true表示可以处理用户发出的所有的无效的ActionURL默认是false.validate指定是否调用ActionForm的validate方法.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><CONTROLLER><FONT size=4>元素:用于配置ActionServlet.buffreSize指定上载文件的输入缓冲大小.该属性为可选默认4096.className指定元素对应的配置类,ControllerConfig.然后是contentType指定响应结果内容类型和字符编码,该属性为可选,默认是text/html如果在Action或者JSP网页也设置了类型内容,会覆盖这个.locale指定是否把Locale对象保存到当前用户的session中默认false.tempDir指定处理文件上载的临时工作目录.nochache如果是true在响应结果中加入特定的头参数.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><MESSAGE-RESOURCES><FONT size=4>元素:用来配置Resource Bundle.用于存放本地文本消息文件.className元素对应的配置类.MessageResourcesConfig.factory指定消息的工厂类.key指定文件存放的Servlet对象中采用的属性Key.null指定如何处理未知消息.parameter指定消息的文件名.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><PLUG-IN><FONT size=4>元素:用于配置Struts插件.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>配置多应用模块<SPAN lang=EN-US>:所有的子应用都可以共享同一个ActionServlet实例,但是每个子应用都有单独的配置文件.把应用划分为多个子应用模块.首先为每个应用创建单独的Struts配置文件,在web.xml的ActionServlet配置代码中添加几个子应用信息.采用<FORWARD>元素来实现应用之间的切换.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Digester组件:是一个Apache的另一个开源代码项目.当Struts被初始化的时候,首先会读取并解析配置文件,框架采用Digester组件来且西配置文件.然后创建config包中的对象.者对象用于存放配置信息.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>其实配置文件不难<SPAN lang=EN-US>,只要都理其中的原理就OK了.真正实际的项目开发中,采用的工具例如Eclipse系列,提供了相应的插件,在创建一个Struts工程的时候配置文件的标签都是自动生成的,而我们只需要往里面填写属性就OK了. </SPAN></FONT></SPAN></P><img src ="http://www.blogjava.net/qq13367612/aggbug/17079.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-27 17:32 <a href="http://www.blogjava.net/qq13367612/articles/17079.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts视图组件</title><link>http://www.blogjava.net/qq13367612/articles/17078.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Thu, 27 Oct 2005 09:31:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17078.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17078.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17078.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17078.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Struts框架的视图负责为客户端提供动态的网页内容.主要是由JSP网页构成.还提供了Struts客户化标签和ActionForm Bean,这些组件提供对国际化,接收用户表单输入的数据,表单验证和错误处理等功能.视图是模型的外在表现形式,用户通过视图来了解模型的状态,同一个模型可以有多种视图.框架中视图由JSP组件构成,除此之外还包括以下组件:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">1)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体">HTML文档<o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">2)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体">JSP客户化标签<o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">3)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体">JavaScripet和stylesheet<o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">4)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">多媒体文件<SPAN lang=EN-US><o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">5)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">消息资源<SPAN lang=EN-US>(Resource Bundle)<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">6)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US style="FONT-FAMILY: 宋体">ActionForm Bean<o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>ActionForm属于一种Bean,什么是Bean呢?是可重用的平台独立的JAVA组件,JavaBean<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>支持属性<SPAN lang=EN-US>,事件,方法和持久化.Struts框架仅仅利用了JavaBean的一小部分特性.Bean和普通的JAVA类很相似,不过它应该遵守以下的规范:<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">1)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">必须提供不带参数的构造方法<SPAN lang=EN-US><o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">2)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">为<SPAN lang=EN-US>Bean的所有属性提供公共的get/set方法<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">3)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">对于<SPAN lang=EN-US>boolean类型的属性要提供isXXX()方法,那么该方法返回Boolean类型的属性<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">4)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">对于数组类型的属性<SPAN lang=EN-US>,应该提供getXXX(int index)和setXXX(index,value)方法来读取和设置数组元素.<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Struts利用JavaBean来创建数据传输对象,Data Transfer Object简称DTO,用于不同的层之间传递数据.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>ActionForm是Struts框架提供的DTO,用于在视图层和控制器之间传递HTML表单数据,控制层可以从ActionForm中读取用于输入的表单数据,也可以把来自模型的数据保存到ActionForm中,然后返回给视图.ActionForm具有表单验证的功能.由于ActionForm类使用了ServletAPI,因此不提倡直接把ActionForm传递给模型,而是应该在控制层把它的数据重新组装到自定义的DTO中,在把它传递给模型层.在配置文件中<ACTION>元素的scope属性设置ActionForm的范围默认是session.Action的生命周期如下:<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">1)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">控制器接收到请求<SPAN lang=EN-US><o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">2)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">从<SPAN lang=EN-US>request或者session范围内取出ActionForm的实例,没有就新建一个<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">3)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">调用<SPAN lang=EN-US>Form的reset()方法<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">4)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">把<SPAN lang=EN-US>ActionForm实例保存到request或者session范围中<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">5)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">把用户输入的表单数据装到<SPAN lang=EN-US>ActionForm中<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">6)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">如果<SPAN lang=EN-US>validate属性是true则调用validate方法<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">7)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">验证成功就把<SPAN lang=EN-US>ActionForm实例以参数传递给Action的execute方法,如果失败把请求转发给<ACTION>的input属性指定的Web组件(大多JSP),ActionForm依然保存在request或者session范围内.<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Struts框架的ActionForm类是抽象类,必须在应用中创建它的子类,来捕获具体的HTML表单数据.其中的属性和表单的属性一一对应.如果配置文件中<FORM-BEAN>元素的name属性和<ACTION>元素的name属性匹配,<ACTION>元素中的的validate属性为true.的时候.validate方法会被调用,基类的返回值是null,如果扩展了ActionForm类,那么应该覆盖validate方法,这个方法主要负责检验格式和语法,而不负责检查数据是否符合业务逻辑.对于一个请求控制器首先调用的是ActionForm的reset()方法,然后在把用户输入的表单数据组装到ActionFrom中.这个方法负责恢复属性的默认值,例如把boolean类型的属性设置成true或者false,把字符串设置为null或者某个初始值.感觉如果ActionForm在request范围内,那么对于每个新的请求都会创建新的ActionForm实例,当新的实例创建后,它的属性就是默认值,所以在写reset()方法就没什么意义了.如果是在session范围内,一个实例可以接收多次请求,那么reset()方法就非常有用了!如果是从request或者session范围中取出Form的值,可以用例如Form f=(Form)session.getAttribute(“Form”)的方法取出.这时Form的名字就是共享对象中的一个key不过如果是在Action的execute()方法中就很简单了,可以Form f=(Form)Form这样来获取一个Form也可以通过其中的具体的get方法来获取具体的属性,注意一定要转换类型.有的时候,由于表单的数量太多,无法在同一个页面显示,可以把他们拆分成多个表单,分多个页面显示.在这种情况下,即可以为每一个表单创建一个单独的ActionForm,也可以只创建一个,和多个表单对应.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>下面研讨以下如何使用动态的<SPAN lang=EN-US>ActionForm,在Struts框架中,ActionForm对象用来包装HTML表单数据,并能够动态返回用于显示给用户的数据.自己写的Form必须符合JavaBean的规范,继承ActionForm同时可以选择的重写reset()和validate()方法.虽然ActionForm简化了Web开发,但是对于大型的项目如果HTML表单改变对应的ActionForm也一定要修改,所以Strust1.1对此做出了修改引入了动态的DynaActionForm类.它支持载配置文件中完成ActionForm的全部配置,没必要写额外的程序来创建具体的ActionForm类,配置动态的方法是在配置文件中一个<FORM-BEAN>元素.如下:<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FORM-BEANS><o:p><FONT size=4></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 10.5pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.5pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><SPAN style="mso-spacerun: yes"><FONT size=4>&nbsp;&nbsp; </FONT></SPAN><FORM-BEAN <o:p name="”loginForm”"></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 84pt; mso-char-indent-count: 8.0; mso-char-indent-size: 10.5pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>type=”org.apache.struts.action.DynaActionForm”<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 84pt; mso-char-indent-count: 8.0; mso-char-indent-size: 10.5pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>//上面是指定DynaActionForm类,名字是loginForm<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 36.75pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FORM-PROPERTY name="”username”" type="”java.lang.String”/"><o:p><FONT size=4></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 36.75pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FORM-PROPERTY name="”password”" type="”java.lang.String”/"><o:p><FONT size=4></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 36.75pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"></FORM-BEAN><o:p><FONT size=4></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"></FORM-BEANS><o:p><FONT size=4></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FORM-BEAN><FONT size=4>元素的子元素<FORM-PROPERTY>来设置动态的ActionForm属性.name指定属性的名称,type指定属性的类型.ActionForm的类型表单的类型.如果要设置JAVA的基本类型,在配置的时候应该用相应的包装类型来替换,例如int的包装类型就是Integer.动态的Form类DynaActionForm提供了initialize()方法,它把调但所有的属性都恢复为默认值.表单属性默认值由<FORM-BEAN>元素的<FORM-PEOPRETY>子元素的initial属性来决定.如果没设置,则表单的默认属性由其JAVA类型来自动决定.例如对象类型的默认就是null.整型是0.Boolean是false.如果希望Struts每次把表单数据组装到动态的ActionForm之前,先把所有的属性恢复为默认值,可以定义一个DynaActionForm的子类,然后覆盖reset()方法,在其中调用initalize()方法就OK了.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Action类和JSP都可以访问动态的ActionForm类,使用方法与标准的Form大致相同.有一点区别就是如果使用标准的Form类,用get和set方法就可以,而DynaActionForm是把所有的属性保存在一个Map类对象中.访问的方法如下:<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>public Object get(String name)<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>public void set(Strig name,Object value)<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>DynaActionForm基类的validate()方法没有提供任何默认的验证行为,可以定义扩展它的子类,然后覆盖validate()方法,但是以编程的方法来验证动态的ActionForm违背了Struts框架提供的机制.幸运的是,可以采用另一种机制.Validator框架来完成验证,如果想了解Validator验证框架,不要急继续关注我的Blog,我还会漫漫道来.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>今天侧重研讨了构成<SPAN lang=EN-US>Struts视图组件的ActionForm,因为它非常重要,必须彻底的了解它算能真正的学会Struts,它可以存放在session和request范围内.下面说一些开发技巧希望能对关注我的Blog的朋友们,在如后的开发中有所帮助.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l3 level1 lfo4; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">1)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">在<SPAN lang=EN-US>HTML表单中定义<HTML;HIDDEN properyt="”page”/">隐藏字段来标示当前页面<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l3 level1 lfo4; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">2)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">在<SPAN lang=EN-US>ActionForm中定义page属性,它和表单中的隐藏字段page对应<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l3 level1 lfo4; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">3)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">在<SPAN lang=EN-US>ActionForm的reset()方法中,只能把当前表单相关的属性值恢复默认值.<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l3 level1 lfo4; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">4)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">在<SPAN lang=EN-US>ActionFomr的validate()方法中,只能对当前表单的相关属性进行验证.<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l3 level1 lfo4; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">5)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">在配置<SPAN lang=EN-US>ActionForm和Actin的映射的时候,应该把ActionForm的范围设为session<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Struts框架还引入了DynaActionForm类,是动态创建ActionForm的类,要注意的如下:<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: -10.5pt; mso-char-indent-count: -1.0; mso-char-indent-size: 10.5pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>1) </FONT>
<FORM><FONT size=4>的<FORM-PORPERTY>子元素是用来配置动态Form的.type属性指定ActionForm的属性的类型.如果是JAVA基本类型,则用JAVA包装类型.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: -10.5pt; mso-char-indent-count: -1.0; mso-char-indent-size: 10.5pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>2)提倡使用Validator框架来验证动态的ActionForm.这样可以避免用编程的方法来实现validate()方法.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: -10.5pt; mso-char-indent-count: -1.0; mso-char-indent-size: 10.5pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>3)通常不需要扩展DynaActionForm类,如果需要提供属性的复位功能,则扩展此类,然后重写reset方法中去调用initialize()方法进行复位,通常ActionForm在Session范围内使用此方法.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>4)如果访问DynaActionForm的属性,应该调用以下方法:<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public Object(String name)<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>public void set(String name,Object value)<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>name参数代表属性的名称.<o:p></o:p></FONT></SPAN></P></FORM><img src ="http://www.blogjava.net/qq13367612/aggbug/17078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-27 17:31 <a href="http://www.blogjava.net/qq13367612/articles/17078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts模型组件</title><link>http://www.blogjava.net/qq13367612/articles/17077.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Thu, 27 Oct 2005 09:30:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17077.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17077.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17077.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17077.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17077.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模型组件代表应用的业务数据</SPAN><SPAN style="FONT-FAMILY: 宋体">和逻辑<SPAN lang=EN-US>.坦率的说Struts框架并没有为设计和创建模型组件提供线程的框架.不过Strtus允许使用其他的模型组件来处理应用的业务领域.如EJB活JDO以及常规的JavaBean和ORM.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>模型是应用中重要的一部分<SPAN lang=EN-US>,它包含了业务实体和业务规则,负责访问和更新持久化数据.应该把所有的模型组件放在系统中的同一个位置,这样利于维护数据和完整性,提高可重用性.模型和视图以及控制器之间保持独立,在分层框架结构中.位于上层的视图和控制器依赖于下层的模型的实现,而下层的模型不应该依赖于上层的视图在控制器的实现.如果在模型组件中通过JAVA的import语句引入了视图和控制器组件,这样的程序就垃圾了.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>在科学和工程技术领域<SPAN lang=EN-US>,模型是一个很有用途的概念,它可以用来模拟一个真是的系统.在软件开发领域,模型用来表示真是世界的实体.在软件开发的不同阶段,需要为目标系统创建不同的模型.可以采用面向对象的建模语言UML来描述.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>在建模之前首先要对问题域进行详细的分析<SPAN lang=EN-US>,确定用例,接下来可以根据用例来创建概念模型.概念模型用来模拟问题域中的真实实体.概念模型描述了每个实体的概念和属性,以及实体之间的关系.这个阶段并不描述实体的行为.比如说商品和商品目录之间存在多对多的关系,这是因为一个商品目录包含多个商品,而一个商品也可以属于多个商品目录.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>设计模型需要在概念模型的基础上设计<SPAN lang=EN-US>.可以用UML类框图,活动图以及状态图来描述设计模型.根据UML语言,类之间存在四种关系:<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39.75pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.75pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">1)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">关联<SPAN lang=EN-US>(Association):就是类之间的引用关系,<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39.75pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.75pt"><FONT size=4><SPAN lang=EN-US>2)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">依赖<SPAN lang=EN-US>(Dependency):是指类之间的访问关系.</SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39.75pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.75pt"><FONT size=4><SPAN lang=EN-US>3)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">累积<SPAN lang=EN-US>(Aggregation)就是说整体与个体之间的关系,可以把累积看作一种强关联关系.</SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39.75pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 39.75pt"><FONT size=4><SPAN lang=EN-US>4)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">一般化<SPAN lang=EN-US>(Generalization):是类之间的继承关系.</SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>如果想了解如何为应用创建合理的面向对象的设计模型<SPAN lang=EN-US>,可以浏览<A href="http://www.uml.org/"><FONT color=#4371a6>www.uml.org</FONT></A>深入了解UML语言.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>业务对象<SPAN lang=EN-US>BO(Business Object),是对真是世界的实体的软件抽象.它可以代表业务领域中的人,地点,事务或者概念.业务对象包括状态和行为.如果一个类可以作为业务对象它应该具有以下特征:<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">1)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">包含状态和行为<SPAN lang=EN-US>.<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US>2)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">代表业务领域的人<SPAN lang=EN-US>,地点,事务或概念.</SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo2; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US>3)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">可以重用<SPAN lang=EN-US>.</SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>业务对象客分为三种类型<SPAN lang=EN-US>:<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: 宋体">1)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">实体业务对象<SPAN lang=EN-US>.<o:p></o:p></SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US>2)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">过程业务对象<SPAN lang=EN-US>.</SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo3; tab-stops: list 39.0pt"><FONT size=4><SPAN lang=EN-US>3)<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">事件业务对象<SPAN lang=EN-US>.</SPAN></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>实体对象就是具体的对象<SPAN lang=EN-US>,比如人,地点,商品,订单.过程对象就是业务过程或者流程,<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>他们通常依赖于实体对象<SPAN lang=EN-US>.可以把业务领域的动词,比如登陆,发货等作为过程对象.事件对象代表一些时间如比异常,警告,超时,错误.这些事件通常由系统中的行为触发器激活.在应用使用业务对象好处很多,最重要的一点就是业务对象提供了通用的技术术语和概念,不管技术人员还是非技术人员都可以共享理解它们.此外业务对象可以隐藏实现的细节,对外只暴露接口,提高了安全性.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>通常<SPAN lang=EN-US>,持久化意味着通过手工或者其他方法输入到应用中的数据,能够在应用结束运行后依然存在.即使应用运行结束或者计算机关闭,这些信息依然存在.当应用中的业务对象在内存中创建后,他们不可能永远存在.最后,他们要么消失,要么就要被持久化到数据库中.内存无法永久保留数据,因此必须对业务对象进行持久化.关系型数据库被广泛用来存储数据.关系型数据库中存放的是关系型数据.它是非面向对象的.把业务对象映射到非面向对象的数据库中,因为对象由状态和行为组成,而关系数据库则由表组成.对象之间的各种关系和关系型数据库中表之间的关系并不一一对应.例如对象之间继承关系就不能直接映射到关系型数据库中了.而对于JAVA应用,可以直接通过JDBC编程来访问数据库.JDBC可以说是访问持久化数据层的最原始最直接的方法,如果数据模型非常复杂,这里我推荐用Hibernate架构来进行持久化层的处理.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>因为<SPAN lang=EN-US>Struts中本身不包含处理模型的架构,所以在这里只是简单的对模型进行了介绍.至于具体的知识可以研究Ejb,JavaBean等技术.至于持久化层的hibernate架构,这里我推荐阅读孙卫琴的:&lt;&lt;精通Hibernate&gt;&gt;.</SPAN></FONT></SPAN></P><img src ="http://www.blogjava.net/qq13367612/aggbug/17077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-27 17:30 <a href="http://www.blogjava.net/qq13367612/articles/17077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts控制器组件</title><link>http://www.blogjava.net/qq13367612/articles/17076.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Thu, 27 Oct 2005 09:29:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17076.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17076.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17076.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17076.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Struts控制器组件负责接收用户的请求,更新模型.以及选择合适的视图组件返回给客户端.控制器组件有助于将模型和视图分离,有了这种分离可以在同一个模型的基础上得心应手的开发多种模型的视图.主要是ActionServlet框架中央控制器,RequestProcessor每个子应用的模块处理器,Action负责处理具体的业务的组件.Struts采用ActionServlet和RequestProcessor组件进行集中控制,并且采用Action组件来完成具体的业务单项处理.控制器组件的控制机制:主要认识是接受用户请求,根据用户的请求调用合适的模型来执行业务逻辑,获取业务逻辑的结果,根据当前状态以及业务逻辑执行结果选择合适的视图组件返回给客户端.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>ActionServlet类:是Struts框架的核心控制器组件,所有的用户请求都先由它来处理,然后再由它把请求转发给其他组件.容器启动的时候或者用户首次请求ActionServlet的时候加载ActionServlet类在这两种情况下,容器都会在ActionServlet被加载后立即执行它的init()方法,这可以保证当ActionServlet处理用户请求的时候已经被初始化.至于具体的初始化方法我们不用去管,下面研究一下ActinServlet的process()方法.当主控制器实例接收到Http请求后,在doGet()或者doPost()方法中都会调用process()方法来处理请求.在这个方法中首先调用selectModule()方法,这个方法选择负责处理用于请求的子应用模块.然后把子应用模块相关的ModuleConfig和MessageResources对象存储到request范围内,这使得框架的其余组件可以方便地从request范围内读取这些对象.从而获取应用配置信息和消息资源.ActionServlet是可以派生子类的但是感觉没什么意义了,多数的功能都被移动到了RequestProcessor类中,以便减轻ActionServlet的负担.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>RequestProcessor类:对于应用模块,每个子应用模块都由各自的RequestProcessor实例.在ActionServlet的process()方法中一旦选择了正确的子应用模块,就会调用子应用的模块的RequestProcessor类,每个子应用模块都可以拥有单纯的RequestProcessor类.开发人员可以很方便的创建客户化的RequestProcessor类.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US style="FONT-FAMILY: 宋体"><FONT size=4>Action类:是用户请求和业务逻辑之间的桥梁,每个Action充当客户的一项业务代理.在RequestProcessor类预处理请求的时候.在创建了Action的实例后,就调用自身的processActionPerForm()方法,该方法调用Action的execute()方法.为了确保线程安全thread-safe,在一个应用的生命周期中.Struts框架只会为每个Action类创建一个Action实例.所有的客户请求共享同一个Action实例.并且所有的请求线程可以执行它的execute方法.Action类的execute()方法返回一个ActionForward对象,代表了Web资源的逻辑对象,这里的Web资源可以是JSP页面,JAVA servlet或者Action.从execute()方法返回的对象有两种方法:创建一个动态的ActionForward实例和在配置文件的action元素里的子元素<FORWARD>元素.在execute()方法只需要调用mapping实例参数的findForward()方法,来获得特定的ActionForward对象.<ACTION>元素的roles属性是指定这个Action的用户必须具备的安全角色.多个角色之间以逗号隔开.<o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>利用<SPAN lang=EN-US>Token解决重复提交:在某些情况下,如果用户对同一个HTML表单多次提交,Web应用必须能够判断用户的重复提交的行为,以做出相应的处理.可以利用同步令牌Token机制来解决Web应用重复提交的问题.Struts给出了一个参考实例.Action类中提供了一系列和Token相关的方法判断存储在当前用户会话中的令牌值和请求参数中的令牌是否匹配,如果匹配返回true.否则返回false.方法是protected boolean isTokenValid(request).<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>实用类<SPAN lang=EN-US>:RequestUtils类:org.apache.struts.util.RequestUtlis为Struts框架提供了一些处理请求的通用的方法.ModuleUtils类:org.apache.strtus.taglib.ModuleUtils类提供了处理子应用应用模块的实用方法.Globals类:org.apache.struts.Globals类提供了一组公共类型的静态常量.<o:p></o:p></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体"><FONT size=4>控制器组件的核心技术可以说就是<SPAN lang=EN-US>Servlet,控制器也是Struts的灵魂也是MVC模式的核心,所以如果想学好Struts就必须彻底的了解控制器的运行原理.</SPAN></FONT></SPAN></P><img src ="http://www.blogjava.net/qq13367612/aggbug/17076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-27 17:29 <a href="http://www.blogjava.net/qq13367612/articles/17076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts配置文件简介</title><link>http://www.blogjava.net/qq13367612/articles/17064.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Thu, 27 Oct 2005 08:26:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/17064.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/17064.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/17064.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/17064.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/17064.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Struts framework根据配置文件使得ServletAction，ActionMapping，Action，ActionForm这几个不同层次的组件相互交互，协调的工作。这些配置文件是在系统启动的时候，读入并保存于内存中，供控制器使用的。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Struts framework主要包括三部分的配置描述，一个是指定有关Struts Controller及其相关的的配置描述（Initialization Parameters），一个是对struts tag lib的描述，一个是Struts组件（ActionMapping，Action，ActionForm）之间相互映射协调的关系</P>
<P>&nbsp;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因为Struts Controller的主要类ActionServlet是继承自HttpServlet，所以必须像配置一个Servlet那样在部署描述符（Web.xml ）中配置ActionServlet类及其访问映射。</P>
<P>&nbsp;&nbsp; 当第一次创建基于Struts的Web应用程序时，将为您创建一个部署描述符，这通常就足够了。该文件包括下列条目：</P>
<P>l、&lt;servlet&gt;条目定义用于Web应用程序的servlet (在本例中，这是唯一的servlet)：</P>
<P>— &lt;servlet-name&gt; 和&lt;servlet-class&gt;指示ActionServlet (标识为“操作”)接收HTTP请求并确定如何响应。</P>
<P>— &lt;init-param&gt;表示servlet初始化参数.</P>
<P>— “config”指示ActionServlet的行为由指定的配置文件来指导，该配置文件通常具有以下名称：</P>
<P>\WEB-INF\struts-config.xml</P>
<P>— “debug”具有整数值，它指示将有关处理的详细信息写至控制台的程度。“0”表示不生成任何Debug信息。</P>
<P>— “detail”具有整数值，它指示将“映射”详细信息(如后面所述)写至控制台的程度。</P>
<P>―&nbsp; &lt;load-on-startup&gt;导致在启动应用程序时装入servlet。</P>
<P>—&nbsp; &lt;servlet-mapping&gt;元素标识这样的命名模式：当命名模式由URL进行匹配时，Web服务器就将控制权移交给ActionServlet。考虑下面各种情况：</P>
<P>―&nbsp; 访问了ActionServlet，原因是“操作”(&lt;servlet-mapping&gt;中的&lt;servlet-name&gt;元素的内容)与“操作”(&lt;servlet&gt;中的&lt;servlet-name&gt;元素的内容)相匹配。</P>
<P>— &lt;servlet-mapping&gt;元素指定URL的结尾的命名模式。每个URL的开头都是应用程序上下文路径。按照惯例，ActionServlet调用对象以响应与命名模式“*.do”(其中“*”是通配符)一致的URL。</P>
<P>— &lt;welcome-file-list&gt;元素指示获得初始控制权的特定于应用程序的代码；在本例中，Web服务器直接从Web Content目录中调用index.jsp。</P>
<P>— &lt;error-page&gt;元素指示显示哪个JSP来响应错误;在本例中，错误为如下所示：</P>
<P>―&nbsp; 404&nbsp; (找不到资源)</P>
<P>―&nbsp; 500&nbsp; (Web服务器内部发生错误)</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;每个&lt;taglib&gt;元素都使相对URL(相对于Web.xml)与标记库描述符(相对于Web应用程序根目录)相关联。每个JSP都可以使用同一个URL来表示给定的标记库，而Web.xml确定引用了哪个文件。</P>
<P>有关struts tag lib的配置描述<BR>&nbsp;&nbsp;&nbsp; 如果你的web application打算使用Struts的taglib，那么你有必要在web.xml中对struts taglib进行配置描述。</P>
<P>有关Struts Action Mapping的配置描述<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作为先前描述的web.xml设置的结果，Web应用程序服务器将请求的一个子集按路径发送至ActionServlet，它通常调用一系列操作和JSP。ActionServlet的响应是基于配置文件struts-config.xml的内容的。有关其DTD文档的描述，请参考<A href="http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"><STRONG>这里</STRONG></A>。</P>
<P>&nbsp;&nbsp;&nbsp; 一般struts-config（version1.1）包含了如下几个部分：</P>
<P>&nbsp;&nbsp;&nbsp;（1）form-bean</P>
<P>&nbsp;&nbsp;&nbsp;（2）global-forwards</P>
<P>&nbsp;&nbsp;&nbsp;（3）action-mappings</P>
<P>&nbsp;&nbsp;&nbsp;（4）data-sources</P>
<P>&nbsp;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对于这样的一个请求（例如，表示为“/login.do”），Struts框架将会执行下列步骤：</P>
<P>1、&nbsp;&nbsp;&nbsp;&nbsp;寻找操作类对象（继承org.&nbsp;apache.struts.action.Action的类）<BR>2、&nbsp;&nbsp;&nbsp;&nbsp;ActionServlet调用操作类对象的执行方法<BR>操作类中的执行方法的特征符为如下所示：<BR>public&nbsp;ActionForward&nbsp;&nbsp;execute(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionMapping&nbsp;mapping,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionForm&nbsp;form,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest&nbsp;request,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)<BR>&nbsp;&nbsp;&nbsp;&nbsp;映射对象（ActionMapping），它包含指示如何响应方法的每个可能结果的规则（“映射”）<BR>&nbsp;&nbsp;&nbsp;&nbsp;Struts表单bean（ActionForm），它保存发送至HTML表单或接收自HTML表单的数据<BR>&nbsp;&nbsp;&nbsp;&nbsp;请求和响应对象（HttpServletReques/&nbsp;HttpServletResponse）<BR><BR>3、&nbsp;&nbsp;&nbsp;&nbsp;从执行方法返回ActionForward对象，用于指导ActionServlet接着访问哪个操作类或JSP<BR>返回的ActionForward对象中的信息取决于两个值：<BR>&nbsp;&nbsp;&nbsp;&nbsp;方法的结果（如在“成功”或“故障”等字符串中所述）<BR>&nbsp;&nbsp;&nbsp;&nbsp;映射对象，它包含从Struts配置文件中读取的信息<BR><BR><BR>要弄明白某些运行时关系，要明白struts-config.xml该文件包括下面的一组条目：<BR>&nbsp;&nbsp;&nbsp;&nbsp;＜form-beans＞标记标识每个表单bean<BR>&nbsp;&nbsp;&nbsp;&nbsp;＜action-mappings＞标记包括用于指导应用程序流的信息，每个＜action＞子标记都使相对URL与操作类和潜在的后续操作相关。<BR>Form-bean元素<BR>Struts配置文件中的一个示例＜form-bean＞子元素为如下所示：<BR>　&lt;form-bean&nbsp;name=“registerForm”&nbsp;&nbsp;type=“strutscommon.RegisterForm”/&gt;<BR>每个&lt;form-bean&gt;子元素都包括下列属性：<BR>name<BR>表单bean的名称，稍后在配置文件中会用到。ActionServlet举例说明了该bean（如果需要的话）并在将对bean的引用存储在请求或会话对象中时将该名称用作键。<BR>type<BR>　　　　　类的全限定名称，它继承org.apache.struts.action.ActionForm该类必须在类路径中。接受“Struts贸易样本”中的注册的表单bean包括HTML注册表单中每个字段的getter&nbsp;和setter方法。该bean还包括验证方法，如下节“验证”中所述。<BR>Action元素<BR>&nbsp;&nbsp;&nbsp;Struts配置文件中的一个示例＜action＞元素为如下所示：<BR>　　&lt;action&nbsp;path=“/register”<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type=“strutsEGL.RegisterAction”<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name=“registerForm”<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input=“/register.jsp”<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scope=“request”<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;forward&nbsp;name=“success”path=“/home.do”/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;&nbsp;forward&nbsp;name=“failure”path=“/register.jsp”/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/action&gt;<BR>每个＜action＞元素都包括下列属性中的某些属性或所有属性：<BR>&nbsp;path<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;将请求指定为非限定URL，不带文件扩展名（例如，“/register”）请求是根据＜action＞元素中的其它属性来处理的，并且是用户输入的结果或者是在different＜action＞元素中标识的转发的结果。<BR>type<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;指定在发出请求时调用其执行方法的操作类的全限定名。该类必须在类路径中。<BR>　　　注：不指定要实例化的类，可以通过使用forward属性来转发请求，该属性在“Struts贸易样本”中未使用，并且与后面描述的＜forward＞子元素不相同。<BR>name<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用于保存发送至HTML表单或接收自HTML表单的数据表单bean的名称。<BR>　　&nbsp;input<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;指定相对URL（例如，“/register.do”或“/index.jsp”）必须包括后缀，<BR>如果表单bean的验证方法指示发生了输入错误，则会调用URL；有关详细信息，参见下节的“验证”。<BR>　　&nbsp;scope<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;指定将对表单&nbsp;bean的引用存储在哪个作用域中。其值为“会话”（缺省值）或“请求”。<BR>　　　　&nbsp;Struts配置文件中的每个＜action＞元素还包括子元素＜forward＞，它指定从方法结果至后续调用的映射。每个＜forward＞子元素都包括下列属性<BR>　　name&nbsp;<BR>指定导致在运行时使用当前映射的字符串（例如，“success”），但是<BR>只限于以下情况：在&nbsp;type&nbsp;中引用的操作类的执行方法使用完全相同<BR>的字符串来配置返回至ActionServlet的&nbsp;ActionForward对象。下面<BR>的执行方法不是很重要，但是会导致使用“success”映射：<BR>&nbsp;&nbsp;<BR>&nbsp;public&nbsp;ActionForward&nbsp;exectue(<BR>&nbsp;&nbsp;&nbsp;ActionMapping&nbsp;mapping,<BR>&nbsp;&nbsp;&nbsp;ActoinForm&nbsp;form,<BR>&nbsp;&nbsp;&nbsp;HttpServletRequest&nbsp;request,<BR>&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)<BR>&nbsp;&nbsp;&nbsp;Throws&nbsp;IOException,ServletException<BR>｛<BR>&nbsp;&nbsp;&nbsp;ActionForward&nbsp;forward=new&nbsp;ActionForward();<BR>&nbsp;&nbsp;&nbsp;Forward=mapping,findForward(“success”);<BR>&nbsp;&nbsp;&nbsp;return(forward)；<BR>｝<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;path<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;指定非限定URL（例如，“/home.do”&nbsp;或“/index.jsp”）必须包括文件扩展名，仅当使用当前映射时才会调用该URL，转发操作类是根据different&lt;action&gt;元素中的属性来处理的，尤其是，在其path属性标识相同URL的&lt;action&gt;元素中。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;有必要提一下的是，在struts1.1中，提出了对Multiple&nbsp;Application&nbsp;Support。在struts的早先版本中，只有一个struts配置文件，一般叫struts-config.xml。但是，对于越来越复杂的应用系统的发展，只有一个地方存放这个一个文件，对大型项目来说，使用和修改这个配置文件，使其成为了一个应用的瓶颈问题。在struts1.1中，你可以定义多了配置文件协同工作。<BR></P><img src ="http://www.blogjava.net/qq13367612/aggbug/17064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qq13367612/" target="_blank">Sung</a> 2005-10-27 16:26 <a href="http://www.blogjava.net/qq13367612/articles/17064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts原理、开发及项目实施 </title><link>http://www.blogjava.net/qq13367612/articles/16894.html</link><dc:creator>Sung</dc:creator><author>Sung</author><pubDate>Wed, 26 Oct 2005 08:30:00 GMT</pubDate><guid>http://www.blogjava.net/qq13367612/articles/16894.html</guid><wfw:comment>http://www.blogjava.net/qq13367612/comments/16894.html</wfw:comment><comments>http://www.blogjava.net/qq13367612/articles/16894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qq13367612/comments/commentRss/16894.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qq13367612/services/trackbacks/16894.html</trackback:ping><description><![CDATA[1、 摘要<BR>2、 关键词<BR>3、 Framework<BR>4、 Struts的起源<BR>5、 Struts工作原理<BR>6、 Struts安装<BR>7、 一个实例<BR>8、 Struts优缺点<BR>9、 Struts项目实施经验<BR>10、 总结<BR>11、 参考文献<BR><BR>1、 摘要<BR>　　本文主要讲述了Struts（以Struts1.0.2为例）的工作原理，安装以及配置方面的问题。然后结合一个实例，详细讨论了Struts在实际开发过程中的应用，最后提供一些在开发过程中积累的经验，供大家参考。<BR><BR>2、关键词<BR>Struts、MVC、J2EE、Tiles、Framework<BR><BR>3、Framework<BR>　　Framework即架构（框架），这里指软件的架构方式，为什么要提Framework呢？请允许我从J2EE讲起。<BR>　　J2EE体系包括JSP、Servlet、