﻿<?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-badboy空间-文章分类-Framework</title><link>http://www.blogjava.net/badboy/category/5951.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:18:17 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:18:17 GMT</pubDate><ttl>60</ttl><item><title>Struts Classic 的变迁（下），从1.1到1.2 </title><link>http://www.blogjava.net/badboy/articles/46247.html</link><dc:creator>badboy</dc:creator><author>badboy</author><pubDate>Mon, 15 May 2006 09:05:00 GMT</pubDate><guid>http://www.blogjava.net/badboy/articles/46247.html</guid><wfw:comment>http://www.blogjava.net/badboy/comments/46247.html</wfw:comment><comments>http://www.blogjava.net/badboy/articles/46247.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/badboy/comments/commentRss/46247.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/badboy/services/trackbacks/46247.html</trackback:ping><description><![CDATA[
		<h1>Struts1.2.4</h1>
		<h2>新特征</h2>
		<h3>主要修改：</h3>
		<p>
				<strong>不赞成特征</strong>
				<strong>
				</strong>
				<br />Struts1.1中已经有很多构造不再赞成使用。许多已经被删除了。所以在升级到1.2.4时，请clean-compile 你的应用，并且使deprecation warnings 被打开。在升级到1.2.4之前强烈建议解决所有decprecated 的用法。最可能应用开发人员的用法是： </p>
		<ol>
				<ol>
						<li>org.apache.struts.Action statics: 如今使用org.apache.struts.Global statics 
</li>
						<li>Action.perform: 如今使用Action.execute </li>
				</ol>
		</ol>
		<p>虽然没有被删除也没有被标明为不赞成使用，最好还是将ActionErrors 替换为ActionMessages 以确保正确的操作。 <br /><strong>TagUtils </strong><strong>和</strong><strong>ModuleUtils</strong><br />许多以前在org.apache.struts.utils.RequestUtils中找到的工具方法如今移动到了org.apache.struts.taglibs.TagUtils 或org.apache.struts.utils.ModuleUtils包中。 <br /><strong>GenericDataSource / GenericConnection </strong><strong>实现被删除</strong><strong></strong><br />datasources manager 仍然支持，但是我们自己的datasource <em>implementation</em>is 并不被支持。很欢迎你插入自己的DataSource 实现，但是我们没有资源来维护我们自己的实现。如果你的容器不支持DataSource实现，推荐使用Jakarta Commons的 DBCP package。 <br /><strong>Validator </strong><strong>增强</strong><strong></strong></p>
		<ol>
				<li>ValidWhen </li>
		</ol>
		<p>Struts Validator 如今支持ValidWhen 规则，以便一个验证可以依赖于另一个验证。</p>
		<ol>
				<li>IntRange 现在可以检测select-one 和radio 字段。比如：这使得我们可以使用一些有效的选项加上一个具有诸如"Choose one" 标题并且值为"-1"的附加选项来组装一个组合框。那么当用户试图提交一个表单时，你可以检测值是否为-1，从而决定是否没有选择选项。 
</li>
				<li>你现在可以强制进行客户端Javascript 验证来检测所有约束，而不是停留在第一个错误之处。方法是设置Validator PlugIn上的一个新的属性stopOnFirstError为false。<a href="http://struts.apache.org/struts-doc-1.2.4/userGuide/dev_validator.html#stopOnFirstError"></a></li>
				<li>"required" 验证现在可以检测checkboxes, radio,select-one, 和 select-multiple 字段类型。参见修改后的Validator 示例来看如何使用这些新的特征。 
</li>
				<li>一个标准的validateUrl 规则可以让你能够检测某一个属性是否包含一个格式正确的URL。 </li>
		</ol>
		<p>
				<strong>DigestingPlugIn</strong>
				<br />一个新的标准PlugIn 可以帮助你在application范围内创建你自己的对象图（object graph）。这是创建供Action调用的业务对象的快捷方式。请参见最新的MailReader 示例来看如何使用DigestingPlugin。 <br /><strong>ModuleConfigVerifier</strong><br />虽然不是全新的，一个标准类，用来验证模块配置，位于PlugIn 包。ModuleConfigVerifier 主要确认Struts对象图的各中组件被载入。但是，开发人员可扩展此类来检查确保Struts 配置文件的内部一致性。 <br /><strong>提供了支持Maven的项目文件</strong>.<br /><strong>新的配置</strong><strong>DTD</strong><br />推荐使用<a href="http://struts.apache.org/dtds/struts-config_1_2.dtd"><font color="#56662d">struts-config_1_2.dtd</font></a>。新的DTD 添加了两个新的元素&lt;display-name&gt; 和 &lt;description&gt; 到struts-config 元素中。这些元素可用于struts配置文件工具和文档产生工具。在Struts 1.2.x 中，已有的Struts 配置文件可以使用两个版本的DTD 都可载入。 <br /><strong>新的</strong><strong>Taglib URIs</strong><br />标签库的URI已经被修改已反映Struts从Jakarta 移到了Apache 的顶级项目。为了兼容，使用旧的URI的TLD仍然有效，但是鼓励使用新的URI。 <br /><strong>Struts-Chain</strong><br />试验性的，这个新的"contrib" package 使用了Jakarta Sandbox中的Responsibilty package 的Chainin 来创建一个新的RequestProcessor的Breed。未来版本可能会成为默认实现。.<br /><strong>MappingDispatchAction</strong><br />一个新的标准Action，将控制转发到ActionMapping 参数命名的一个方法。 <br /><strong>Cancel handlers</strong><br />DispatchAction, LookupDispatchAction, 和 MappingDispatchAction ，如今提供了默认的可以覆写的cancel handler。也可以指定默认的handler name。 <br /><strong>Session-scoped ActionMessages</strong><br />现在你可以将ActionMessages 保存在session 中and have them cleaned up after the first use。现在除了Action.saveMessages() 将消息保存在session中还有了另外一种选择。在消息已经被访问过一次之后ActionMessages.isAccessed() 返回true。RequestProcessor.processCachedMessages() 查询isAccessed() 已决定是否应该将消息从session中删除。 <br /><strong>JA Mailreader</strong><br />Struts Mailreader Example 应用现在包含Japanese 资源文件。 <br /><strong>Tiles EL</strong><br />Tiles tags 如今可以通过Struts EL taglib使用EL，后者基于JSTL。 <br /><strong>Wildcard Mappings</strong><br />现在可以在actiponMapping中使用通配符。详细信息参见Struts Mailreader Example application。 <br /><strong>Action attributes</strong><br />html img tag 添加了Action 属性，以匹配html link tag。 <br /><strong>Module attribute</strong><br />Forward元素以及多个核心标签中新增一个"module" 属性。这个属性允许你通过名称（或者前缀）指定另一个模块来创建模块间的直接链接。新的module 属性优于contextRelative属性，并且可以常用于"SwitchAction"中。 </p>
		<h1>Struts 1.2.7</h1>
		<h2>主要修改</h2>
		<h3>依赖性</h3>
		<p>Struts 对下列组件的依赖性发生了改变： </p>
		<table cellspacing="0" cellpadding="0" border="1">
				<tbody>
						<tr>
								<td valign="top" width="340">
										<br />依赖性 </td>
								<td valign="top" width="340">
										<p>新的版本</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="340">
										<p>Commons BeanUtils</p>
								</td>
								<td valign="top" width="340">
										<p>Version 1.7.0</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="340">
										<p>Commons Digester</p>
								</td>
								<td valign="top" width="340">
										<p>Version 1.6</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="340">
										<p>Commons Validator</p>
								</td>
								<td valign="top" width="340">
										<p>Version 1.1.4</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="340">
										<p>Commons Collections</p>
								</td>
								<td valign="top" width="340">
										<p>removed</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="340">
										<p>Commons Lang</p>
								</td>
								<td valign="top" width="340">
										<p>removed</p>
								</td>
						</tr>
				</tbody>
		</table>
		<h3>Core Struts</h3>
		<h4>Saving Messages in the Session</h4>
		<p>在action也新增了一个方法[saveErrors(HttpSession, ActionMessages)]来将<em>errors</em> 保存在Session 中，并且在其第一次被访问之后被自动从Session中删除。这是等同于1.2.4 中message上新增的功能。 </p>
		<h4>Re-directing ActionForward</h4>
		<p>
				<em>ActionRedirect</em> 是ActionForward 的一个子类，其设计来用于重定向请求，支持在运行时添加参数。 </p>
		<h4>Download Action</h4>
		<p>
				<em>DownloadAction</em> 是一个提供了下载文件的具体细节的抽象Action。 </p>
		<h4>Dispatch Helper</h4>
		<p>
				<em>ActionDispatcher</em> 是一个提供<em>DispatchAction</em> 类型的行为但是不必继承自<em>DispatchAction</em>。 </p>
		<h4>
				<em>Lazy</em> Validator Form</h4>
		<p>
				<em>DynaBean</em> 风格的ActionForm，它不需要其属性被定义，并提供<em>Lazy List</em> 和<em>Lazy Map</em> 行为。 </p>
		<h4>jars 中的配置文件 </h4>
		<p>配置文件(如. Struts config, Validator config 和 Tiles 配置文件)现在可以被保存在jars。Struts 会像以前一样检查servlet context，但是如果没找到， Struts 会尝试classloader 去查找。 </p>
		<h3>Tag Library 改变</h3>
		<h4>Highlighting Errors</h4>
		<p>Struts现在可以使用HTML Input Tags上的<em> errorKey</em>, <em>errorStyle</em>, <em>errorStyleClass</em> 和 <em>errorStyleId</em> 属性自动高亮错误字段。 </p>
		<h4>Readonly / Disabled Forms</h4>
		<p>现在可以使用&lt;html:form&gt; tag的<em>readonly</em> 和<em>disabled</em>属性来禁止或者使全部的字段只读。<br /><strong>N.B. </strong><em>readonly</em> 属性只影响&lt;html:text&gt;, &lt;html:textarea&gt; 和 &lt;html:password&gt; as per the HTML 4 specification。 </p>
		<h4>HTML Tag Refactoring</h4>
		<p>许多<em>HTML</em>标签都被重构了，以便更易使用。</p>
		<ol>
				<li>
						<strong>添加了prepareOtherAttributes()</strong> 方法- 刚好在关闭元素之前调用，提供一个地方来渲染额外的属性。 
</li>
				<li>
						<em>name</em> 属性渲染如今在<strong>prepareName()</strong> 方法中，以便更易提供定制行为。 
</li>
				<li>
						<em>value</em> 属性如今在<strong>prepareValue()</strong> 方法中以便更易提供定制行为。 
</li>
				<li>当渲染一个属性时，这些标签现在使用属性的<em>getter</em> 而不是直接使用实际的属性，这意味着如果你想，比如覆盖TextTag的 <em>styleClass</em> ，那么一个选择是覆盖getStyleClass()方法。 
</li>
				<li>属性的渲染现在使用一个简单的 <strong>prepareAttribute()</strong> 方法来产生<em>name="attribute"</em> 格式，使多数属性渲染一个一行语句。 </li>
		</ol>
		<h4>Bundle Attribute</h4>
		<p>
				<em>bundle</em> 属性被添加到了下列标签：ButtonTag, CancelTag, CheckboxTag, FileTag, FrameTag, HiddenTag, LinkTag, MultiboxTag, PasswordTag, RadioTag, ResetTag, SelectTag, SubmitTag, TextTag, TextareaTag。 </p>
		<h4>ErrorTag</h4>
		<p>现在新增了<strong>header</strong>, <strong>footer</strong>, <strong>prefix</strong>, <strong>suffix</strong><strong>属性。</strong></p>
		<h3>Validator</h3>
		<h4>Resource Bundle Support</h4>
		<p>Validator 配置文件中(e.g. <em>validation.xml</em>)的&lt;msg&gt; 和 &lt;arg&gt; 元素的<em>bundle</em> 属性现在随同&lt;msg&gt; 的<em>resource</em> 属性一起得到支持。 <br /><em>struts-examples</em> webapp 中添加了新的页面来展示对<em>Resource Bundle </em><em>的支持。</em></p>
		<h1>Struts1.2.8</h1>
		<h2>主要改变</h2>
		<p>Struts 1.2.8 的主要改变是修正了<em>Cross Site Scripting</em> (XSS) 弱点。 </p>
<img src ="http://www.blogjava.net/badboy/aggbug/46247.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/badboy/" target="_blank">badboy</a> 2006-05-15 17:05 <a href="http://www.blogjava.net/badboy/articles/46247.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts Classic 的变迁（上），从1.0到1.1 </title><link>http://www.blogjava.net/badboy/articles/46245.html</link><dc:creator>badboy</dc:creator><author>badboy</author><pubDate>Mon, 15 May 2006 09:04:00 GMT</pubDate><guid>http://www.blogjava.net/badboy/articles/46245.html</guid><wfw:comment>http://www.blogjava.net/badboy/comments/46245.html</wfw:comment><comments>http://www.blogjava.net/badboy/articles/46245.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/badboy/comments/commentRss/46245.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/badboy/services/trackbacks/46245.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<font color="#ff0000">最近在编写Struts教程的时候，把Struts1.1到1.2的个版本变化总结了一下，希望能够从整体上把握它的变迁脉络，在开发和维护的时候也可以参考参考。</font>
				<br />
				<br />
				<br />
				<br />
				<h1>Struts1.1的修改</h1>
				<h2>新特征</h2>
				<h3>引入新的配置DTD</h3>
				<p>Struts 1.0 的配置DTD 已经不赞成使用，引入了新的struts-config_1_1.dtd。在Struts 1.1 中，已有的Struts 配置文件可以使用这两个版本的DTD载入。 </p>
				<h3>新的Commons 包依赖性</h3>
				<p>在Struts中使用了多个Apache Jarkarta commons的组件，而Commons组件并不仅仅可以用来构建Struts应用。在Struts1.1中，所使用的Commons组件已经重构来外部依赖于Jarkarta Commons项目，而不是1.0中的内部版本。 <br />下面的Commons包包括了对相应的Struts 1.0 中的类的替代： </p>
				<ol>
						<li>
								<strong>BeanUtils </strong>[org.apache.commons.beanutils]： 
<ol><li>org.apache.struts.utils.BeanUtils 
</li><li>org.apache.struts.utils.ConvertUtils 
</li><li>org.apache.struts.utils.PropertyUtils. </li></ol></li>
						<li>
								<strong>Collections </strong>[org.apache.commons.collections] 
<ol><li>org.apache.struts.util.ArrayStack 
</li><li>org.apache.struts.util.FastArrayList 
</li><li>org.apache.struts.util.FastHashMap 
</li><li>org.apache.struts.util.FastTreeMap. </li></ol></li>
						<li>
								<strong>Digester </strong>[org.apache.commons.digester] 
<ol><li>org.apache.struts.digester.*. </li></ol></li>
				</ol>
				<p>下面这几个包现在仍然被Struts框架的各种组件使用： </p>
				<ol>
						<li>
								<strong>FileUpload </strong>[org.apache.commons.fileupload] 
</li>
						<li>
								<strong>Logging </strong>[org.apache.commons.logging] 
</li>
						<li>
								<strong>Validator </strong>[org.apache.commons.validator] </li>
				</ol>
				<h3>XML解析器</h3>
				<p>
						<strong>另外，</strong>Struts 1.1 需要符合JAXP/1.1 (而不是JAXP/1.0) API的XML解析器，比如JAXP/1.1 参考实现和Xerces 1.3.1+。 </p>
				<h3>源代码</h3>
				<p>如果需要从源代码开始构建Struts，请使用Ant 1.4 以上版本。 </p>
				<h3>集成Struts Validator</h3>
				<p>一个新的Commons Validator组件被集成到Struts 1.1中，包含在新的Validator包中。 </p>
				<h3>Tiles </h3>
				<p>引入了一个新的JSP模板组装机制Tiles，通过标签库提供集成。 </p>
				<h3>Nested </h3>
				<p>Nested taglib 绑定到了Struts1.1中，增强了现有Struts标签的功能。 </p>
				<h3>新的示例应用</h3>
				<p>Struts1.1发布包中包括了针对Validator 和Tiles的新的示例。 </p>
				<h3>新的可选组件</h3>
				<p>CVS源代码库中新增了一个目录contrib，包含了很有用的，但是没有集成到标准代码基中的扩展。 </p>
				<ol>
						<li>Scaffold – 一个对Commons Scaffold 工具包扩展，旨在提供可重用的构建Web应用的类 
</li>
						<li>Struts-EL – 可选的Struts-EL taglib 使得在Struts 中使用JSTL更加容易。(需要Servlet 2.3 +容器支持) </li>
				</ol>
				<h3>Action 包的增加</h3>
				<p>基本的控制器框架 [org.apache.struts.action]新增了一下特征： </p>
				<ol>
						<li>ActionServlet 现在提供了对模块化应用的支持，并且新增了多个扩展点。 
</li>
						<li>新增了一个ActionMessages 类，支持ActionErrors功能的一个超集，可以用于通用的消息收集传递，不仅仅针对errors。 </li>
				</ol>
				<h3>Upload 包</h3>
				<p>文件上传类[org.apache.struts.upload]新增了一下特征： </p>
				<ol>
						<li>CommonsMultipartRequestHandler：这个新类使用Jakarta Commons FileUpload 包实现了文件上传。这也是Struts的默认文件上传实现。 </li>
				</ol>
				<h3>Util 包</h3>
				<p>工具（utility）类 [org.apache.struts.util]新增了以下特征： </p>
				<ol>
						<li>LocalStrings: 修正了与可替换参数相关的消息，以便它不会添加一个外来的无关的字符。 
</li>
						<li>LabelValueBean: 一个新类，定义了一个名值对的集合，可以用在&lt;html:options&gt; 和&lt;html:optionsCollection&gt;标签，或者其它地方。 
</li>
						<li>MessageResources: 转移包含在特定消息字符串中的单引号。 
</li>
						<li>computeParameters: 允许事务令牌是唯一的参数。 
</li>
						<li>RequestUtils: 在构建一个查询字符串时，修改来编码一个&amp;号。 </li>
				</ol>
				<h3>Bean Taglib </h3>
				<p>
						<em>struts-bean</em> 标签库[org.apache.struts.taglib.bean]中新增了以下特征： </p>
				<ol>
						<li>&lt;bean:write&gt;：加入了format, locale 和 bundle 属性以支持根据用户当前场所进行格式化的功能，格式化来自属性或者来自字符串资源的字符串。 
</li>
						<li>&lt;bean:cookie&gt;, &lt;bean:header&gt;, 或&lt;bean:parameter&gt;：纠正了在标签使用"multiple"属性时，所产生的脚本变量类型。 
</li>
						<li>&lt;bean:message&gt;：加入了name, property, 和scope 属性，以便消息资源key 可以动态地从一个bean 或者bean 属性获得。 </li>
				</ol>
				<h3>HTML Taglib</h3>
				<p>
						<em>struts-html</em> [org.apache.struts.taglib.html]加入了如下新特征： </p>
				<ol>
						<li>&lt;html:link&gt;: 添加了'action' 属性 
</li>
						<li>&lt;html:options&gt;: 如果'property' 属性制定的属性（property）返回null，现在标签将抛出一个错误消息指名实际问题而不是造成NPE。 
</li>
						<li>&lt;html:option&gt; 和 &lt;html:options&gt;：添加了'style' 和'styleClass' 属性。 
</li>
						<li>&lt;html:optionsCollection&gt;：新标签。提供了一个更清晰的方式来从集合组装HTML options。 
</li>
						<li>&lt;bean:message&gt;：添加了'name', 'property' 和'scope' 属性，以便消息资源key 可以动态地从bean获得。 
</li>
						<li>&lt;html:messages&gt;：新标签。可以通过新的ActionMessages 类中的一个消息集合进行迭代。 
</li>
						<li>ActionForm：现在，此标签在它初始化ActionForm Bean的时候会调用reset() 方法。它也要求被标签所实例化的bean 是ActionForm 的一个子类。 
</li>
						<li>&lt;html:image&gt;：添加了'align' attribute。 
</li>
						<li>&lt;html:img&gt;：添加了mouse 事件属性('onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout')。 
</li>
						<li>SubmitTag, SelectTag, LinkTag.java, CheckboxTag, ButtonTag, ImageTag, RadioTag, 和TextArea 标签： 添加了indexed 属性。 </li>
				</ol>
				<h3>Logic Taglib</h3>
				<p>
						<em>struts-logic</em> 标签库[org.apache.struts.taglib.logic]加入了如下新特征： </p>
				<ol>
						<li>&lt;logic:empty&gt; 和&lt;logic:notEmpty&gt;：新标签。类似于&lt;logic:present&gt; 和&lt;logic:notPresent&gt;，但对空字符串的处理不同。 </li>
				</ol>
				<h3>Template Taglib </h3>
				<p>无变化，但无赞成使用。推荐使用Tiles.<strong></strong></p>
				<h2>运性层面的改变</h2>
				<h3>加入了Config Package</h3>
				<ol>
						<li>ControllerConfig：添加了inputForward 属性以指示ActionMapping.input是一个forward 而不是URI。 
</li>
						<li>ControllerConfig：添加了forwardPattern 和inputPattern 到help 应用面模块的管理页面目录 
</li>
						<li>添加了一个新的包以提供更多的灵活性来支持控制器配置和多模块应用的支持。 </li>
				</ol>
				<h3>Action 包<br /></h3>
				<p>基本框架(org.apache.struts.action)进行了如下修改或者修正： </p>
				<ol>
						<li>Action 类中的所有常数：不赞成使用。提取到新的Globals类中。 
</li>
						<li>ActionMapping：如果模块的ControllerConfig bean [org.apache.struts.config.ControllerConfig]的inputForward 设置为true，input 属性将引用一个ActionForward 而不是模块相对的路径。 
</li>
						<li>ActionServlet：添加了convertNull 参数以在组装Form时仿真Struts 1.0 行为。如果设置为true，数值numeric Java wrapper 类类型 (如java.lang.Integer) 将默认为null (而不是0)。 
</li>
						<li>ActionServlet：添加了"config/$foo" 参数，不赞成使用包中的其他参数。 
</li>
						<li>ActionForms 和相关类：为了保存资源，现在在响应toString请求的时候使用一个StringBuffer。 
</li>
						<li>LookupDispatchAction：添加的新的标准Action，以帮助在国际化的按钮之间进行选择。 
</li>
						<li>ActionForm 类：修改来使用ActionServletWrapper 而不是暴露ActionServlet。 
</li>
						<li>ActionServletWrapper 类：添加的新类，用于ActionForm，以防止ActionServlet 的公开字符串属性被通过查询字符串改写。 
</li>
						<li>Action.MAPPING_KEY的 request 属性： 如果没有指定form bean，无条件地将选择的mapping 传递为请求属性("org.apache.struts.action.mapping.instance")。 
</li>
						<li>ActionServlet:避免了在初始化Servlet失败的时候导致的NullPointerException。 
</li>
						<li>ActionForm 类：现在是真正的serializable，因为两个非serializable 的实例变量(servlet 和multipartRequestHandler) 已经成为transient。但是，如果你的确需要序列化和解序列化这个实例，你要自己负责重设这两个属性。 
</li>
						<li>ActionMessages 和ActionErrors：The initial order a property/key is added in is now retained. 
</li>
						<li>processActionForward(): 不赞成，推荐使用processForwardConfig </li>
				</ol>
				<h3>Upload包</h3>文件上传 (package org.apache.struts.upload) [ Upload 应用的一部分]作了如下修改和修正： 
<ol><li>CommonsMultipartRequestHandler：基于Jakarta Commons FileUpload 包的文件上传的新实现。这个新实现如今是默认实现。 
</li><li>BufferedMultipartInputStream：解决了丢失字节的问题。 
</li><li>ArrayIndexOutOfBoundsException：解决了已知的错误。 
</li><li>Multipart requests：Better reporting for premature closing of input streams while reading multipart requests. 
</li><li>新行字符（New line characters）：解决了上传和新换行字符时导致的文件损坏问题。 </li></ol><h3>Utility包</h3><p>utilities (package org.apache.struts.util)发生如下修改和修正： </p><ol><li>RequestUtils：添加了对ControllerConfig 的forwardPattern, pagePattern, 和inputForward 属性的支持。 
</li><li>GenericDataSource：不赞成。修改为作为[org.apache.commons.dbpc.BasicDataSource]的一个薄的Wrapper。建议直接使用BasicDataSource 或其它兼容组件。 
</li><li>RequestUtils 类：修改为使用ActionServletWrapper而不是暴露 ActionServlet。 
</li><li>为getActionErrors 和 getActionMessages 方法添加了错误消息。 
</li><li>getActionErrors 和 getActionMessages：添加了根据基于传入的消息关键字从Request范围获取的对象来产生正确的相应对象的方法。 
</li><li>ActionErrors 或 ActionMessages：创建一个这种对象的逻辑被移到了RequestUtils中的一个工具方法。. 
</li><li>JspException 消息：现在在RequestUtils中生成。 
</li><li>ConvertUtils.convertCharacter()：现在将检测空字符串并返回默认值。 </li></ol><h3>Bean Taglib包</h3><em>struts-bean</em> c标签库 [org.apache.struts.taglib.bean]发生了如下修改和修正： 
<ol><li>&lt;html:errors&gt;：当指定了属性标签时，如果指定的属性没有发生错误，则不会输出错误。而前面的错误将总是会被输出。未来的增强版本将包括额外的属性来关闭header 或 footer。 
</li><li>将helper 方法从"private"改为 "protected" 。 </li></ol><h3>HTML Taglib 包</h3><p><em>struts-html</em> 标签库(package org.apache.struts.taglib.html)发生了如下修改和修正： </p><ol><li>FormTag：修正为，当指定了action mapping的名称时，要排除查询字符串。 
</li><li>ImgTag：如果只有一个参数，能正确地URLEncode 查询字符串参数。 
</li><li>MultiboxTag.doAfterBody():：修正为返回SKIP_BODY 而不是SKIP_PAGE。 
</li><li>Errortag：不赞成使用defaultLocale方法。 </li></ol><h3>Documentation 示例应用</h3><p>Struts Documentation 应用(对应Struts 网站的内容)发生了如下修改： </p><ol><li>重新组织了资源到单独的页面中。 
</li><li>在Tag Developers Guide中，添加了更详细的文件上传要求。 
</li><li>在Building View Components，澄清了额外的i18n 支持可以由浏览器提供，并且超出了框架的范围。 
</li><li>在Building Controller Components一节，文档 'validating' init-param，添加了各种参数的默认值，澄清了某些web.xml 设置不是Struts特定的。 
</li><li>Tag library 文档：移到User's Guide下。 </li></ol><h3>MailReader 示例应用</h3><p>Struts MailReader Example Application 发生如下修改和修正： </p><ol><li>添加了应用资源的 Russian 和Japanese 翻译，并且设置JSP的字符集为"UTF-8"以便其可以显示English 或Japanese。 
</li><li>在Struts配置文件中交换了Edit mappings的"attribute" 属性的"name" 。 
</li><li>删除了对"tour"文档中的保存的数据库数据的引用，因为这个功能已经被删除。 </li></ol><h3>Exercise Taglib 示例应用</h3><p>Struts Exercise Taglib Example Application 发生了如下修改和修正： </p><ol><li>添加了针对使用了"action"属性的&lt;html:link&gt; 的test case 。 
</li><li>添加了针对基于保存在page上下文中的集合使用&lt;html:options&gt; 和 &lt;html:optionsCollection&gt;的&lt;html:select&gt; 的test case。 </li></ol><h2>不同之处</h2><p>这里列出1.0到1.1中新增的类和已经不赞成使用的类： </p><h3>1.0中不赞成使用，1.1中已经删除的类。</h3><ol><li>删除：org.apache.struts.utils.BeanUtils, org.apache.struts.utils.ConvertUtils, and org.apache.struts.utils.PropertyUtils – 替换为org.apache.commons.beanutils 
</li><li>删除：org.apache.struts.util.ArrayStack, org.apache.struts.util.FastArrayList, org.apache.struts.util.FastHashMap, org.apache.struts.util.FastTreeMap – 替换为org.apache.commons.collections 
</li><li>删除： org.apache.struts.digester.* - 替换为org.apache.commons.digester 
</li><li>删除：struts-config.dtd – 替换为struts-config_1_1.dtd. 
</li><li>删除：omnibus "struts" taglib 和其相应的TLD – 替换为bean, logic, 和html taglib。 
</li><li>删除："form" taglib 和其相应的TLD – 替换为html taglib. </li></ol><h3>Struts 1.1新增的包</h3><ol><li>config 
</li><li>taglib.nested 
</li><li>taglib.nested.bean 
</li><li>taglib.nested.html 
</li><li>taglib.nested.logic 
</li><li>validator </li></ol><h3>Struts 1.1新增的类</h3><p><strong>action</strong></p><ol><li>ActionMessage 
</li><li>ActionMessages 
</li><li>DynaActionForm 
</li><li>DynaActionFormClass 
</li><li>ExceptionHandler 
</li><li>RequestProcessor </li></ol><p><strong>actions</strong></p><ol><li>LookupDispatchAction </li></ol><p><strong>taglib.html</strong></p><ol><li>FrameTag 
</li><li>JavascriptValidatorTag 
</li><li>MessagesTag 
</li><li>OptionsCollectionTag </li></ol><p><strong>taglib.logic</strong></p><ol><li>EmptTag 
</li><li>MessagesNotPresentTag 
</li><li>MessagesPresentTag 
</li><li>NotEmptyTag </li></ol><p><strong>upload</strong></p><ol><li>CommonsMultipartRequestHandler </li></ol><p><strong>util</strong></p><ol><li>LabelValueBean </li></ol><h3>Struts 1.1中新增的类成员</h3><p><strong>action.Action</strong></p><ol><li>ACTION_SERVLET_KEY 
</li><li>APPLICATION_KEY 
</li><li>MESSAGE_KEY 
</li><li>PLUG_INS_KEY 
</li><li>REQUEST_PROCESSOR_KEY 
</li><li>execute 
</li><li>getResources(javax.servlet.http.HttpServletRequest) 
</li><li>saveMessages </li></ol><p><strong>action.A<u>ctionServlet</u></strong></p><ol><li>configDigester 
</li><li>convertHack 
</li><li>log 
</li><li>processor 
</li><li>getInternal 
</li><li>destroyApplications 
</li><li>destroyConfigDigester 
</li><li>getApplicationConfig 
</li><li>getRequestProcessor 
</li><li>initApplicationConfig 
</li><li>initApplicationDataSources 
</li><li>initApplicationPlugIns 
</li><li>initApplicationMessageResources 
</li><li>initConfigDigester 
</li><li>methods created for backward-compatiblity only 
<ol><li>defaultControllerConfig 
</li><li>defaultFormBeansConfig 
</li><li>defaultForwardsConfig 
</li><li>defaultMappingsConfig 
</li><li>defaultMessageResourcesConfig </li></ol></li></ol><p><strong><u>taglib.html.BaseHandlerTag</u></strong><strong></strong></p><ol><li>indexed 
</li><li>setIndexed 
</li><li>getIndexed </li></ol><h3>Struts 1.0 到Struts 1.1不赞成的类</h3><p><strong>action</strong></p><ol><li>ActionException 
</li><li>ActionFormBeans 
</li><li>ActionForwards 
</li><li>ActionMappings </li></ol><h3>Struts 1.0 不赞成的类成员</h3><p><strong>action.Action</strong></p><ol><li>FORM_BEANS_KEY 
</li><li>FORWARDS_KEY 
</li><li>MAPPINGS_KEY 
</li><li>getResources() 
</li><li>perform </li></ol><p><strong>ActionServlet</strong></p><ol><li>findDataSource 
</li><li>findFormBean 
</li><li>findForward 
</li><li>findMapping 
</li><li>initDataSources 
</li><li>methods created for backward-compatiblity only 
<ol><li>defaultControllerConfig 
</li><li>defaultFormBeansConfig 
</li><li>defaultForwardsConfig 
</li><li>defaultMappingsConfig 
</li><li>defaultMessageResourcesConfig </li></ol></li></ol></div>
<img src ="http://www.blogjava.net/badboy/aggbug/46245.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/badboy/" target="_blank">badboy</a> 2006-05-15 17:04 <a href="http://www.blogjava.net/badboy/articles/46245.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>扩展Struts</title><link>http://www.blogjava.net/badboy/articles/45849.html</link><dc:creator>badboy</dc:creator><author>badboy</author><pubDate>Fri, 12 May 2006 07:21:00 GMT</pubDate><guid>http://www.blogjava.net/badboy/articles/45849.html</guid><wfw:comment>http://www.blogjava.net/badboy/comments/45849.html</wfw:comment><comments>http://www.blogjava.net/badboy/articles/45849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/badboy/comments/commentRss/45849.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/badboy/services/trackbacks/45849.html</trackback:ping><description><![CDATA[
		<span style="FONT-SIZE: 16px">作者：Sunil Patil
<p></p></span>
		<strong>
				<span style="FONT-SIZE: 16px">简介</span>
				<br />
				<br />
		</strong>
		<font size="2">我见过许多项目开发者实现自己专有的MVC框架。这些开发者并不是因为想实现不同于Struts的某些功能，而是还没有意识到怎么去扩展Struts。通过开发自己的MVC框架，你可以掌控全局，但同时这也意味着你必须付出很大的代价；在项目计划很紧的情况下也许根本就不可能实现。<br /><br />Struts不但功能强大也易于扩展。你可以通过三种方式来扩展Struts:<br /><br />1.PlugIn：在应用启动或关闭时须执行某业务逻辑，创建你自己的PlugIn类<br /><br />2.RequestProcessor：在请求处理阶段一个特定点欲执行某业务逻辑，创建你自己的RequestProcessor。例如：你想继承RequestProcessor来检查用户登录及在执行每个请求时他是否有权限执行某个动作。<br /><br />3.ActionServlet：在应用启动或关闭或在请求处理阶段欲执行某业务逻辑，继承ActionServlet类。但是必须且只能在PligIn和RequestProcessor都不能满足你的需求时候用。<br /><br />本文会列举一个简单的Struts应用来示范如何使用以上三种方式扩展Struts。在本文末尾资源区有每种方式的可下载样例源代码。Struts Validation 框架和 Tiles 框架是最成功两个的Struts扩展例子。<br /><br />我是假设读者已经熟悉Struts框架并知道怎样使用它创建简单的应用。如想了解更多有关Struts的资料请参见资源区。<br /><br /></font>
		<b>
				<span style="FONT-SIZE: 16px">PlugIn</span>
		</b>
		<br />
		<br />
		<font size="2">根据Struts文档，“PlugIn是一个须在应用启动和关闭时需被通知的模块定制资源或服务配置包”。这就是说，你可以创建一个类，它实现PlugIn的接口以便在应用启动和关闭时做你想要的事。<br /><br />假如创建了一个web应用，其中使用Hibernate做为持久化机制；当应用一启动，就需初始化Hinernate，这样在web应用接收到第一个请求时，Hibernate已被配置完毕并待命。同时在应用关闭时要关闭Hibernate。跟着以下两步可以实现Hibernate PlugIn的需求。<br /><br />1.创建一个实现PlugIn接口的类，如下：<br /><br /></font>
		<pre class="overflow" title="pre code">public class HibernatePlugIn implements PlugIn{<br />        private String configFile;<br />        // This method will be called at application shutdown time<br />        public void destroy() {<br />                System.out.println("Entering HibernatePlugIn.destroy()");<br />                //Put hibernate cleanup code here<br />                System.out.println("Exiting HibernatePlugIn.destroy()");<br />        }<br />        //This method will be called at application startup time<br />        public void init(ActionServlet actionServlet, ModuleConfig config)<br />                throws ServletException {<br />                System.out.println("Entering HibernatePlugIn.init()");<br />                System.out.println("Value of init parameter " +<br />                                    getConfigFile());<br />                System.out.println("Exiting HibernatePlugIn.init()");<br />        }<br />        public String getConfigFile() {<br />                return name;<br />        }<br />        public void setConfigFile(String string) {<br />                configFile = string;<br />        }<br />}</pre>
		<br />
		<br />实现PlugIn接口的类必须是实现以下两个方法：<br />init() 和destroy().。在应用启动时init()被调用，关闭destroy()被调用。Struts允许你传入初始参数给你的PlugIn类；为了传入参数你必须在PlugIn类里为每个参数创建一个类似JavaBean形式的setter方法。在HibernatePlugIn类里，欲传入configFile的名字而不是在应用里将它硬编码进去<br /><br />2.在struts-condig.xml里面加入以下几行告知Struts这个新的PlugIn<br /><br /><pre class="overflow" title="pre code">&lt;struts-config&gt;<br />        ...<br />        &lt;!-- Message Resources --&gt;<br />        &lt;message-resources parameter=<br />          "sample1.resources.ApplicationResources"/&gt;<br /><br />        &lt;!-- Declare your plugins --&gt;<br />        &lt;plug-in className="com.sample.util.HibernatePlugIn"&gt;<br />                &lt;set-property property="configFile"<br />                   value="/hibernate.cfg.xml"/&gt;<br />        &lt;/plug-in&gt;<br />&lt;/struts-config&gt;</pre><br />ClassName属性是实现PlugIn接口类的全名。为每一个初始化传入PlugIn类的初始化参数增加一个&lt;set-property&gt;元素。在这个例子里，传入config文档的名称，所以增加了一个config文档路径的&lt;set-property&gt;元素。<br /><br />Tiles和Validator框架都是利用PlugIn给初始化读入配置文件。另外两个你还可以在PlugIn类里做的事情是：<br /><br />假如应用依赖于某配置文件，那么可以在PlugIn类里检查其可用性，假如配置文件不可用则抛出ServletException。这将导致ActionServlet不可用。<br /><br />PlugIn接口的init()方法是你改变ModuleConfig方法的最后机会，ModuleConfig方法是描述基于Struts模型静态配置信息的集合。一旦PlugIn被处理完毕，Struts就会将ModuleCOnfig冻结起来。<br /><br /><b><span style="FONT-SIZE: 16px">请求是如何被处理的</span></b><br /><br />ActionServlet是Struts框架里唯一一个Servlet，它负责处理所有请求。它无论何时收到一个请求，都会首先试着为现有请求找到一个子应用。一旦子应用被找到，它会为其生成一个RequestProcessor对象，并调用传入HttpServletRequest和HttpServletResponse为参数的process()方法。<br /><br />大部分请处理都是在RequestProcessor.process()发生的。Process()方法是以模板方法（Template Method）的设计模式来实现的，其中有完成request处理的每个步骤的方法；所有这些方法都从process()方法顺序调用。例如，寻找当前请求的ActionForm类和检查当前用户是否有权限执行action mapping都有几个单独的方法。这给我们提供了极大的弹性空间。Struts的RequestProcessor对每个请求处理步骤都提供了默认的实现方法。这意味着，你可以重写你感兴趣的方法，而其余剩下的保留默认实现。例如，Struts默认调用request.isUserInRole()检查用户是否有权限执行当前的ActionMapping，但如果你需要从数据库中查找，那么你要做的就是重写processRoles()方法，并根据用户角色返回true 或 false。<br /><br />首先我们看一下process()方法的默认实现方式，然后我将解释RequestProcessor类里的每个默认的方法，以便你决定要修改请求处理的哪一部分。<br /><br /><pre class="overflow" title="pre code">public void process(HttpServletRequest request,<br />                        HttpServletResponse response)<br />    throws IOException, ServletException {<br />        // Wrap multipart requests with a special wrapper<br />        request = processMultipart(request);<br />        // Identify the path component we will<br />        // use to select a mapping<br />        String path = processPath(request, response);<br />        if (path == null) {<br />            return;<br />        }<br />        if (log.isDebugEnabled()) {<br />            log.debug("Processing a '" + request.getMethod() +<br />                      "' for path '" + path + "'");<br />        }<br />        // Select a Locale for the current user if requested<br />        processLocale(request, response);<br />        // Set the content type and no-caching headers<br />        // if requested<br />        processContent(request, response);<br />        processNoCache(request, response);<br />        // General purpose preprocessing hook<br />        if (!processPreprocess(request, response)) {<br />            return;<br />       }<br />        // Identify the mapping for this request<br />        ActionMapping mapping =<br />            processMapping(request, response, path);<br />        if (mapping == null) {<br />            return;<br />        }<br />        // Check for any role required to perform this action<br />        if (!processRoles(request, response, mapping)) {<br />            return;<br />        }<br />        // Process any ActionForm bean related to this request<br />        ActionForm form =<br />            processActionForm(request, response, mapping);<br />        processPopulate(request, response, form, mapping);<br />        if (!processValidate(request, response, form, mapping)) {<br />            return;<br />        }<br />        // Process a forward or include specified by this mapping<br />        if (!processForward(request, response, mapping)) {<br />            return;<br />        }<br />        if (!processInclude(request, response, mapping)) {<br />            return;<br />        }<br />        // Create or acquire the Action instance to<br />        // process this request<br />        Action action =<br />            processActionCreate(request, response, mapping);<br />        if (action == null) {<br />            return;<br />        }<br />        // Call the Action instance itself<br />        ActionForward forward =<br />            processActionPerform(request, response,<br />                                action, form, mapping);<br />        // Process the returned ActionForward instance<br />        processForwardConfig(request, response, forward);<br />    }</pre><br /><br /><br /><b>1、processMultipart(): </b>在这个方法中，Struts读取request以找出contentType是否为multipart/form-data。假如是，则解析并将其打包成一个实现HttpServletRequest的包。当你成生一个放置数据的HTML FORM时，request的contentType默认是application/x-www-form-urlencoded。但是如果你的form的input类型是FILE-type允许用户上载文件，那么你必须把form的contentType改为multipart/form-data。如这样做，你永远不能通过HttpServletRequest的getParameter()来读取用户提交的form值；你必须以InputStream的形式读取request，然后解析它得到值。<br /><br /><b>2、processPath():</b> 在这个方法中，Struts将读取request的URI以判断用来得到ActionMapping元素的路径。<br /><br /><b>3、processLocale():</b> 在这个方法中，Struts将得到当前request的Locale；Locale假如被配置，将作为org.apache.struts.action.LOCALE属性的值被存入HttpSession。这个方法的附作用是HttpSession会被创建。假如你不想此事发生，可将在struts-config.xml 文件里ControllerConfig的local属性设置为false,如下：<br /><pre class="overflow" title="pre code">&lt;controller&gt;<br />        &lt;set-property property="locale" value="false"/&gt;<br />&lt;/controller&gt;</pre><br /><br /><b>4、processContent()：</b>通过调用response.setContentType()设置response的contentType。这个方法首先会试着的得到配置在struts-config.xml里的contentType。默认为text/html，重写方法如下：<br /><pre class="overflow" title="pre code">&lt;controller&gt;<br />        &lt;set-property property="contentType" value="text/plain"/&gt;<br />&lt;/controller&gt;</pre><br /><br /><b>5、processNoCache()：</b>Struts将为每个response的设置以下三个header，假如已在struts 的config.xml将配置为no-cache。<br /><pre class="overflow" title="pre code">response.setHeader("Pragma", "No-cache");<br />response.setHeader("Cache-Control", "no-cache");<br />response.setDateHeader("Expires", 1);</pre><br /><br />假如你想设置为no-cache header，在struts-config.xml中加如以下几行<br /><pre class="overflow" title="pre code">&lt;controller&gt;<br />        &lt;set-property property="noCache" value="true"/&gt;<br />&lt;/controller&gt;</pre><br /><br /><b>6、processPreprocess()：</b>这是一个一般意义的预处理hook，其可被子类重写。在RequestProcessor里的实现什么都没有做，总是返回true。如此方法返回false会中断请求处理。<br /><br /><b>7、processMapping():</b>这个方法会利用path信息找到ActionMapping对象。ActionMapping对象在struts-config.xml file文件里表示为&lt;action&gt;<br /><pre class="overflow" title="pre code">&lt;action path="/newcontact" type="com.sample.NewContactAction"<br />        name="newContactForm" scope="request"&gt;<br />        &lt;forward name="sucess" path="/sucessPage.do"/&gt;<br />        &lt;forward name="failure" path="/failurePage.do"/&gt;<br />&lt;/action&gt;</pre><br /><br />ActionMapping元素包含了如Action类的名称及在请求中用到的ActionForm的信息，另外还有配置在当前ActionMapping的里的ActionForwards信息。<br /><br /><b>8、processRoles():</b> Struts的web 应用安全提供了一个认证机制。这就是说，一旦用户登录到容器，Struts的processRoles()方法通过调用request.isUserInRole()可以检查他是否有权限执行给定的ActionMapping。<br />        &lt;action path="/addUser" roles="administrator"/&gt;<br /><br />假如你有一个AddUserAction，限制只有administrator权限的用户才能新添加用户。你所要做的就是在AddUserAction 的action元素里添加一个值为administrator的role属性。<br /><br /><b>9、processActionForm()：</b>每个ActionMapping都有一个与它关联的ActionForm类。struts在处理ActionMapping时，他会从&lt;action&gt;里name属性找到相关的ActionForm类的值。<br /><pre class="overflow" title="pre code">&lt;form-bean name="newContactForm" <br />           type="org.apache.struts.action.DynaActionForm"&gt;<br />                &lt;form-property name="firstName"<br />                          type="java.lang.String"/&gt;<br />                &lt;form-property name="lastName"<br />                          type="java.lang.String"/&gt;<br />&lt;/form-bean&gt;</pre><br /><br />在这个例子里，首先会检查org.apache.struts.action.DynaActionForm类的对象是否在request 范围内。如是，则使用它，否则创建一个新的对象并在request范围内设置它。<br /><br /><b>10、processPopulate():：</b>在这个方法里，Struts将匹配的request parameters值填入ActionForm类的实例变量中。<br /><br /><b>11、processValidate()：</b>Struts将调用ActionForm的validate()方法。假如validate()返回ActionErrors，Struts将用户转到由&lt;action&gt;里的input属性标示的页面。<br /><br /><b>12、processForward() and processInclude()：</b>在这两个方法里，Struts检查&lt;action&gt;元素的forward和include属性的值，假如有配置，则把forward和include 请求放在配置的页面内。<br /><pre class="overflow" title="pre code">&lt;action forward="/Login.jsp" path="/loginInput"/&gt;<br />        &lt;action include="/Login.jsp" path="/loginInput"/&gt;</pre><br /><br />你可以从他们的名字看出其不同之处。processForward()调用RequestDispatcher.forward(),，processInclude()调用RequestDispatcher.include()。假如你同时配置了orward 和include 属性，Struts总会调用forward，因为forward,是首先被处理的。<br /><br /><b>13、processActionCreate()：</b>这个方法从&lt;action&gt;的type属性得到Action类名，并创建返回它的实例。在这里例子中struts将创建一个com.sample.NewContactAction类的实例。<br /><br /><b>14、processActionPerform()：</b>这个方法调用Action 类的execute()方法，其中有你写入的业务逻辑。<br /><br /><b>15、processForwardConfig()：</b>Action类的execute()将会返回一个ActionForward类型的对象，指出哪一页面将展示给用户。因此Struts将为这个页面创建RequestDispatchet，然后再调用RequestDispatcher.forward()方法。<br /><br />以上列出的方法解释了RequestProcessor在请求处理的每步默认实现及各个步骤执行的顺序。正如你所见，RequestProcessor很有弹性，它允许你通过设置&lt;controller&gt;里的属性来配置它。例如，假如你的应用将生成XML内容而不是HTML，你可以通过设置controller的某个属性来通知Struts。<br /><br /><b><span style="FONT-SIZE: 16px">创建你自己的RequestProcessor</span></b><br /><br />从以上内容我们已经明白了RequestProcessor的默认实现是怎样工作的，现在我将通过创建你自己的RequestProcessor.展示一个怎样自定义RequestProcessor的例子。为了演示创建一个自定义RequestProcessor，我将修改例子实现以下连个业务需求：<br /><br />我们要创建一个ContactImageAction类，它将生成images而不是一般的HTMl页面<br /><br />在处理这个请求之前，将通过检查session里的userName属性来确认用户是否登录。假如此属性没有被找到，则将用户转到登录页面。<br /><br /><br />分两步来实现以上连个业务需求。<br />创建你自己的CustomRequestProcessor类，它将继承RequestProcessor类，如下：<br /><br /><pre class="overflow" title="pre code">public class CustomRequestProcessor<br />    extends RequestProcessor {<br />        protected boolean processPreprocess (<br />            HttpServletRequest request,<br />            HttpServletResponse response) {<br />            HttpSession session = request.getSession(false);<br />        //If user is trying to access login page<br />        // then don't check<br />        if( request.getServletPath().equals("/loginInput.do")<br />            || request.getServletPath().equals("/login.do") )<br />            return true;<br />        //Check if userName attribute is there is session.<br />        //If so, it means user has allready logged in<br />        if( session != null &amp;&amp;<br />        session.getAttribute("userName") != null)<br />            return true;<br />        else{<br />            try{<br />                //If no redirect user to login Page<br />                request.getRequestDispatcher <br />                    ("/Login.jsp").forward(request,response);<br />            }catch(Exception ex){<br />            }<br />        }<br />        return false;<br />    }<br /><br />    protected void processContent(HttpServletRequest request,<br />                HttpServletResponse response) {<br />            //Check if user is requesting ContactImageAction<br />            // if yes then set image/gif as content type<br />            if( request.getServletPath().equals("/contactimage.do")){<br />                response.setContentType("image/gif");<br />                return;<br />            }<br />        super.processContent(request, response);<br />    }<br />}</pre><br /><br />在CustomRequestProcessor 类的processPreprocess方法里，检查session的userName属性，假如没有找到，将用户转到登录页面。<br /><br />对于产生images作为ContactImageAction类的输出，必须要重写processContent方法。首先检查其request是否请求/contactimage路径，如是则设置contentType为image/gif；否则为text/html。<br /><br />加入以下几行代码到sruts-config.xml文件里的&lt;action-mapping&gt;后面，告知Struts ，CustomRequestProcessor应该被用作RequestProcessor类<br /><br /><pre class="overflow" title="pre code">&lt;controller&gt;<br />        &lt;set-property  property="processorClass"<br />        value="com.sample.util.CustomRequestProcessor"/&gt;<br />&lt;/controller&gt;</pre><br /><br />请注意，假如你只是很少生成contentType不是text/html输出的Action类，重写processContent()就没有问题。如不是这种情况，你必须创建一个Struts子系统来处理生成image  Action的请求并设置contentType为image/gif<br /><br />Title框架使用自己的RequestProcessor来装饰Struts生成的输出。<br /><br /><b>ActionServlet</b><br /><br />假如你仔细研究Struts web应用的web.xml文件，它看上去像这样：<br /><pre class="overflow" title="pre code">&lt;web-app &gt;<br />        &lt;servlet&gt;<br />            &lt;servlet-name&gt;action=&lt;/servlet-name&gt;<br />            &lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt;<br />            &lt;!-- All your init-params go here--&gt;<br />        &lt;/servlet&gt;<br />        &lt;servlet-mapping&gt;<br />            &lt;servlet-name&gt;action&lt;/servlet-name&gt;<br />            &lt;url-pattern&gt;*.do&lt;/url-pattern&gt;<br />        &lt;/servlet-mapping&gt;<br />&lt;/web-app &gt;</pre><br /><br />这就是说，ActionServlet负责处理所有发向Struts的请求。你可以创建ActionServlet的一个子类，假如你想在应用启动和关闭时或每次请求时做某些事情。但是你必须在继承ActionServlet类前创建PlugIn 或 RequestProcessor。在Servlet 1.1前，Title框架是基于继承ActionServlet类来装饰一个生成的response。但从1.1开始，就使用TilesRequestProcessor类。<br /><br /><span style="FONT-SIZE: 16px">结论</span><br /><br />开发你自己的MVC模型是一个很大的决心——你必须考虑开发和维护代码的时间和资源。Struts是一个功能强大且稳定的框架，你可以修改它以使其满足你大部分的业务需求。<br /><br />另一方面，也不要轻易地决定扩展Struts。假如你在RequestProcessor里放入一些低效率的代码，这些代码将在每次请求时执行并大大地降低整个应用的效率。当然总有创建你自己的MVC框架比扩展Struts更好的情况。<br /><img src ="http://www.blogjava.net/badboy/aggbug/45849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/badboy/" target="_blank">badboy</a> 2006-05-12 15:21 <a href="http://www.blogjava.net/badboy/articles/45849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate2.1升级到Hibernate3.0</title><link>http://www.blogjava.net/badboy/articles/44306.html</link><dc:creator>badboy</dc:creator><author>badboy</author><pubDate>Mon, 01 May 2006 13:13:00 GMT</pubDate><guid>http://www.blogjava.net/badboy/articles/44306.html</guid><wfw:comment>http://www.blogjava.net/badboy/comments/44306.html</wfw:comment><comments>http://www.blogjava.net/badboy/articles/44306.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/badboy/comments/commentRss/44306.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/badboy/services/trackbacks/44306.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 如何把														Hibernate2.1														升级到														Hibernate3.0														？																																																选自													...&nbsp;&nbsp;<a href='http://www.blogjava.net/badboy/articles/44306.html'>阅读全文</a><img src ="http://www.blogjava.net/badboy/aggbug/44306.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/badboy/" target="_blank">badboy</a> 2006-05-01 21:13 <a href="http://www.blogjava.net/badboy/articles/44306.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate要点</title><link>http://www.blogjava.net/badboy/articles/35598.html</link><dc:creator>badboy</dc:creator><author>badboy</author><pubDate>Thu, 16 Mar 2006 03:48:00 GMT</pubDate><guid>http://www.blogjava.net/badboy/articles/35598.html</guid><wfw:comment>http://www.blogjava.net/badboy/comments/35598.html</wfw:comment><comments>http://www.blogjava.net/badboy/articles/35598.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/badboy/comments/commentRss/35598.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/badboy/services/trackbacks/35598.html</trackback:ping><description><![CDATA[原文：<A href="http://www.donews.net/dyhcn/">http://www.donews.net/dyhcn/</A> <BR>1.两种配置文件： <BR>&nbsp; A.hibernate.cfg.xml&nbsp;&nbsp; 和&nbsp;&nbsp; B.hibernate.properties 
<P>&nbsp; A中可含映射文件的配置，而B中hard codes加映射文件。</P>
<P>&nbsp; A。Configuration config=new Configuration().config(); <BR>&nbsp; B. Configuration config=new Configuration(); <BR>&nbsp;&nbsp;&nbsp;&nbsp; config.addClass(TUser.class); </P>
<P><BR>2.你不必一定用hibernate.cfg.xml或hibernate.properties这两文件名， <BR>&nbsp;&nbsp; 你也不一定非得把配置文件放在Classes下， <BR>&nbsp;&nbsp; File file=new File("c:\\sample\\myhibernate.xml"); <BR>&nbsp;&nbsp; Configuration config=new Configuration().config(file); </P>
<P>3. session.Flush() <BR>&nbsp;&nbsp; 强制数据库立即同步，当用事务时，不必用flush,事务提交自动调用flush <BR>&nbsp;&nbsp; 在session关闭时也会调用flush </P>
<P><BR>4. Hibernate总是使用对象类型作为字段类型 </P>
<P>5. XDoclet专门建立了hibernate doclet,就是在java代码上加上一些 <BR>&nbsp;&nbsp; java docTag，后来再让XDoclet分析该java代码，生成映射文件; </P>
<P>6.HQL子句本身大小写无关，但是其中出现的类名和属性名必须注意大小写区分。</P>
<P>7.关系： <BR>&nbsp; Constrained : 约束，表明主控表的主键上是否存在一个外键（foreigh key） <BR>&nbsp;&nbsp; 对其进行约束。 </P>
<P>&nbsp; property-ref:关联类中用于与主控类相关联的属性名，默认为关联类的主键属性名</P>
<P>&nbsp; 单向一对多需在一方配置，双向一对多需在双方进行配置</P>
<P>8.lazy=false:被动方的记录由hibernate负责记取，之后存放在主控方指定的 <BR>&nbsp; Collection类型属性中 </P>
<P>9. java.util.Set或net.sof.hibernate.collecton.Bag类型的Collection</P>
<P><BR>10.重要：inverse:用于标识双向关联中的被动方一端。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inverse=false的一方（主控方）负责维护关联关系.默认值：false </P>
<P>11.batch-size:采用延迟加载特征时，一次读入的数据数昨。</P>
<P>12.一对多通过主控方更新（主控方为一方时）</P>
<P>&nbsp;&nbsp; user.getAddresses().add(addr); <BR>&nbsp;&nbsp; session.save(user);//通过主控对象级联更新 &nbsp; </P>
<P>13.在one-to-many 关系中，将many 一方设为主动方（inverse=false）将有助性能 <BR>&nbsp;&nbsp; 的改善。在一方设置关系时，inverse=true,即将主控权交给多方， <BR>&nbsp;&nbsp; 这样多方可主动从一方获得foreign key,然后一次insert即可完工。 </P>
<P><BR>&nbsp;&nbsp; addr.setUser(user);//设置关联的TUser对象 <BR>&nbsp;&nbsp; user.getAddresses().add(addr); <BR>&nbsp;&nbsp; session.save(user);//级联更新&nbsp; </P>
<P>14.只有设为主控方的一方才关心（访问）对方的属性，被动方是不关心对方的属性的。</P>
<P>15.one-to-many与many-to-one节点的配置属性不同： <BR>&nbsp;&nbsp; 一对多关系多了lazy和inverse两个属性 <BR>&nbsp;&nbsp; 多对多节点属性：column:中间映射表中，关联目标表的关联字段 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class:类名，关联目标类 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outer-join:是否使用外联接&nbsp;&nbsp; &nbsp; </P>
<P>&nbsp;&nbsp; 注意:access是设置属性值的读取方式。</P>
<P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column是设置关联字段。 </P>
<P><BR>16.多对多，注意两方都要设置inverse和lazy,cascade只能设为insert-update <BR>&nbsp;&nbsp; 多对多关系中，由于关联关系是两张表相互引用，因此在保存关系状态时必须对双方同时保存。 </P>
<P>&nbsp;&nbsp; group1.getRoles().add(role1); <BR>&nbsp;&nbsp; role1.getGroups().add(group1); </P>
<P>&nbsp;&nbsp; session.save(role1); <BR>&nbsp;&nbsp; session.save(group1); </P>
<P>17.关于vo和po <BR>&nbsp;&nbsp; vo经过hibernate容量处理，就变成了po(该vo的引用将被容器保存，并且在session关闭时flush,因此po如果再传到其它地方改变了，就危险了) <BR>&nbsp; <BR>&nbsp;&nbsp; vo和po相互转换：BeanUtils.copyProperties(anotherUser,user); </P>
<P>18.对于save操作而言，如果对象已经与Session相关联（即已经被加入Session的实体容器中），则无需进行具体的操作。因为之后的Session.flush过程中，Hibernate <BR>会对此实体容器中的对象进行遍历，查找出发生变化的实体，生成并执行相应的update <BR>语句。 </P>
<P>19.如果我们采用了延迟加载机制，但希望在一些情况下，实现非延迟加 <BR>载时的功能，也就是说，我们希望在Session关闭后，依然允许操作user的addresses <BR>属性 <BR>Hibernate.initialize方法可以通过强制加载关联对象实现这一功能： <BR>这也正是我们为什么在编写POJO时，必须用JDK Collection接口（如Set,Map）, <BR>而非特定的JDK Collection实现类（如HashSet、HashMap）申明Collection属性的 <BR>原因。 </P>
<P>20.事务：从sessionFactory获得session,其自动提交属性就已经关闭(AutoCommit=false),此时若执行了jdbc操作，如果不显式调用session.BeginTransaction(),是不会执行事务操作的。</P>
<P>&nbsp;&nbsp; jdbc transaction:基于同一个session(就是同一个connection)的事务; <BR>&nbsp;&nbsp; jta&nbsp; transaction:跨session（跨connection）事务. </P>
<P>&nbsp;&nbsp; 对于jta事务，有三种实现方法： <BR>&nbsp;&nbsp;&nbsp;&nbsp; A。UserTransaction tx=new InitialContext().lookup("..."); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tx.commit(); <BR>&nbsp;&nbsp;&nbsp;&nbsp; B. 使用hibernate封装的方法：(不推荐) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Transaction tx=session.beginTransaction(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tx.commit(); <BR>&nbsp;&nbsp;&nbsp;&nbsp; C. 使用ejb之sessionBean的事务技持方法，你只要在把需要在发布描述符中，把需要jta事务的方法声明为require即可 </P>
<P>21.悲观锁，乐观锁： <BR>&nbsp;&nbsp; 乐观锁一般通过version来实现，注意version节点必须出现在id后。 </P>
<P><BR>22.Hibernate中，可以通过Criteria.setFirstResult和Criteria.setFetchSize方法设定分页范围。 <BR>&nbsp;&nbsp; Query接口中也提供了与其一致的方法，hibernate主要在dialect类中实现在这个功能。 </P>
<P><BR>23.cache <BR>&nbsp;&nbsp; &lt;hibernate-configuration&gt; <BR>&nbsp;&lt;session-factory&gt; <BR>&nbsp;…… <BR>&nbsp;&nbsp;&lt;property name="hibernate.cache.provider_class"&gt; <BR>&nbsp;&nbsp;&nbsp;net.sf.ehcache.hibernate.Provider <BR>&nbsp;&nbsp;&lt;/property&gt;&nbsp; </P>
<P>&nbsp; 还需对ecache本身进配置 <BR>&nbsp; &lt;ehcache&gt; <BR>&nbsp;&lt;diskStore path="java.io.tmpdir"/&gt; <BR>&nbsp;&lt;defaultCache <BR>&nbsp;maxElementsInMemory="10000" //Cache中最大允许保存的数据数量 <BR>&nbsp;eternal="false" //Cache中数据是否为常量 <BR>&nbsp;timeToIdleSeconds="120" //缓存数据钝化时间 <BR>&nbsp;timeToLiveSeconds="120" //缓存数据的生存时间 <BR>&nbsp;overflowToDisk="true" //内存不足时，是否启用磁盘缓存 <BR>&nbsp;/&gt; <BR>&nbsp; &lt;/ehcache&gt; </P>
<P>&nbsp; 之后在映射文件中指定各个映射实体的cache策略 <BR>&nbsp; &lt;class name=" org.hibernate.sample.TUser" .... &gt; <BR>&nbsp;&lt;cache usage="read-write"/&gt; <BR>&nbsp;.... <BR>&nbsp;&lt;set name="addresses" .... &gt; <BR>&nbsp;&nbsp;&lt;cache usage="read-only"/&gt; <BR>&nbsp;.... <BR>&nbsp;&lt;/set&gt; <BR>&nbsp;&lt;/class&gt; </P>
<P>&nbsp;***************************************************** <BR>&nbsp;Query.list()跟Query.iterate()的不同： <BR>&nbsp;对于query.list()总是通过一条sql语句获取所有记录,然后将其读出，填入pojo返回; <BR>&nbsp;但是query.iterate()，则是首先通过一条Select SQL 获取所有符合查询条件的记录的 <BR>id，再对这个id 集合进行循环操作，通过单独的Select SQL 取出每个id 所对应的记 <BR>录，之后填入POJO中返回。 </P>
<P>&nbsp;也就是说，对于list 操作，需要一条SQL 完成。而对于iterate 操作，需要n+1 <BR>条SQL。，list方法将不会从Cache中读取数据。iterator却会。 </P>
<P><BR>24.ThreadLocal:它会为每个线程维护一个私有的变量空间。实际上， <BR>其实现原理是在JVM 中维护一个Map，这个Map的key 就是当前的线程对象，而value则是 <BR>线程通过ThreadLocal.set方法保存的对象实例。当线程调用ThreadLocal.get方法时， <BR>ThreadLocal会根据当前线程对象的引用，取出Map中对应的对象返回。 </P>
<P>&nbsp;这样，ThreadLocal通过以各个线程对象的引用作为区分，从而将不同线程的变量隔离开 <BR>来。 </P>
<P><BR>25.Hibernate官方开发手册标准示例: <BR>&nbsp; public class HibernateUtil { <BR>private static SessionFactory sessionFactory; <BR>static { <BR>try { <BR>// Create the SessionFactory <BR>sessionFactory = new <BR>Configuration().configure().buildSessionFactory(); <BR>} catch (HibernateException ex) { <BR>throw new RuntimeException( <BR>"Configuration problem: " + ex.getMessage(), <BR>ex <BR>); <BR>} <BR>} <BR>public static final ThreadLocal session = new ThreadLocal(); <BR>public static Session currentSession() throws HibernateException <BR>{ <BR>Session s = (Session) session.get(); <BR>// Open a new Session, if this Thread has none yet <BR>if (s == null) { <BR>s = sessionFactory.openSession(); <BR>session.set(s); <BR>} <BR>return s; <BR>} <BR>public static void closeSession() throws HibernateException { <BR>Session s = (Session) session.get(); <BR>session.set(null); <BR>if (s != null) <BR>s.close(); <BR>} <BR>}&nbsp; </P>
<P><BR>&nbsp;&nbsp;&nbsp;&nbsp; <BR>26.通过filter实现session的重用： <BR>&nbsp;&nbsp; public class PersistenceFilter implements Filter <BR>{ <BR>protected static ThreadLocal hibernateHolder = new ThreadLocal(); <BR>public void doFilter(ServletRequest request, ServletResponse <BR>response, FilterChain chain) <BR>throws IOException, ServletException <BR>{ <BR>hibernateHolder.set(getSession()); <BR>try <BR>{ <BR>…… <BR>chain.doFilter(request, response); <BR>…… <BR>} <BR>finally <BR>{ <BR>Session sess = (Session)hibernateHolder.get(); <BR>if (sess != null) <BR>{ <BR>hibernateHolder.set(null); <BR>try <BR>{ <BR>sess.close(); <BR>} <BR>catch (HibernateException ex) { <BR>throw new ServletException(ex); <BR>} <BR>} <BR>} <BR>} <BR>……} </P>
<P>27.Spring的参数化事务管理功能相当强大，笔者建议在基于Spring Framework的应用 <BR>开发中，尽量使用容器管理事务，以获得数据逻辑代码的最佳可读性。 <BR>&nbsp; <BR>public class UserDAO extends HibernateDaoSupport implements IUserDAO <BR>{ <BR>public void insertUser(User user) { <BR>getHibernateTemplate().saveOrUpdate(user); <BR>} <BR>} </P>
<P><BR>&nbsp; 上面的UserDAO实现了自定义的IUserDAO接口，并扩展了抽象类： <BR>HibernateDaoSupport <BR>HibernateSupport实现了HibernateTemplate和SessionFactory实例的关联。 <BR>HibernateTemplate对Hibernate Session操作进行了封装，而 <BR>HibernateTemplate.execute方法则是一封装机制的核心 </P>
<P>&nbsp; *在spring的配置文件里，移植了整个hibernate.cfg.xml的内容。</P><img src ="http://www.blogjava.net/badboy/aggbug/35598.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/badboy/" target="_blank">badboy</a> 2006-03-16 11:48 <a href="http://www.blogjava.net/badboy/articles/35598.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>