﻿<?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-祸兮福所倚，福兮祸所伏-文章分类-Java翻译</title><link>http://www.blogjava.net/liujing/category/1659.html</link><description>    想随便当个小职员，随便赚点钱然后随便和一个不美也不丑的普通女孩结婚，随便生两个孩子，先生个女孩再生个男孩。等女儿结婚，儿子也能够独挡一面的时候，然后就退休，然后每天过着下着象棋和围棋的悠闲生活。然后在自己的老婆死之前自己先老死这种生活多美好呀！</description><language>zh-cn</language><lastBuildDate>Sat, 03 Mar 2007 09:43:09 GMT</lastBuildDate><pubDate>Sat, 03 Mar 2007 09:43:09 GMT</pubDate><ttl>60</ttl><item><title>FastTrackToStruts 7 用插件定制扩展</title><link>http://www.blogjava.net/liujing/articles/5791.html</link><dc:creator>塞翁</dc:creator><author>塞翁</author><pubDate>Thu, 09 Jun 2005 01:12:00 GMT</pubDate><guid>http://www.blogjava.net/liujing/articles/5791.html</guid><wfw:comment>http://www.blogjava.net/liujing/comments/5791.html</wfw:comment><comments>http://www.blogjava.net/liujing/articles/5791.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liujing/comments/commentRss/5791.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liujing/services/trackbacks/5791.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp;&nbsp; 用插件定制扩展<BR>&nbsp;&nbsp;&nbsp; 一个框架必须提供一种容易的创建定制扩展的方式，允许一种插件机制，把外部服务无缝的插入到框架中。要实现这个，框架必须提供扩展点，让一个可插入的组件可以进行生命周期管理（比如init和destroy）。通过提供这样的扩展点，一个开发人员能够写一个服务，该服务能够根据扩展机制确保接口支持，这种插件接口用来控制服务和相关框架资源的创建，使用，清除。<BR>&nbsp;&nbsp;&nbsp; struts校验就是一个插件例子，它是声明式校验变成可能。struts-config.xml的相应条目描述如下：<PLUG-IN classname="" /><BR>&nbsp; <SET-PROPERTY property="pathnames" <br="" />&nbsp;&nbsp;&nbsp; value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;<BR></PLUG-IN /><BR>ValidatorPlugIn类和其它所有插件类有控制器初始化时实例化。每个插件对象使用<PLUG-IN />的className属性实例化。这个插件对象遵循JavaBeans规范的设计模式,对于每个定义在<PLUG-IN />元素的属性都提供了属性处理方法。一旦一个插件实例化，它的init方法被调用，以让开发人员完成插件自己的实例化操作。比如，ValidatorPlugIn.init方法会初始化它的资源并使用ValidatorPlugIn.VALIDATOR_KEY保存资源到上下文中；这些资源将在创建框架的上下文中的org.apache.commons.validator.Validator类的实例时使用。控制器初始化的插件用Action.PLUG_INS_KEY关键字，把org.apache.struts.action.PlugIn对象的数组保存在上下文中，接着使用控制器的destroy方法调用每个插件的destroy方法释放请求的资源。</P>
<P>&nbsp;&nbsp;&nbsp; 摘要<BR>&nbsp;&nbsp;&nbsp; 实现基于http协议的请求/相应的MVC模式所花费的时间和努力会是有利可图的。选择一个合适的框架解决这个问题会提供一个领先的开始，它会允许架构师和开发人员更多的关注业务而不是集成。struts也提供了完整的模块比如validator实现表单的声明式校验，Tiles组织复合视图；这些模块加强了框架的功能，极大的简化了设计和开发应用程序的任务。更多关于struts，安装配置信息可以在<A href="http://jakarta.apache.org/struts/userGuide/index.html">http://jakarta.apache.org/struts/userGuide/index.html</A>找到。因为struts一直在修改，可能在你读到本文章的时候，一些实现可能发生改变，因此最好通过<A href="http://jakarta.apache.org/struts">http://jakarta.apache.org/struts</A>发布的文档和更新声明完成这些内容<BR></P>
<P>&nbsp;&nbsp;&nbsp; 参考</P>
<P>&nbsp;&nbsp;&nbsp; [Core] Core J2EE Patterns by Deepak Alur et. al. (Prentice Hall, 2001)<BR>&nbsp;&nbsp;&nbsp; [Gof] Design Patterns by Erich Gamma et. al. (Addison-Wesley, 1995)</P><img src ="http://www.blogjava.net/liujing/aggbug/5791.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liujing/" target="_blank">塞翁</a> 2005-06-09 09:12 <a href="http://www.blogjava.net/liujing/articles/5791.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FastTrackToStruts 4 错误处理</title><link>http://www.blogjava.net/liujing/articles/5788.html</link><dc:creator>塞翁</dc:creator><author>塞翁</author><pubDate>Thu, 09 Jun 2005 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/liujing/articles/5788.html</guid><wfw:comment>http://www.blogjava.net/liujing/comments/5788.html</wfw:comment><comments>http://www.blogjava.net/liujing/articles/5788.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liujing/comments/commentRss/5788.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liujing/services/trackbacks/5788.html</trackback:ping><description><![CDATA[<P>大多数的表单交互中，用户都需要看到操作的结果。以一致的方式显示错误和信息是一个好的框架应该具备的功能。在前面一节中，我们讨论了通过消息资源对象本地化消息。通过名/值对让消息资源对象和属性文件对应。一个基于struts的应用会在处理资源包之前在ActionErrors对象中收集和查找，确认和通知信息。下面的图示解释了struts中涉及到错误处理机制的类。</P>
<P><IMG alt=" " src="http://storage.msn.com/x1pqP5noGPWAA6sGj8HSz8CqcDMUmOGZDKHo7MkoXxyB5K28gWLCY73Ip_HgMlIWOynfTVPSXhjM62VZ8aQLxtncuaBLTiLVJ2B7WO9_MIf3rcBtY19InnVtwasSFgg-EoRI0Z65k0iB7NMSREejD98YA" onload="function anonymous()&#13;&#10;{&#13;&#10; img_auto_size(this,450,true);&#13;&#10;}" align=baseline></P>
<P>我们将简单的讨论前面解释的交互动作。我们将看到struts怎样从本地特定消息中获得消息key，又怎么在视图中以一致的方式得到处理。我们将用jsp作为视图组件。</P>
<P>&nbsp;&nbsp;&nbsp; 用ActionError标识错误</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实现Action.execute(…)&nbsp;或 ActionForm.validate(…)方法，应该可以捕捉验证和应用程序特定错误到ActionErrors对象中，他们组成了ActionError对象。一个ActionError对象有一个消息key和一个可选对象用来存放动态返回的消息。参考上一节的相关信息，一个ActionErros对象不用关心本地化和相关的资源包就可以创建。我们可以处理118N当ActionError对象处理消息时。可以参考ActionErrorAPI获得完全的创建ActionError对象的方法列表。一旦一个ActionError对象创建，就应该使用ActionError对象的ActionError.add方法添加到ActionError对象组中，并且传递ActionError和检测到校验错误的属性名。为了保存错误消息而不关联到属性，可以用ActionErrors.GLOBAL_ERROR代替属性参数。使用属性名创建ActionError对象在ActionErrors一节解释。ActionError类扩展ActionMessage类；和struts1.1一样，ActionError类简单的把调用委托给ActionMessage类。</P>
<P>&nbsp;&nbsp;&nbsp; 用ActionErrors管理错误</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ActionErrors对象使用HashMap方式管理所有ActionError对象，名是消息属性名，值是ActionMessageItem对象。ActionMessageItem作为inner类声明在ActionMessages中。每一个ActionMessageItem对象由一个唯一的序列号和一个包含属性对应所有校验错误的的ArrayList对象组成。序列号用来排序ActionMessageItem集合，其中的校验错误通过开始标记为invalid的属性获得。ActionErrors.get返回一个ArrayList的迭代器，其中容纳了ActionError对象集合。这个迭代对象通过定制ErrorsTag标签引用，将在下节解释。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在请求处理器，比如在Action.execute中，ActionErrors应该用属性名Action.ERROR_KEY保存到HttpServletRequest中；这个操作通过调用action基类的saveErrors方法，传递请求对象和ActionErrors对象作为参数。ActionErrors作为ActionForm.validate(…)的结果产生，由在请求对象中的RequestProcessor使用Action.ERROR_KEY保存。下一个视图可以用ErrorsTag来获得ActionErrors对象；ErrorsTag可以用在jsp中。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ActionErrors类扩展了actionMessages类。ActionErrors提供了静态成员GLOBAL_ERROR，ActionMessages提供了静态成员GLOBAL_MESSAGE，这些静态成员当消息不是特定属性时可以作为keys用。如果要保存ActionMessages对象到请求处理对象中，传递请求对象和ActionMessages对象给Action.saveMessages(…)方法即可；Action.saveMessages(…)对象使用Action.MESSAGE_KEY保存到请求对象中。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果想简单的获得消息keys，不用属性和动态参数，可以用org.apache.struts.util.RequestUtils.getActionErrors(…)方法转换一个String对象，String数组，或一个ErrorMessages对象（Vector）到一个ActionErrors对象中。对于这种方式，getActionErrors(…)会用ActionErrors.GLOBAL_ERROR代替属性参数。</P>
<P>&nbsp;&nbsp;&nbsp; 用ErrorsTag显示错误</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个定制的标签显示消息到HTML文档中。它使用Action.ERROR_KEY从HttpServletRequest中获得ActionErrors对象，然后使用ActionErrors.get()方法获得容纳ActionError对象的ArrayList的迭代器。对ArrayList中的每一个ActionError对象，一个本地消息被写到response流中。默认使用session中的本地对象；但是可以在标签中定义相反的本地属性。默认情况下，资源包用Action.MESSAGES_KEY保存到上下文中，除潜昵┒ㄒ辶似渌粜浴Ｒ孕枰哺亲试窗绻桓鲆陨系幕咀试次募枰芾硎薄：蛃truts1.1一样，一个ErrorsTag仅能使用一个资源包家族（有相同的基本名称），因此在ActionErrors对象中的所有错误应该在资源包家族中都可以找到。因为ActionErrors对象中的所有ActionError对象都用属性名登记了，消息可以通过在ErrorsTag中定义一个属性名对应。ErrorsTag使用消息keys‘errors.header’和‘errors.footer’提供错误消息显示的标题和格式。</P><img src ="http://www.blogjava.net/liujing/aggbug/5788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liujing/" target="_blank">塞翁</a> 2005-06-09 09:09 <a href="http://www.blogjava.net/liujing/articles/5788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FastTrackToStruts 5 异常处理</title><link>http://www.blogjava.net/liujing/articles/5789.html</link><dc:creator>塞翁</dc:creator><author>塞翁</author><pubDate>Thu, 09 Jun 2005 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/liujing/articles/5789.html</guid><wfw:comment>http://www.blogjava.net/liujing/comments/5789.html</wfw:comment><comments>http://www.blogjava.net/liujing/articles/5789.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liujing/comments/commentRss/5789.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liujing/services/trackbacks/5789.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp; 除了错误处理机制以外，一个表示层框架必须提供本地异常信息的显示和反馈机制。一个可行的方式是捕获实际的异常和错误内容到日志文件中然后发送一个有意义的信息帮助用户决定适当的操作。在jsp中没有捕获的异常，都将由jsp1.2规范定义的错误页面机制处理。类似的，在servlets中没有处理的异常将由web.xml定义的errorpage属性处理。struts提供了一个简单的机制，这个机制使用相同的错误页面机制处理jsp和servlet容器的未处理的异常。struts-config.xml文件例子略。<BR>&nbsp;&nbsp; 异常处理机制是建立在错误处理机制的基础上的，因此也是使用消息资源提供本地消息信息。下面的图示解释了struts涉及到异常处理机制的类关系。<BR><IMG alt=" " src="http://storage.msn.com/x1pqP5noGPWAA6sGj8HSz8CqcDMUmOGZDKHo7MkoXxyB5Kqopq8d51Jbjy1xydo86Vk06q9jC69TnZNhxZE553t9AO7Zx0d1rDKRC2vDidv9X2BQ_yb74rSG5PKpOJxwQN8m42w9tXbaAWNJNwjTTsBKw" onload="function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10; img_auto_size(this,450,true);&#13;&#10;}&#13;&#10;}&#13;&#10;}&#13;&#10;}&#13;&#10;}" align=baseline></P>
<P>&nbsp;&nbsp;&nbsp; 分派的角色<BR>&nbsp;&nbsp;&nbsp; 就像在RequestProcessor一节讨论的一样，request processor调用request handler的execute方法。任何request handler抛出的异常都被RequestProcessor捕获然后在strutsconfig.xml中找到可能的<EXCEPTION />匹配。RequestProcessor会调用ActionMapping.findException方法找到一个ExceptionConfig配置对象（是<EXCEPTION />元素的运行时表现形式），它的类型属性匹配异常类型。如果找不到一个<EXCEPTION />配置，findException方法会一直沿着超类找匹配到最顶层类的匹配。ActionMapping.findException会在本地范围和全局范围的ActionMapping对象搜索<EXCEPTION />元素。下面是一个全局对象<EXCEPTION />元素定义的例子略。<BR>&nbsp;&nbsp;&nbsp; 异常处理AppException<BR>&nbsp;&nbsp;&nbsp; 在request handlers中这是一个创建exceptions的基类。它封装了异常发生原因属性（）和相关的ActionError对象。一个AppException的子类可以提供合适的构造函数，通过可选的属性名和对象参数，用消息key正确初始化对象。消息key可以从和异常对应的ExceptionConfig对象中获得。涉及到AppException的API是构造函数列表（可以被子类调用），AppException作为ExceptionHandler.execute的方法参数传递的。</P>
<P>&nbsp;&nbsp;&nbsp; 转换异常到ActionErrors中<BR>&nbsp;&nbsp;&nbsp; RequestProcessor查询ExceptionConfig的异常处理定义。RequestProcessor创建特定的ExceptionHandler并调用它的execute方法并传AppException作为参数。org.apache.struts.action.ExceptionHandler的一个默认的异常处理是预先配置在ExceptionConfig对象中的。ExceptionHandler从AppException对象获得ActionError对象，然后根据ErrorsTag创建ActionErrors对象使用。如果异常不是AppException类或其继承类，ExceptionHandler会用定义的<EXCETION>元素创建一个ActionErrors对象。这样就减轻了请求处理的开发人员写额外的异常处理代码。然而这样就限制了框架仅能调用ActionError的一个构造函数，接收一个key参数值。如果需要可以用<EXCEPTION>元素覆盖默认的异常处理。ExceptionHandler类或其子类会使用ExceptionConfig中的路径属性创建一个ActionForward对象。如果该路径没有定义，那么就会使用ActionMapping配置对象中的输入属性中定义的路径。ExceptionHandler也用Action.EXCEPTION_KEY保存原始的异常到请求对象中。一个视图可以用任何方式自由处理这个信息。Action.EXCEPTION_KEY也可以被servlet容器的错误页面机制使用来获得根据原始异常重新抛出的异常。</P><img src ="http://www.blogjava.net/liujing/aggbug/5789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liujing/" target="_blank">塞翁</a> 2005-06-09 09:09 <a href="http://www.blogjava.net/liujing/articles/5789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FastTrackToStruts 6 表单提交一次</title><link>http://www.blogjava.net/liujing/articles/5790.html</link><dc:creator>塞翁</dc:creator><author>塞翁</author><pubDate>Thu, 09 Jun 2005 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/liujing/articles/5790.html</guid><wfw:comment>http://www.blogjava.net/liujing/comments/5790.html</wfw:comment><comments>http://www.blogjava.net/liujing/articles/5790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liujing/comments/commentRss/5790.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liujing/services/trackbacks/5790.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp;&nbsp; 开发基于浏览器的客户端总是会遇到表单重复提交的问题。很明显的在一个商业应用中重复提交是不希望发生的。struts提供一个机制，使用Action基类的generateToken方法产生一个token来保护模型层避免受到表单多次提交的影响。为了控制事务的完整性和原子性，在使用ActionForward选择下一个视图前要调用request handler的saveToken方法。saveToken方法调用generateToken方法创建一个唯一标识符，然后用Action.TRANSACTION_TOKEN_KEY保存到session中。表单标签从session中获得token然后用Constants.TOKEN_KEY保存到隐藏字段中。在接下来的请求中，request handler通过调用action基类的isTokenValid方法检查token的合法性。如果该方法返回false，request handler必须实现合适的逻辑处理遇到的问题。一个处理的例子如下所示：<BR>&nbsp;&nbsp;&nbsp; if (!isTokenValid(request)) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errors.add(ActionErrors.GLOBAL_ERROR,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new ActionError("transaction.token.invalid"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //errors object is of type ActionErrors<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; isTokenValid同步处理session对象的token来阻止表单重复提交请求。在request handlers中，isTokenValid方法必须跟一个resetToken来从session中移除token;这样可以保证任何后续请求都将导致isTokenValid返回fa，因此组织表单多次提交。request handler的saveToken方法应该被调用来重建一个新的事务token满足下次的请求。<BR>&nbsp;&nbsp;&nbsp; 获得表单数据<BR>&nbsp;&nbsp;&nbsp; jsp规范使用<USEBEAN />和<SETPROPERTY />在请求时的JavaBeans中提取和存储表单数据。然而，这种方式使表现层和JavaBeans强耦合；而且HTML文档的创建者还必须知道这些组件以及他们在页面中的正确用法。因为JavaBeans能够通过<USEBEAN />标签或另一个服务器组件在一个特定的范围创建和使用，这样可能会造成在不同组件共享的JavaBean的生命周期管理产生问题。struts提供了一个机制提取，存储，校验表单数据。同时也客服了<USEBEAN />和<SETPROPERTY />的缺点。例子略。<BR>&nbsp;&nbsp;&nbsp; 例子映射一个JavaBean类型为packageName.customerProfileForm用name=customerProfileForm (唯一标识)，name=customerProfileForm; request handler通过输入请求中的路径/editCustomerProfile唯一标识。 表单的创建和使用在下面的图片中解释。<BR><IMG alt=" " src="http://storage.msn.com/x1pqP5noGPWAA6sGj8HSz8CqcDMUmOGZDKHo7MkoXxyB5Jb3SYQxF_osBhWfmlCPrN8mC2bX8MEsOP6KOh6Ou5T9UVl7-HQ2d7wXu477OV-htdrsb5a7JaH8FR6SJO04BMmTRsXnutVV5b_0mD6umZGbg" onload="function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10; img_auto_size(this,450,true);&#13;&#10;}&#13;&#10;}&#13;&#10;}&#13;&#10;}" align=baseline></SETPROPERTY /></USEBEAN /></USEBEAN /></SETPROPERTY /></USEBEAN /></P>
<P><USEBEAN /><SETPROPERTY /><USEBEAN /><USEBEAN /><SETPROPERTY />&nbsp;&nbsp;&nbsp; 首先，我们将用一个简单的JavaBeans对象研究表单的处理机制。这些对象是作为ActionForm对象实现的。我们接下来要讨论使用DynaActionForm进行表单处理，这个DynaActionForm对象能够支持才请求时动态设置属性。</P>
<P><BR>&nbsp;&nbsp;&nbsp; 用FormTag初始化ActionForm对象<BR>&nbsp;&nbsp;&nbsp; 用前面介绍的方式FormTag初始化ActionForm对象，在HTML表单中的action URL对应<ACTION />配置节点，该节点通过<FORM-BEAN />配置对于formbean。FormTag的action属性定义的URL通过配置描述文件中的<URL-PATTERN />的路径结构转换成URL。通过扩展名映射，实现了用<URL-PATTERN作为资源的扩展名。因此一个URL editcustomerprofile?customertype="preferred将会转换为/editCustomerProfile.do?customerType=preferred。<br" />&nbsp;&nbsp;&nbsp; FormTag调用RequestUtils.createActionForm方法，该方法通过名字匹配<ACTION />元素的名字来搜索ActionFormBean配置对象（(ActionFormBean是运行时<FORMBEAN />表现形式）。使用<FORM-BEAN />元素创建一个新的ActionForm实例，如实例存在，则FormTag会在存在的form bean调用ActionForm.reset方法清除数据，为下一次请求的表单数据做准备。范围定义在<ACTION />元素的scope属性中；新的ActionForm实例或者重新初始化的实例保存在该属性定义的范围中。</P>
<P><BR>&nbsp;&nbsp;&nbsp; 用ActionForm存储表单数据&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 被继承的ActionForm对象是用来存放表单请求对象参数的，因此他们是和用户紧耦合的。一个ActionForm子类是一个带属性存取方法的JavaBean，这些属性与HttpServletRequest对象的参数对应。如果一个ActionForm对象通过FormTag创建（前面介绍了），那么在接下来通过FormTag解析的表单请求将由RequestProcessor在特定范围处理。表单通过相关的action映射标识找到。RequestProcessor为重置表单属性，通常表单带有请求时间参数，然后调用表单对象的validate方法完成服务端校验用户输入。仅当ActionMapping对象的校验属性设为true时，validate方法才会被调用。这是一个默认的行为。使用request.getParameterValues(parameterName)获得一个String数组对象，这个对象用来存放表单数据；在请求参数类型转换一节将做解释。校验结构是一个ActionErrors对象（在错误处理一节解释了），它使用org.apache.struts.taglib.html.ErrorsTag显示校验错误给用户。ActionForm也能存储中间层模型状态，这些状态数据接下来会视图（jsp）引用并展示给用户。<BR>&nbsp;&nbsp;&nbsp; 一个ActionForm类也可以被RequestProcessor创建。这种情况发生在导航到URL，该URL映射到控制器servlet而不是jsp，相关的action映射定义了表单属性。在这种情况下，RequestProcessor搜索form bean的尝试会导致创建一个新的ActionForm对象，如果在特定范围没有找到的话，或者在特定范围通过<ACTION />元素的名字属性找到ActionForm对象；当一个表单对象被RequestProcessor找到，将传递给请求处理对象的execute方法。一个ActionForm对象也能被请求处理器创建。<BR>&nbsp;&nbsp;&nbsp; 表单对象的创建的目的是为了提供中间层模型状态给jsp时应该使用请求范围；这样可以保证在他们的有效性过期后对象不会再被使用。默认的所有表单保存在session范围。在session中存在的表单对象超过了他们的有效性范围会导致浪费内存，因此，请求处理者必须跟踪存储在session中的表单对象的生命周期。获得表单数据的一个好的实践是用单一的form bean关联跨越服务端用户交互的表单。form beans也能够存储中间层模型状态，这个状态在相应用户时，通过定制的标签适配到用户视图中。标签用来避免在视图层混合java代码，因此导致了一个好的分工，web开发团队处理标记，应用开发团队处理java代码。标签区分了中间层处理逻辑；这些逻辑可能相当复杂，比如处理嵌套对象或通过集合迭代对象。<BR><BR>&nbsp;&nbsp;&nbsp; 用动态属性创建ActionForm对象<BR>&nbsp;&nbsp;&nbsp; DynaActionForm对象是带动态集合属性的对象。DynaActionForm扩展了ActionForm对象；通过在struts-config.xml文件中声明来创建form对象。例子略。RequestProcessor创建，操作，校验DynaActionForm的方式和操作ActionForm是一致的，也就是说对于在DynaActionForm的动态属性（定义在<FORM-BEAN />元素的动态集合属性），请求对象参数是可操作的。其它参数被简单跳过。</P>
<P>&nbsp;&nbsp;&nbsp; 请求参数类型转换<BR>&nbsp;&nbsp;&nbsp; 这节讨论request.getParameterValues(parameterName)获得的String数组类型怎样转换到表单对象的对应属性类型上。下面是支持的目标类型列表。<BR>java.lang.BigDecimal<BR>java.lang.BigInteger<BR>boolean and java.lang.Boolean<BR>byte and java.lang.Byte<BR>char and java.lang.Character<BR>double and java.lang.Double<BR>float and java.lang.Float<BR>int and java.lang.Integer<BR>long and java.lang.Long<BR>short and java.lang.Short<BR>java.lang.String<BR>java.sql.Date<BR>java.sql.Time<BR>java.sql.Timestamp<BR>&nbsp;&nbsp;&nbsp; 目标类型，也就是说和表单对象属性关联的类型,是通过自省机制找到的；一个特定struts定制的自省机制是在DynaActionForm对象中使用的。struts也支持索引属性，parameterName[n];索引从0开始。这种命名转换的form bean的方法是通过按照下面定义的javabeans规范描述的，使用了索引属性模式。下面的方法用来处理所有的索引属性的数组元素。<BR>public <PROPERTYTYPE />[] get<PROPERTYNAME />();<BR>public void set<PROPERTYNAME />(<PROPERTYTYPE />[] value);<BR>下面的方法是用来处理单独的数组元素<BR>public <PROPERTYTYPE />get<PROPERTYNAME />(int index)<BR>public void set<PROPERTYNAME />(int index, <PROPERTYTYPE />value)<BR>下面描述了使用简单的属性和索引属性的语法。<BR>&nbsp;&nbsp;&nbsp; 1.当bean的属性是数组，且请求参数名没有使用索引符号parameterName[n]时，由request.getParameterValues(parameterName)返回的String[]将转换成目标组件类型的数组。由struts框架内部实现该方法。ActionForm子类应该定义下面的方法声明。<BR>public void set<PROPERTYNAME />(<PROPERTYTYPE />[] value)<BR>public <PROPERTYTYPE />[] get<PROPERTYNAME />();<BR>&nbsp;&nbsp;&nbsp; 2.当bean的属性是数组,且请求参数名使用索引符号parameterName[n],由request.getParameterValues(parameterName)返回的String[]将被认为仅容纳一个简单的值；仅String[0]被转换成数组的组件类型。由struts框架内部实现该方法。ActionForm子类应该定义下面的方法声明来接收索引参数。<BR>public void set<PROPERTYNAME />(int index, <PROPERTYTYPE />value)<BR>public <PROPERTYTYPE />get<PROPERTYNAME />(int index)<BR>上面的方法声明遵循了javabeans规范中定义的索引属性设计模式。当这些方法都没有时，通过实现下面的方法也可以处理索引存取属性。<BR>public <PROPERTYTYPE />[] get<PROPERTYNAME />();<BR>在这个场景中，请求数组的读写是通过struts框架处理，首先获得根本的数组对象然后处理给定序号的元素。这个模式也支持基于list的请求参数实现，使用parameterName[n]访问。<BR>&nbsp;&nbsp;&nbsp;&nbsp; 3.对于简单的属性类型，由request.getParameterValues(parameterName)返回的String[]将被认为仅容纳一个简单的值；仅String[0]被转换成目标类型。由struts框架内部实现该方法。对于简单的属性,ActionForm子类应该定义下面的方法声明。<BR>public void set<PROPERTYNAME>(<PROPERTYTYPE> value)<BR>public <PROPERTYTYPE>get<PROPERTYNAME>();<BR>struts绑定的标签库提供了处理简单属性和索引属性的方式；org.apache.struts.taglib.nested包容纳了这些标签。struts中的完全的标签列表请参考<A href="http://jakarta.apache.org/struts/userGuide/index.html">http://jakarta.apache.org/struts/userGuide/index.html</A>; 更多的资源请参考<A href="http://jakarta.apache.org/struts/resources/index.html">http://jakarta.apache.org/struts/resources/index.html</A>. struts将来的趋势是采用JSTL和<BR>JSF上。</SETPROPERTY /></USEBEAN /></USEBEAN /></SETPROPERTY /></USEBEAN /></P><img src ="http://www.blogjava.net/liujing/aggbug/5790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liujing/" target="_blank">塞翁</a> 2005-06-09 09:09 <a href="http://www.blogjava.net/liujing/articles/5790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FastTrackToStruts 2 Struts MVC 语义</title><link>http://www.blogjava.net/liujing/articles/5786.html</link><dc:creator>塞翁</dc:creator><author>塞翁</author><pubDate>Thu, 09 Jun 2005 01:08:00 GMT</pubDate><guid>http://www.blogjava.net/liujing/articles/5786.html</guid><wfw:comment>http://www.blogjava.net/liujing/comments/5786.html</wfw:comment><comments>http://www.blogjava.net/liujing/articles/5786.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liujing/comments/commentRss/5786.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liujing/services/trackbacks/5786.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp;&nbsp; 让我们开始看看struts的核心，这也是MVC框架的核心。Struts用the Service to Worker模式[Core]实现了MVC模式.</P>
<P>&nbsp; <IMG alt=" " src="http://storage.msn.com/x1pqP5noGPWAA6sGj8HSz8CqcDMUmOGZDKHo7MkoXxyB5KHnd8TWmTJ8HjeDEBc6Pl0hpE5-IBUugWjJHV0AN8Diaaip0eEurhuvHY6DedGDg-szbg53qC41C9bloZ9bE2QcGCRHuLHJNcbhM7IK95HRA" onload="function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10;function anonymous()&#13;&#10;{&#13;&#10; img_auto_size(this,450,true);&#13;&#10;}&#13;&#10;}&#13;&#10;}&#13;&#10;}&#13;&#10;}" align=baseline></P>
<P>控制器对象</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 控制器实现了ActionServlet类。它集中处理所有客户端的请求。它清晰的划分了控制层的作用，处理视图和导航管理，保留模型处理和操作给请求处理器（Command objects[Gof]）处理。发布文档中定义了所有输入请求映射到中央控制器的描述，如下：</P>
<P>&nbsp; <SERVLET /><BR>&nbsp;&nbsp;&nbsp;&nbsp; <SERVLET-NAME />action</SERVLET-NAME /><BR>&nbsp;&nbsp;&nbsp;&nbsp; <SERVLET-CLASS />org.apache.struts.action.ActionServlet</SERVLET-CLASS /><BR>&nbsp; </SERVLET /></P>
<P>&nbsp; 所有URIs请求以do结尾的都映射到servlet中，如下：</P>
<P><SERVLET-MAPPING /><BR>&nbsp; <SERVLET-NAME />action</SERVLET-NAME /><BR>&nbsp; <URL-PATTERN />*.do</URL-PATTERN /><BR></SERVLET-MAPPING /></P>
<P>匹配该模式的表单请求如下所示：</P>
<P><A href="http://www.my_site_name.com/mycontext/actionName.do">http://www.my_site_name.com/mycontext/actionName.do</A></P>
<P>映象前缀叫做扩展映象，然而，你也可以定义路径映象用/*结尾，如下</P>
<P><SERVLET-MAPPING /><BR>&nbsp; <SERVLET-NAME />action</SERVLET-NAME /><BR>&nbsp; <URL-PATTERN />/do/*</URL-PATTERN /><BR></SERVLET-MAPPING /></P>
<P>对应请求：<A href="http://www.my_site_name.com/mycontext/do/action_Name">http://www.my_site_name.com/mycontext/do/action_Name</A></P>
<P>通过配置文件可以不用改变程序代码就可以改变映射的方式；这个映射方案也涉及到Mulitplexed Resource Mapping。对于所有表现层请求，控制器提供了一个集中处理点。控制器委托请求处理器处理每一个请求。请求处理器分配请求到相关的form bean处理表单校验，处理模型。控制器和请求处理器的联合构成了控制器处理机制的核心。由控制器提供的这种抽象减轻了开发人员创建公共应用程序服务比如管理视图，sessions，表单数据的劳动。开发人员可以遵循标准的机制处理例如：错误异常处理，导航，国际化，数据验证，数据转换等。</P>
<P>&nbsp;&nbsp;&nbsp; 在Struts1.1中，struts的配置通过控制器的init方法加载。配置文件控制框架的行为；包括使用ActionMapping配置对象映射URIs 到请求处理器，配置消息资源，通过插件处理外部资源等。实际上ActionServlet委托所有输入请求给RequestProcessor，由它实际处理所有请求。</P>
<P>分配器对象</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; RequestProcessor把请求处理器和关联的form bean联合提供分派和处理客户请求的功能。form bean的错误创建，抛出异常和请求处理器都由RequestProcessor处理，并影响RequestProcessor的视图管理函数。form beans协助RequestProcessor存储表单数据，或者传递视图需要的模型数据。通过struts－config.xml的<ACTION />配置。所有请求被控制器委托给分配器，分配器是RequestProcessor对象。RequestProcessor根据action标识检查请求URI，利用ActionMapping配置对象（下一节介绍）的信息创建请求处理对象，调用requesthandler.execute方法。该方法和应用程序的模型交互。根据处理结果，请求处理器会返回一个ActionForward配置对象（ActionForward是带有<FORWARD />元素的运行时表示，在使用ActionForward导航一节解释）给RequestProcessor。它会使用ActionForward对象通过调用RequestDispatcher.forward方法或response.sendRedirect方法激活下一个视图。</P>
<P>ActionMapping的命令模式（译注：本节翻译从简，因为涉及到具体语法。）</P>
<P>&nbsp;&nbsp;&nbsp; struts通过xml语法指定URI和servlet的映射。这个实现和GOf的命令模式非常相似。</P>
<P>模型和RequestHandlers的交互</P>
<P>&nbsp;&nbsp;&nbsp; Action的子类用来适配请求和模型。一个Action的子类也叫request handler，根据具体请求创建。一个action由RequestProcessor最先解释，并返回一个相关的request handler。对应每个请求创建的action的父类由分配器对象创建。request handler实现了命令模式。一个客户端请求在URI中封装了想要的行为，路径信息由分配器（RequestProcessor）提取并创建一个相关的请求处理对象实例。命令模式解耦请求处理和UI。</P>
<P>&nbsp;&nbsp; 基本的Action类提供了公用的函数处理框架相关的资源和方法，保存子类execute方法执行时检测到的错误。这些错误通过使用在用ErrorsTag显示错误一节介绍的定制的org.apache.struts.taglib.html.ErrorsTag显示在html表单中。request handler的execute方法应该包含控制流程处理请求参数和相关联的ActionForm，它应该封装模型交互语法，提供基于模型操作结果的下一个视图。Request handlers由RequestProcessor在第一次创建时缓存，给其它请求使用；因此request handlers不能够包含用户特殊的状态信息；而且当需要串行处理时，request handlers必须加上同步机制处理资源。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于分布式应用来说，一个action类包含和EJB组件中的业务逻辑交互的控制逻辑，类似于业务委托对象。业务委托使得request handlers不用直接处理复杂的分布式组件。因为处理服务端组件的逻辑被嵌入到业务委托中，所以业务委托设计模式使request handlers 和服务端组件松耦合。一个request handler由开发人员在表示层编写，然而一个业务委托通常由开发人员在创建业务层服务时编写。对于小的非分布式应用，action类可以包含业务逻辑。当不需要分布式处理和业务逻辑嵌入到request handlers中时，数据处理对象[Core]可以被用来提取数据处理的实现；它提供了request handlers和数据处理层松耦合，因此保证表示层不用实现中间层的变化。action的基类提供了方便的方法，请参考<A href="http://jakarta.apache.org/struts/api/index.html">http://jakarta.apache.org/struts/api/index.html</A>.的API文档</P>
<P>&nbsp; &nbsp; 用ActionForward导航</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; ActionForward对象是配置对象。这些配置对象都有基于有意义名称比如'success','failure'等的唯一标识符保证可以被找到。request handlers使用封装了URL路径的ActionForward对象识别目的视图。ActionForward对象根据struts-config.xml的<FORWARD />元素创建。例子略。</P><img src ="http://www.blogjava.net/liujing/aggbug/5786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liujing/" target="_blank">塞翁</a> 2005-06-09 09:08 <a href="http://www.blogjava.net/liujing/articles/5786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FastTrackToStruts 3 国际化和本地支持</title><link>http://www.blogjava.net/liujing/articles/5787.html</link><dc:creator>塞翁</dc:creator><author>塞翁</author><pubDate>Thu, 09 Jun 2005 01:08:00 GMT</pubDate><guid>http://www.blogjava.net/liujing/articles/5787.html</guid><wfw:comment>http://www.blogjava.net/liujing/comments/5787.html</wfw:comment><comments>http://www.blogjava.net/liujing/articles/5787.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liujing/comments/commentRss/5787.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liujing/services/trackbacks/5787.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp; 国际化又叫118N是一种处理引擎，通过它们一个应用程序能够适应各种语言和地区而不用修改应用逻辑。为了支持国际化，一个应用必须考虑下列问题。</P>
<P>&nbsp;&nbsp; 1.文本，错误提示，异常提示，GUI组件标签必须放到资源文件中。这些资源文件容纳下面介绍的特定的信息。</P>
<P>&nbsp;&nbsp; 2.日期，时间，货币，数字，计量单位和电话号码必须基于本地参数和文化格式化显示。</P>
<P>&nbsp; 在今天的全球化市场一个带国际化支持的应用是很重要的。实现国际化功能比在程序开发完后合并多语言要方便得多。国际化类通过JDK提供的本地类处理本地显示。一个本地对象表现了一个特定地区的地理，政治，文化。下面讨论struts怎么实现国际化。</P>
<P>&nbsp;&nbsp;&nbsp; 本地对象</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; struts类提供了118N支持，用getAttribute(Action.LOCALE_KEY)从HttpSession中获得本地特定信息。本地对象使用下面介绍的几种方式保存在session中。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 使用HtmlTag：定制的标签org.apache.struts.taglib.html.HtmlTag插入到jsp中.这是也声明的方式保存。当locale为true时，标签逻辑会使用HttpServletRequest.getLocale()方法获得本地对象。getLocale方法返回客户端浏览器基于Accept－Language header接受的内容的首选本地对象。当客户端没有提供一个Accept－Language header一个默认的本地对象将返回。如果session不存在就会创建，然后本地对象将用Action.LOCALE_KEY存到session对象中。HTML标签接着使用本地对象的语言属性设置特定语言到输出流中。这种方式本地对象存储一次；以后的locale＝true的操作将不能替换session中的本地对象。这种方式最好用在用户更改浏览器本地设置时。</P>
<P>&nbsp;&nbsp;&nbsp; 使用action对象</P>
<P align=left>&nbsp;&nbsp;&nbsp; 如果要变成改变本地对象，action类提供了setLocale方法使用Action.LOCALE_KEY保存本地对象到session中。这种设置本地对象的方式最好用在用户通过点击UI组件选择HTML表单的本地化方式时。但是，如果本地化资源正在加载，而用户正在改变本地化方式时会引起错误。当一个本地化改变时最好在重置所有本地资源且可控的方式下进行。</P>
<P align=left>&nbsp;&nbsp;&nbsp; 使用<CONTROLLER />元素</P>
<P align=left>&nbsp;&nbsp;&nbsp; 在struts-config.xml文件中通过controller标签，标记RequestProcessor从</P>
<P align=left>&nbsp;&nbsp;&nbsp; <SET-PROPERTY value="true" property="locale" />HttpServletRequest对象获得本地对象，用Action.LOCALE_KEY把本地对象放到session中。如果value＝true，本地对象将通过request. getLocale()获得然后保存到session中（如果以前没有保存）</P>
<P align=left>
<P align=left>&nbsp;&nbsp;&nbsp; 国际化提示和标签</P>
<P align=left>&nbsp;&nbsp;&nbsp; 因为要支持国际化，所以所有的错误提示，指导性的提示，信息，标题，GUI组件的标签，输入标签必须必须单独保存，通过本地特定方式处理。struts框架提供了MessageResources类用来模拟JDK提供的ResourceBundle类。本地特定的资源包提供一个分离本地特定信息的方式。资源包的成员都使用一个共同的基本名字，但是名字的额外部分标识不同的本地性。默认的资源包也有同样的基本名字，没有找到匹配的本地信息时就用默认包。例如：</P>
<P align=left>&nbsp; &nbsp; 如果资源包名为MyApplicationResources，这这个包家族的成员名字会是。</P>
<P align=left>&nbsp;&nbsp;&nbsp; MyApplicationResources_en 英文包</P>
<P align=left>&nbsp;&nbsp;&nbsp; MyApplicationResources_fr 法语包</P>
<P align=left>&nbsp;&nbsp;&nbsp;&nbsp;MyApplicationResources_fr_FR&nbsp; 法国的法语包<BR>&nbsp;&nbsp; &nbsp;MyApplicationResources_fr_CA&nbsp;&nbsp; 加拿大的法语包</P>
<P align=left>&nbsp;&nbsp;&nbsp; 资源包搜索顺序如下：</P>
<P align=left>&nbsp;&nbsp;&nbsp; 1. MyApplicationResources_fr_FR&nbsp;预期的包</P>
<P align=left>&nbsp;&nbsp;&nbsp; 2. MyApplicationResources_fr&nbsp;预期包没有时找它<BR>&nbsp;&nbsp;&nbsp; 3. MyApplicationResources_en_US&nbsp;没有匹配包时用默认包<BR>&nbsp;&nbsp;&nbsp; 4. MyApplicationResources_en&nbsp;没有默认包时用它<BR>&nbsp;&nbsp;&nbsp; 5. MyApplicationResources 最基本的包</P>
<P align=left>&nbsp;&nbsp;&nbsp; struts使用MessageResources对象提供相对容易的方式实现上述的机制。MessageResources对象通过下面的属性文件定义的名/值对初始化。你只需要在struts-config.xml定义MessageResources的基本名字，就可以按一致的搜索方式处理本地资源文件。</P>
<P align=left>&nbsp;&nbsp;&nbsp;&nbsp; 配置文件中的parameter属性值声明了基本的不带本地信息的属性文件。这个基本的资源文件名为MyApplicationResources.properties，本地文件可能取名为MyApplicationResoures_localeSpecificExtension.properties.对每一个程序，我们可以定义一个或多个基本包名字。消息资源对象由控制器中的ActionServlet根据Globals.MESSAGES_KEY（和Action.MESSAGES_KEY相同）保存到ServletContext中，或者是多个消息资源时，所有消息资源对象使用<MESSAGE-RESOURCES>元素保存。为了能访问request handlers中的消息资源对象，action类提供了方便的方法Action.getResources通过消息对象特定的标识Key从ServletContext中获得消息资源。每个消息资源对象通过处理下列的本地属性文件来获得本地消息。属性文件通过配载文件参数<MESSAGE-RESOURCES>标签标识基本的消息资源名。</P>
<P align=left>&nbsp;&nbsp;&nbsp; 要获得本地消息，传递本地消息key参数给MessageResources.getMessage即可。使用Action.LOCALE_KEY可以从session中获得本地对象。当给MessageResources.getMessage提供一个对象参数，获得的消息将作为一个消息格式模式并转换为消息格式对象。消息格式对象然后调用MessageFormat.format方法同时传递被适当格式化的对象。消息格式化类不是本地特定的，因此相关消息格式模式和对象必须获得本地化信息到帐号中。消息资源API提供了许多方法处理消息；相关JavaDoc可以在<A href="http://jakarta.apache.org/struts/api/index.html">http://jakarta.apache.org/struts/api/index.html</A>查到。</P><img src ="http://www.blogjava.net/liujing/aggbug/5787.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liujing/" target="_blank">塞翁</a> 2005-06-09 09:08 <a href="http://www.blogjava.net/liujing/articles/5787.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Titles Advanced Features 1 序言</title><link>http://www.blogjava.net/liujing/articles/5784.html</link><dc:creator>塞翁</dc:creator><author>塞翁</author><pubDate>Thu, 09 Jun 2005 01:07:00 GMT</pubDate><guid>http://www.blogjava.net/liujing/articles/5784.html</guid><wfw:comment>http://www.blogjava.net/liujing/comments/5784.html</wfw:comment><comments>http://www.blogjava.net/liujing/articles/5784.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liujing/comments/commentRss/5784.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liujing/services/trackbacks/5784.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大型的web站点通常需要一套公共的外观（Look and Feel（L&amp;F）).如果这样一套外观是用代码方式写死在页面中的话，变动外观就是一场梦魇：你必须修改几乎所有的页面。在一个好的设计中，我们应该分离外观和页面内容。使用模板可以定义主要的外观：设置页头，菜单，内容，页脚。页面内容定义在一个jsp页面，不和外观打搅！通过传递页头，菜单，内容，页脚给模板，由其生成最终页面，响应页面请求！页头，菜单，页脚可能所有页面都是相同的。另外使用样式表来保证一致的颜色，格式。 
<P>&nbsp;&nbsp;web开发的 另外一个方面是经常重复做同样的事情：web站点包括许多公共部分：菜单，表单，购物车，等等。。。每次我们必须重写或拷贝粘贴同样的代码。但是当你发现一个bug或想修改代码时会发生什么呢？你必须修改所有的拷贝粘贴部分！一个解决方案就是重用组件。你总是插入同样的组件带不同的数据。现在，如果你修改组件，这个修改将应用到所有你使用组件的地方。</P>
<P>&nbsp;&nbsp;Titles允许包含模板和组件。实际上所有的机制都是相似的：你定义页面的所有部分（一个Title）。每个部分可带参数，允许动态内容，能够作为一个方法在java代码中使用。</P>
<P>&nbsp; 注意：这章的所有例子都是基于Tiles.war中/examples目录下的新例子。</P><img src ="http://www.blogjava.net/liujing/aggbug/5784.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liujing/" target="_blank">塞翁</a> 2005-06-09 09:07 <a href="http://www.blogjava.net/liujing/articles/5784.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FastTrackToStruts 1.序言</title><link>http://www.blogjava.net/liujing/articles/5785.html</link><dc:creator>塞翁</dc:creator><author>塞翁</author><pubDate>Thu, 09 Jun 2005 01:07:00 GMT</pubDate><guid>http://www.blogjava.net/liujing/articles/5785.html</guid><wfw:comment>http://www.blogjava.net/liujing/comments/5785.html</wfw:comment><comments>http://www.blogjava.net/liujing/articles/5785.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liujing/comments/commentRss/5785.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liujing/services/trackbacks/5785.html</trackback:ping><description><![CDATA[<P>简介</P>
<P>&nbsp;&nbsp;&nbsp; 这篇文章的目的是给struts用户介绍struts的好处，同时解释其配置和用法。我们会对一个健壮的表现层框架下一个定义，同时讨论struts框架如何实现这些要求。我们也探究struts中的设计模式的实现，控制器的语义，相关辅助组件的语义；当你需要设计组件和struts框架交互或者为了适应项目的特殊需要扩展struts框架时这些知识将会非常有用。本文介绍的信息可以在<A href="http://jakarta.apache.org/struts">http://jakarta.apache.org/struts</A>获得。</P>
<P>MVC架构</P>
<P>&nbsp;&nbsp;&nbsp; <IMG alt=" mvc架构" src="http://storage.msn.com/x1pqP5noGPWAA6sGj8HSz8CqcDMUmOGZDKHo7MkoXxyB5KhVddW8kGYb5YctFdx1vVUyNy_EoTQsGBJBQjuz3z-KvXrt6BAyOqyNpid-zKwvwnDuWgHyZ-QH6VHRd93XoZXp1pvr6VEeH89mO2faZMnZg" onload="function anonymous()&#13;&#10;{&#13;&#10; img_auto_size(this,450,true);&#13;&#10;}" align=baseline></P>
<P>&nbsp;&nbsp;&nbsp; mvc架构把一个应用分离为3部分：模型，视图，控制器。它通常应用于图形交互用户模型的输入，处理，输入。</P>
<P>&nbsp; 模型：一个模型表示应用程序中需要逻辑处理和操作的数据。在应用程序中任何有稳定状态的数据都应该放到模型对象中。提供模型的服务必须支持多个客户端。粗略看看模型的公共方法列表，就应该很容易明白怎么控制模型的行为。模型组织相关的数据和操作并提供特定的服务；这些操作的组合包装和抽象了业务逻辑。模型接口公布了处理模型状态的方法和封装到模型中的复杂业务逻辑的方法。模型服务通过控制器处理模型状态的查询或更改。当模型状态变化时，由模型通知视图。</P>
<P>&nbsp;&nbsp;&nbsp; 视图：视图表现模型的状态。表示层语义被封装在视图中，因此同样的模型数据可以适合多个不同类型的客户端。当模型变化并通知视图后，由视图更新自身。视图传递用户输入到控制器。</P>
<P>&nbsp;&nbsp;&nbsp; 控制器：控制器获取和转换用户输入到模型的action中。模型基于用户输入返回处理结果给控制器，由控制器选择适当的视图显示。</P>
<P>&nbsp;&nbsp;&nbsp; 在基于J2EE的应用程序中，MVC架构通过JavaBeans或EJB处理业务逻辑，并同表示层JSP分离，中间通过基于控制器的servlet联系。然而，控制器的设计必须适应不同类型的客户端，包括web客户端的HTTP请求，无线客户端的WML，供应商和业务伙伴的基于XML的文档。拿HTTP请求/相应为例，输入的HTTP请求被路由到中央控制器，由中央控制器解释和委托请求到合适的请求处理器。这个也涉及到MVC2架构。框架的请求处理器提供开发人员实现具体的业务逻辑和模型交互。依赖交互的结果，控制器可以决定下一个视图并产生一个正确的相应。</P><img src ="http://www.blogjava.net/liujing/aggbug/5785.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liujing/" target="_blank">塞翁</a> 2005-06-09 09:07 <a href="http://www.blogjava.net/liujing/articles/5785.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>