﻿<?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-hk2000c技术专栏-随笔分类-CMS项目开发</title><link>http://www.blogjava.net/hk2000c/category/26820.html</link><description>技术源于哲学，哲学来源于生活

关心生活，关注健康，关心他人

</description><language>zh-cn</language><lastBuildDate>Thu, 24 Jan 2008 12:54:11 GMT</lastBuildDate><pubDate>Thu, 24 Jan 2008 12:54:11 GMT</pubDate><ttl>60</ttl><item><title>为BO加入SecurityObject控制</title><link>http://www.blogjava.net/hk2000c/archive/2008/01/24/177387.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Wed, 23 Jan 2008 16:04:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2008/01/24/177387.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/177387.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2008/01/24/177387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/177387.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/177387.html</trackback:ping><description><![CDATA[这样可以做到对所有对象的安全性控制。<br />
可以扩展到一切的业务对象。<br />
包括基础方法，操作。<br />
甚至安全对象本身<br />
有点神学的味道。<br />
<br />
可能是因为采用其他被创造者不知道的机制，所以被创造者无法理解和知晓。<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/177387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2008-01-24 00:04 <a href="http://www.blogjava.net/hk2000c/archive/2008/01/24/177387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于要求hibernate事务报session设置为auto标志异常问题</title><link>http://www.blogjava.net/hk2000c/archive/2007/11/30/164252.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Fri, 30 Nov 2007 06:01:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/30/164252.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/164252.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/30/164252.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/164252.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/164252.html</trackback:ping><description><![CDATA[通常是封装在某一级的接口或者类没有事务声明所致<br />
<br />
&nbsp; &lt;aop:config&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;aop:pointcut id="systemDaoMethods" expression="execution(* com.unitedbiz.system.dao.*.*(..))"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="systemDaoMethods"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/aop:config&gt;<br />
<br />
申明一下就可以了<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/164252.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-30 14:01 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/30/164252.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BO设计定稿</title><link>http://www.blogjava.net/hk2000c/archive/2007/11/15/160825.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Thu, 15 Nov 2007 11:26:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/15/160825.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/160825.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/15/160825.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/160825.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/160825.html</trackback:ping><description><![CDATA[BO设计定稿<br />
<br />
等过些时候重新审视自己的设计再说<br />
<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/160825.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-15 19:26 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/15/160825.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一般性data bind 流程 </title><link>http://www.blogjava.net/hk2000c/archive/2007/11/12/159848.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Sun, 11 Nov 2007 21:22:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/12/159848.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/159848.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/12/159848.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/159848.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/159848.html</trackback:ping><description><![CDATA[<p>org.springframework.web.bind.ServletRequestDataBinder@27ca12</p>
<p><br />
DataBinder: applyPropertyValues(MutablePropertyValues mpvs)</p>
<p><br />
org.springframework.beans.BeanWrapperImpl: wrapping object [com.unitedbiz.model.User@996f0e]<br />
AbstractPropertyAccessor::setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)</p>
<p>&nbsp;</p>
<p>org.springframework.beans.BeanWrapperImpl: wrapping object [com.unitedbiz.model.User@996f0e]::setPropertyValue(PropertyValue pv) </p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/hk2000c/aggbug/159848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-12 05:22 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/12/159848.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>filter 位置不能颠倒</title><link>http://www.blogjava.net/hk2000c/archive/2007/11/08/159149.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Thu, 08 Nov 2007 11:29:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/08/159149.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/159149.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/08/159149.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/159149.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/159149.html</trackback:ping><description><![CDATA[<p>filter 位置不能颠倒</p>
<p>一般位置顺序为</p>
<p>encoding</p>
<p>hibernate</p>
<p><font face="Arial">localeFilter</font></p>
<p><font face="Arial">securityFilter</font></p>
<p><font face="Arial">sitemesh</font></p>
<img src ="http://www.blogjava.net/hk2000c/aggbug/159149.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-08 19:29 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/08/159149.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在validation.xml中进行相关的验证配置</title><link>http://www.blogjava.net/hk2000c/archive/2007/11/08/158969.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Wed, 07 Nov 2007 17:10:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/08/158969.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/158969.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/08/158969.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/158969.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/158969.html</trackback:ping><description><![CDATA[．在validation.xml中进行相关的验证配置如：<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN" "validator_1_0.dtd" &gt;<br />
&lt;form-validation&gt;<br />
<font color="#0000ff">&lt;formset&gt;<br />
&lt;form name="loginForm"&gt;//struts-config.xml中formBean的名字<br />
&lt;field property="username" depends="required,maxlength,minlength"&gt;<br />
//property相关验证字段的名称，depends所对应的验证器<br />
&lt;arg0 key="用户名" resource="false"/&gt;<br />
//当resource为TRUE时，表示使用来自resource Bundle中的消息，反之指定key中消息<br />
&lt;arg1 name="maxlength" resource="false" key="${var:maxlength}"/&gt;<br />
&lt;var&gt;<br />
&lt;var-name&gt;maxlength&lt;/var-name&gt;<br />
&lt;var-value&gt;8&lt;/var-value&gt;<br />
&lt;/var&gt;<br />
&lt;arg2 name="minlength" resource="false" key="${var:minlength}"/&gt;<br />
&lt;var&gt;<br />
&lt;var-name&gt;minlength&lt;/var-name&gt;<br />
&lt;var-value&gt;2&lt;/var-value&gt;<br />
&lt;/var&gt;<br />
<br />
&lt;/field&gt;<br />
&lt;/form&gt;<br />
&lt;/formset&gt;</font><br />
所注意的问题：1、如&lt;arg0 key="用户名" resource="false"/&gt;在arg0中如果不设置验证器，那么就被所有的验证器通用 <br />
2、如&lt;arg1 name="maxlength" resource="false" key="${var:maxlength}"/&gt;中的arg1要与错误信息中所对应的该验证器的参数一至（errors.maxlength={0} can not be greater than {1} characters.）<br />
如果（errors.maxlength={0} can not be greater than {2} characters.）的话，那么就必须将2改为1<br />
<br />
7.jsp中的前台验证：<br />
&lt;htm:form arction =&#8221;&#8221; onsubmit=&#8221; return validateLoginForm(this) &#8221;&gt;<br />
&lt;html:javascript formName="loginForm"/&gt;<br />
//对应formBean的名字<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/158969.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-08 01:10 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/08/158969.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSCache 避免死锁</title><link>http://www.blogjava.net/hk2000c/archive/2007/11/07/158791.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Wed, 07 Nov 2007 05:09:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/07/158791.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/158791.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/07/158791.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/158791.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/158791.html</trackback:ping><description><![CDATA[OSCache 避免死锁<br />
<br />
在正常更新 cache 后， 不要调用&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cache.cancelUpdate(url);<br />
<br />
方法<br />
<br />
<br />
否则会引起系统死锁<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/158791.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-07 13:09 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/07/158791.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详解spring事务属性 </title><link>http://www.blogjava.net/hk2000c/archive/2007/11/01/157521.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Thu, 01 Nov 2007 08:13:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/01/157521.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/157521.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/01/157521.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/157521.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/157521.html</trackback:ping><description><![CDATA[<p>Spring声明式事务让我们从复杂的事务处理中得到解脱。使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的try&#8230;catch&#8230;finally代码。 <br />
我们在使用Spring声明式事务时，有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为，事务的隔离级别，事务的超时值和事务只读标志组成。我们在进行事务划分时，需要进行事务定义，也就是配置事务的属性。 <br />
Spring在<strong>TransactionDefinition</strong>接口中定义这些属性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务管理的核心接口。 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>TransactionDefinition &nbsp;&nbsp;</span></span></li>
    <li class=""><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">interface</span><span>&nbsp;TransactionDefinition&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;getPropagationBehavior(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;getIsolationLevel(); &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;getTimeout(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">boolean</span><span>&nbsp;isReadOnly(); &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>getTimeout()方法，它返回事务必须在多少秒内完成。 <br />
isReadOnly(),事务是否只读，事务管理器能够根据这个返回值进行优化，确保事务是只读的。 <br />
getIsolationLevel()方法返回事务的隔离级别，事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。</p>
<p>在TransactionDefinition接口中定义了五个不同的事务隔离级别 <br />
<strong>ISOLATION_DEFAULT </strong>这是一个PlatfromTransactionManager默认的隔离级别，使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应 <br />
<strong>ISOLATION_READ_UNCOMMITTED</strong> 这是事务最低的隔离级别，它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读，不可重复读和幻像读。 <br />
例如: <br />
Mary的原工资为1000,财务人员将Mary的工资改为了8000，但未提交事务 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Connection&nbsp;con1&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>update&nbsp;employee&nbsp;set&nbsp;salary&nbsp;=&nbsp;</span><span class="number">8000</span><span>&nbsp;where&nbsp;empId&nbsp;=</span><span class="string">"Mary"</span><span>;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
与此同时，Mary正在读取自己的工资 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Connection&nbsp;con2&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>select&nbsp;&nbsp;salary&nbsp;from&nbsp;employee&nbsp;where&nbsp;empId&nbsp;=</span><span class="string">"Mary"</span><span>; &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>Mary发现自己的工资变为了8000，欢天喜地！ <br />
而财务发现操作有误，而回滚了事务,Mary的工资又变为了1000 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;con1.rollback();&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
像这样,Mary记取的工资数8000是一个脏数据。
<p>&nbsp;</p>
<p><strong>ISOLATION_READ_COMMITTED </strong>保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现，但是可能会出现不可重复读和幻像读。</p>
<p><strong>ISOLATION_REPEATABLE_READ </strong>这种事务隔离级别可以防止脏读，不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外，还保证了避免下面的情况产生(不可重复读)。</p>
<p>在事务1中，Mary 读取了自己的工资为1000,操作并没有完成 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con1&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>select&nbsp;salary&nbsp;from&nbsp;employee&nbsp;empId&nbsp;=</span><span class="string">"Mary"</span><span>;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>在事务2中，这时财务人员修改了Mary的工资为2000,并提交了事务. <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con2&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>update&nbsp;employee&nbsp;set&nbsp;salary&nbsp;=&nbsp;</span><span class="number">2000</span><span>; &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>在事务1中，Mary 再次读取自己的工资时，工资变为了2000 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>select&nbsp;salary&nbsp;from&nbsp;employee&nbsp;empId&nbsp;=</span><span class="string">"Mary"</span><span>;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>在一个事务中前后两次读取的结果并不致，导致了不可重复读。 <br />
使用ISOLATION_REPEATABLE_READ可以避免这种情况发生。</p>
<p><strong>ISOLATION_SERIALIZABLE </strong>这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读，不可重复读外，还避免了幻像读。</p>
<p>目前工资为1000的员工有10人。 <br />
事务1,读取所有工资为1000的员工。 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con1&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>Select&nbsp;*&nbsp;from&nbsp;employee&nbsp;where&nbsp;salary&nbsp;=</span><span class="number">1000</span><span>;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
</div>
<script>render_code();</script>共读取10条记录
<p>&nbsp;</p>
<p>这时另一个事务向employee表插入了一条员工记录，工资也为1000 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con2&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>Insert&nbsp;into&nbsp;employee(empId,salary)&nbsp;values(</span><span class="string">"Lili"</span><span>,</span><span class="number">1000</span><span>); &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>事务1再次读取所有工资为1000的员工 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>select&nbsp;*&nbsp;from&nbsp;employee&nbsp;where&nbsp;salary&nbsp;=</span><span class="number">1000</span><span>;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>共读取到了11条记录，这就产生了幻像读。 <br />
ISOLATION_SERIALIZABLE能避免这样的情况发生。但是这样也耗费了最大的资源。</p>
<p><strong>getPropagationBehavior()</strong>返回事务的传播行为，由是否有一个活动的事务来决定一个事务调用。</p>
<p><strong>在TransactionDefinition接口中定义了七个事务传播行为</strong>。</p>
<p><strong>PROPAGATION_REQUIRED </strong>如果存在一个事务，则支持当前事务。如果没有事务则开启一个新的事务。</p>
<p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>methodB{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
使用spring声明式事务，spring使用AOP来支持声明式事务，会根据事务属性，自动在方法调用之前决定是否开启一个事务，并在方法执行之后决定事务提交或回滚事务。
<p>&nbsp;</p>
<p>单独调用methodB方法 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>main{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;metodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
相当于 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Main{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>Connection&nbsp;con=</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;rry{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span class="comment">//方法调用 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="comment">//提交事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>con.commit(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>Catch(RuntimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//回滚事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;con.rollback();&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;closeCon(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
Spring保证在methodB方法中所有的调用都获得到一个相同的连接。在调用methodB时，没有一个存在的事务，所以获得一个新的连接，开启了一个新的事务。
<p>&nbsp;</p>
<p>单独调用MethodA时，在MethodA内又会调用MethodB.</p>
<p>执行效果相当于 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.commit(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>cathc(RuntimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;con.rollback(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;closeCon(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
调用MethodA时，环境中没有事务，所以开启一个新的事务. <br />
当在MethodA中调用MethodB时，环境中已经有了一个事务，所以methodB就加入当前事务。
<p>&nbsp;</p>
<p><strong>PROPAGATION_SUPPORTS </strong>如果存在一个事务，支持当前事务。如果没有事务，则非事务的执行。但是对于事务同步的事务管理器，PROPAGATION_SUPPORTS与不使用事务有少许不同。</p>
<p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span class="comment">//事务属性&nbsp;PROPAGATION_SUPPORTS&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
单纯的调用methodB时，methodB方法是非事务的执行的。 <br />
当调用methdA时,methodB则加入了methodA的事务中,事务地执行。
<p>&nbsp;</p>
<p>PROPAGATION_MANDATORY 如果已经存在一个事务，支持当前事务。如果没有一个活动的事务，则抛出异常。</p>
<p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span class="comment">//事务属性&nbsp;PROPAGATION_MANDATORY&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
当单独调用methodB时，因为当前没有一个活动的事务，则会抛出异常 <br />
throw new IllegalTransactionStateException("Transaction propagation 'mandatory' but no existing transaction found");
<p>&nbsp;</p>
<p>当调用methodA时，methodB则加入到methodA的事务中，事务地执行。</p>
<p><strong>PROPAGATION_REQUIRES_NEW </strong>总是开启一个新的事务。如果一个事务已经存在，则将这个存在的事务挂起。</p>
<p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRES_NEW&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
当单独调用methodB时，相当于把methodb声明为REQUIRED。开启一个新的事务，事务地执行。
<p>&nbsp;</p>
<p>当调用methodA时 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>main(){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;methodA(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>情况有些大不一样.相当于下面的效果。 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;TransactionManager&nbsp;tm&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="comment">//获得一个JTA事务管理器 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;tm&nbsp;=&nbsp;getTransactionManager(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;tm.begin();</span><span class="comment">//开启一个新的事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;Transaction&nbsp;ts1&nbsp;=&nbsp;tm.getTransaction(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;doSomeThing(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;tm.suspend();</span><span class="comment">//挂起当前事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tm.begin();</span><span class="comment">//重新开启第二个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transaction&nbsp;ts2&nbsp;=&nbsp;tm.getTransaction(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ts2.commit();</span><span class="comment">//提交第二个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;Catch(RunTimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ts2.rollback();</span><span class="comment">//回滚第二个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="comment">//methodB执行完后，复恢第一个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;tm.resume(ts1); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;ts1.commit();</span><span class="comment">//提交第一个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span class="keyword">catch</span><span>(RunTimeException&nbsp;ex){ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;ts1.rollback();</span><span class="comment">//回滚第一个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
在这里，我把ts1称为外层事务，ts2称为内层事务。从上面的代码可以看出，ts2与ts1是两个独立的事务，互不相干。Ts2是否成功并不依赖于ts1。如果methodA方法在调用methodB方法后的doSomeThingB方法失败了，而methodB方法所做的结果依然被提交。而除了methodB之外的其它代码导致的结果却被回滚了。 <br />
使用PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作为事务管理器。
<p>&nbsp;</p>
<p><strong>PROPAGATION_NOT_SUPPORTED</strong> 总是非事务地执行，并挂起任何存在的事务。</p>
<p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span class="comment">//事务属性&nbsp;PROPAGATION_NOT_SUPPORTED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
当单独调用methodB时，不启用任何事务机制，非事务地执行。 <br />
当调用methodA时，相当于下面的效果
<p>&nbsp;</p>
<p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;TransactionManager&nbsp;tm&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="comment">//获得一个JTA事务管理器 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;tm&nbsp;=&nbsp;getTransactionManager(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;tm.begin();</span><span class="comment">//开启一个新的事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;Transaction&nbsp;ts1&nbsp;=&nbsp;tm.getTransaction(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;doSomeThing(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;tm.suspend();</span><span class="comment">//挂起当前事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="comment">//methodB执行完后，复恢第一个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;tm.resume(ts1); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;ts1.commit();</span><span class="comment">//提交第一个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span class="keyword">catch</span><span>(RunTimeException&nbsp;ex){ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;ts1.rollback();</span><span class="comment">//回滚第一个事务 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作为事务管理器。
<p>&nbsp;</p>
<p><strong>PROPAGATION_NEVER</strong> 总是非事务地执行，如果存在一个活动事务，则抛出异常</p>
<p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span class="comment">//事务属性&nbsp;PROPAGATION_NEVER&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>单独调用methodB，则非事务的执行。 <br />
调用methodA则会抛出异常 <br />
throw new IllegalTransactionStateException( <br />
"Transaction propagation 'never' but existing transaction found");
<p>&nbsp;</p>
<p><strong>PROPAGATION_NESTED</strong>如果一个活动的事务存在，则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行</p>
<p>这是一个嵌套事务,使用JDBC 3.0驱动时,仅仅支持DataSourceTransactionManager作为事务管理器。需要JDBC 驱动的java.sql.Savepoint类。有一些JTA的事务管理器实现可能也提供了同样的功能。</p>
<p>使用PROPAGATION_NESTED，还需要把PlatformTransactionManager的nestedTransactionAllowed属性设为true; <br />
而nestedTransactionAllowed属性值默认为false; <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span class="comment">//事务属性&nbsp;PROPAGATION_NESTED </span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
如果单独调用methodB方法，则按REQUIRED属性执行。
<p>&nbsp;</p>
<p>如果调用methodA方法，相当于下面的效果 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>Connection&nbsp;con&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>Savepoint&nbsp;savepoint&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span></li>
    <li class=""><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;con&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;savepoint&nbsp;=&nbsp;con2.setSavepoint(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;}</span><span class="keyword">catch</span><span>(RuntimeException&nbsp;ex){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.rollback(savepoint); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;con.commit(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span class="keyword">catch</span><span>(RuntimeException&nbsp;ex){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;con.rollback(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>当methodB方法调用之前，调用setSavepoint方法，保存当前的状态到savepoint。如果methodB方法调用失败，则恢复到之前保存的状态。但是需要注意的是，这时的事务并没有进行提交，如果后续的代码(doSomeThingB()方法)调用失败，则回滚包括methodB方法的所有操作。
<p>&nbsp;</p>
<p><strong>嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时，会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚</strong>。</p>
<p><strong>PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区别</strong>:它们非常类似,都像一个嵌套事务，如果不存在一个活动的事务，都会开启一个新的事务。使用PROPAGATION_REQUIRES_NEW时，内层事务与外层事务就像两个独立的事务一样，一旦内层事务进行了提交后，外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA事务管理器的支持。 <br />
使用PROPAGATION_NESTED时，外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚，它是一个真正的嵌套事务。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED时，需要JDBC 3.0以上驱动及1.4以上的JDK版本支持。其它的JTA TrasactionManager实现可能有不同的支持方式。</p>
<p>PROPAGATION_REQUIRED应该是我们首先的事务传播行为。它能够满足我们大多数的事务需求。</p>
<img src ="http://www.blogjava.net/hk2000c/aggbug/157521.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-01 16:13 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/01/157521.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring配置事务在DAO层和业务逻辑层 </title><link>http://www.blogjava.net/hk2000c/archive/2007/11/01/157508.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Thu, 01 Nov 2007 07:38:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/01/157508.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/157508.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/01/157508.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/157508.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/157508.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt">Spring<span style="font-family: 宋体">通过</span>AOP<span style="font-family: 宋体">实现声明式事务管理。通常通过</span>TransactionProxyFactoryBean<span style="font-family: 宋体">设置</span>Spring<span style="font-family: 宋体">事务代理。我们需要一个目标对象包装在事务代理中。这个目标对象一般是一个普通</span>Java<span style="font-family: 宋体">对象的</span>bean<span style="font-family: 宋体">。当我们定义</span>TransactionProxyFactoryBean<span style="font-family: 宋体">时，必须提供一个相关的</span> PlatformTransactionManager<span style="font-family: 宋体">的引用和事务属性。</span> <span style="font-family: 宋体">事务属性含有上面描述的事务定义。</span></p>
<p style="margin: 0cm 0cm 0pt">PlatformTransactionManager<span style="font-family: 宋体">：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt">HibernateTransactionManager<span style="font-family: 宋体">需要一个</span>SessionFactory<span style="font-family: 宋体">的引用</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt">JtaTransactionManager</p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">一．把事务放置在了</span>DAO<span style="font-family: 宋体">层：</span></p>
<p style="margin: 0cm 0cm 0pt"><span style="color: red">&lt;!—hibernateTransactionManager--&gt;</span></p>
<p style="margin: 0cm 0cm 0pt">&lt;bean id="transactionManager"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="sessionFactory" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;!—DAO<span style="font-family: 宋体">层接口实现</span>--&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;bean id="companyDAOTarget"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.vstsoft.querycompany.dao.impl.CompanyDAOImpl"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="sessionFactory" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt"><span style="color: red">&lt;!—spring</span><span style="color: red; font-family: 宋体">对</span><span style="color: red">DAO</span><span style="color: red; font-family: 宋体">层的事务代理</span><span style="color: red">--&gt;</span></p>
<p style="margin: 0cm 0cm 0pt">&lt;bean id="companyDAOProxy"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="transactionManager"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="transactionManager" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="companyDAOTarget" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="transactionAttributes"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;props&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="insert*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="delete*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="find*"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PROPAGATION_REQUIRED,readOnly</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/prop&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/props&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;!—<span style="font-family: 宋体">业务层接口实现，把</span>DAO<span style="font-family: 宋体">注入到</span>Service<span style="font-family: 宋体">里面</span>--&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;bean name="companyManageTarget"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.vstsoft.querycompany.service.impl.CompanyManageTarget"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="companyDAO"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="companyDAOProxy" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt"><span style="color: red">&lt;!—spring</span><span style="color: red; font-family: 宋体">对</span><span style="color: red">Service</span><span style="color: red; font-family: 宋体">层的代理</span><span style="color: red">--&gt;</span></p>
<p style="margin: 0cm 0cm 0pt">&lt;bean id="companyManageProxy"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.springframework.aop.framework.ProxyFactoryBean"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="proxyInterfaces"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;com.vstsoft.querycompany.service.CompanyManage&lt;/value&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="companyManageTarget" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;!—<span style="font-family: 宋体">配置</span>struts<span style="font-family: 宋体">访问，把</span>service<span style="font-family: 宋体">层注入到</span>action<span style="font-family: 宋体">里面</span>--&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;bean name="/company"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.vstsoft.querycompany.web.action.CompanyAction" singleton="false"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="companyManage"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="companyManageProxy" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">二．把事务放置在了</span>Service<span style="font-family: 宋体">层：</span></p>
<p style="margin: 0cm 0cm 0pt"><span style="color: red">&lt;!—jtaTransactionManager--&gt;</span></p>
<p style="margin: 0cm 0cm 0pt">&lt;bean id="jtaTransactionManager"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.springframework.transaction.jta.JtaTransactionManager" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;!—DAO<span style="font-family: 宋体">层接口实现</span>--&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;bean id="companyDAOTarget"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.vstsoft.querycompany.dao.impl.CompanyDAOImpl"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="sessionFactory" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt"><span style="color: red">&lt;!—spring</span><span style="color: red; font-family: 宋体">对</span><span style="color: red">DAO</span><span style="color: red; font-family: 宋体">层的代理</span><span style="color: red">--&gt;</span></p>
<p style="margin: 0cm 0cm 0pt">&lt;bean id="companyDAOProxy"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.springframework.aop.framework.ProxyFactoryBean"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="proxyInterfaces"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;com.vstsoft.querycompany.dao.CompanyDAO&lt;/value&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="companyDAOTarget" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;!—<span style="font-family: 宋体">业务层接口实现，把</span>DAO<span style="font-family: 宋体">注入到</span>Service<span style="font-family: 宋体">里面</span>--&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;bean name="companyManageTarget"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.vstsoft.querycompany.service.impl.CompanyManageTarget"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="companyDAO"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="companyDAOProxy" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt"><span style="color: red">&lt;!—spring</span><span style="color: red; font-family: 宋体">代理业务层的事务管理</span><span style="color: red">--&gt;</span></p>
<p style="margin: 0cm 0cm 0pt">&lt;bean id="companyManageProxy"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="transactionManager"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="jtaTransactionManager" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="transactionAttributes"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;props&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="set*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="find*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/props&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="companyManageTarget" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;!—<span style="font-family: 宋体">配置</span>struts<span style="font-family: 宋体">访问，把</span>service<span style="font-family: 宋体">层注入到</span>action<span style="font-family: 宋体">里面</span>--&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;bean name="/company"</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.vstsoft.querycompany.web.action.CompanyAction" singleton="false"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="companyManage"&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="companyManageProxy" /&gt;</p>
<p style="margin: 0cm 0cm 0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;</p>
<p style="margin: 0cm 0cm 0pt">&lt;/bean&gt;</p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体">在</span>service<span style="font-family: 宋体">层的接口实现</span>CompanyManageImpl<span style="font-family: 宋体">里面有个</span>setData<span style="font-family: 宋体">方法：按顺序执行数据查询，数据删除，数据插入数据库行为，如果哪一步出异常（运行时异常），事务回滚，只有所有行为都没成功，事务提交。</span></p>
<img src ="http://www.blogjava.net/hk2000c/aggbug/157508.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-01 15:38 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/01/157508.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring事务探索 [转]</title><link>http://www.blogjava.net/hk2000c/archive/2007/11/01/157362.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Wed, 31 Oct 2007 17:36:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/01/157362.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/157362.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/01/157362.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/157362.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/157362.html</trackback:ping><description><![CDATA[<p><span id="showcontent">spring自建事务管理模块。而且这个事务管理是一个抽象设计，可以应用到很多场合，包括普通的DataSource，jta，jms和hibernate上。&nbsp;<br />
<br />
要正确使用spring的事务，首先需要了解spring在事务设计上的一些概念&nbsp;<br />
统观spring事务，围绕着两个核心PlatformTransactionManager和TransactionStatus <br />
</span></p>
<div class="entry-more" id="more">
<p>PlatformTransactionManager 直译过来就是平台相关事务，这里的平台指的是&#8220;事务源&#8221;，包括刚才我说的DataSource，jta等等。这些无一不是一个事务源。广义的说，凡是可以完成事务性操作的对象，都可以设计出相对应的PlatformTransactionManager，只要这个事务源支持commit，rollback 和getTransaction语意。 </p>
<p>查看spring代码，可以发现这些manager实现事务，就是调用事务源的事务操作方法 </p>
<p>比如 </p>
<p>HibernateTransactionManager <br />
java代码: </p>
<p>protected void doCommit(DefaultTransactionStatus status) { <br />
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction(); <br />
if (status.isDebug()) { <br />
logger.debug("Committing Hibernate transaction on session [" + <br />
txObject.getSessionHolder().getSession() + "]"; <br />
} <br />
try { <br />
txObject.getSessionHolder().getTransaction().commit(); <br />
} <br />
... </p>
<p>}<br />
</p>
<p>&nbsp;</p>
<p>jdbc 的DataSourceTransactionManager <br />
java代码: </p>
<p>protected void doCommit(DefaultTransactionStatus status) { <br />
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); <br />
Connection con = txObject.getConnectionHolder().getConnection(); <br />
if (status.isDebug()) { <br />
logger.debug("Committing JDBC transaction on connection [" + con + "]"; <br />
} <br />
try { <br />
con.commit(); <br />
} <br />
... <br />
}<br />
</p>
<p>&nbsp;</p>
<p>那么PlatformTransactionManager以什么依据处理事务呢？ <br />
是TransactionStatus <br />
查看api发现这个接口有三个方法 <br />
isNewTransaction() ，isRollbackOnly()，setRollbackOnly() <br />
PlatformTransactionManager 就是根据前两个方法决定是否要创建一个新事务，是要递交还是回滚。至于第三个方法是改变事务当前状态的，很多地方都要用到，偏偏 PlatformTransactionManager自身好像不怎么用，毕竟事务状态的改变是由程序员代码决定的，不需要一个manager多管闲事。 </p>
<p>总结上面所说的，spring的事务由PlatformTransactionManager管理，manager最后调用事务源的方法来实现一个事务过程。而manager通过TransactionStatus 来决定如何实现。 </p>
<p>接下去说spring事务中的TransactionTemplate和TransactionInterceptor </p>
<p>TransactionTemplate 其实和spring中其他的template的作用类似，起到化简代码的作用，不要被它那么长的名字吓倒了，事实上这个template并不是什么非常核心的对象。如果比较学究派的，可以去看看template设计模式，在此就不再对此赘述了。 <br />
为什么要有TransactionTemplate？先来看看如果没有TransactionTemplate，我们的代码该怎么写 </p>
<p>先来看看spring reference中的一段代码 <br />
java代码: </p>
<p>DefaultTransactionDefinition def = new DefaultTransactionDefinition() <br />
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); </p>
<p>TransactionStatus status = transactionManager.getTransaction(def); </p>
<p>try { <br />
// execute your business logic here <br />
} catch (MyException ex) { <br />
transactionManager.rollback(status); <br />
throw ex; <br />
} <br />
transactionManager.commit(status);<br />
</p>
<p>这是直接使用transactionManager的例子，可以看到真正执行business logic 的地方是在try当中那段，前后的代码都是为了完成事务管理的。如果每个business logic都要写上那么一段，我肯定是疯了。我们翻出TransactionTemplate的代码看看他怎么化简了我们的代码 </p>
<p>java代码: </p>
<p>public Object execute(TransactionCallback action) throws TransactionException { <br />
TransactionStatus status = this.transactionManager.getTransaction(this); <br />
Object result = null; <br />
try { <br />
result = action.doInTransaction(status); <br />
} <br />
catch (RuntimeException ex) { <br />
// transactional code threw application exception -&gt; rollback <br />
rollbackOnException(status, ex); <br />
throw ex; <br />
} <br />
catch (Error err) { <br />
// transactional code threw error -&gt; rollback <br />
rollbackOnException(status, err); <br />
throw err; <br />
} <br />
this.transactionManager.commit(status); <br />
return result; <br />
}<br />
</p>
<p><br />
同上面的代码如出一辙，前后是事务处理代码，当中那段result = action.doInTransaction(status);是我们的应用代码。至于action是什么，全看各位的需要了。但是有一点要主要，如果利用TransactionTemplate，那么他不管你扔出什么异常都会回滚事务，但是回滚的是哪个事务呢？继续挖代码 <br />
java代码: </p>
<p>private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException { <br />
if (logger.isDebugEnabled()) { <br />
logger.debug("Initiating transaction rollback on application exception", ex); <br />
} <br />
try { <br />
this.transactionManager.rollback(status); <br />
} <br />
catch (RuntimeException ex2) { <br />
logger.error("Application exception overridden by rollback exception", ex); <br />
throw ex2; <br />
} <br />
catch (Error err) { <br />
logger.error("Application exception overridden by rollback error", ex); <br />
throw err; <br />
} <br />
}<br />
</p>
<p>真相大白，是对template所持有的某个transactionManager进行回滚。所以如果你的应用代码用的是事务源a的一些资源，比如到服务器 a的一个datasource，但是你的transactionManager管理的是另一些资源，比如服务器b的一个datasource，代码铁定不会正常运行 </p>
<p>特别是在一些多事务源的程序里，这点千万不能搞错。如果多个事务源之间要完成全局事务，还是老老实实用分布式事务管理服务吧（jta） </p>
<p>那么TransactionInterceptor是干什么的？这个是spring 的声明式事务的支持方式。因为用 TransactionTemplate要硬编码，而且调整事务策略很麻烦（不是说不能调。举个例子原来程序抛出异常A需要回滚，现在不需要要，我就可以把a catch吃掉。这时候template就不会回滚了。但是每次调整都要重写编码。）而用TransactionInterceptor就可以将这些调整写在配置中。我们再来挖TransactionInterceptor的代码 </p>
<p>java代码: </p>
<p>public Object invoke(MethodInvocation invocation) throws Throwable { <br />
// Work out the target class: may be null. <br />
// The TransactionAttributeSource should be passed the target class <br />
// as well as the method, which may be from an interface <br />
Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null; <br />
<br />
// Create transaction if necessary <br />
TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass); </p>
<p>Object retVal = null; <br />
try { <br />
// This is an around advice. <br />
// Invoke the next interceptor in the chain. <br />
// This will normally result in a target object being invoked. <br />
retVal = invocation.proceed(); <br />
} <br />
catch (Throwable ex) { <br />
// target invocation exception <br />
doCloseTransactionAfterThrowing(txInfo, ex); <br />
throw ex; <br />
} <br />
finally { <br />
doFinally(txInfo); <br />
} <br />
doCommitTransactionAfterReturning(txInfo); </p>
<p>return retVal; <br />
}<br />
</p>
<p>万变不离其宗。 </p>
<p>所以使用spring的事务管理需要作这些事 <br />
1，设置好事务源，比如DataSource，hibernate的session。如果有多个事务源要考虑他们之间是否有全局事务，如果有，老老实实用jta，否则就需要自己写一个manager了 <br />
2，设置manager，根据你的事务源选择对应的PlatformTransactionManager <br />
3，选择实现事物的方式，用template还是interceptor。用template代码直观点，但是template所管辖的manager和你应用代码所用的事务源要一致。如果用interceptor千万注意，一定要调用interceptor那个bean，而不是原始的那个target。在坛子上我已经看到至少有两个朋友说spring事物不起作用，从配置和代码上看都正确，这时要好好查查，调用的bean是哪一个。 <br />
4，这个是设计问题了，推荐事务处于一个较高层次，比如service上的某个函数，而底层的dao可以不考虑事务，否则可能会出现事务嵌套，增加程序复杂度。</p>
</div>
<img src ="http://www.blogjava.net/hk2000c/aggbug/157362.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-01 01:36 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/01/157362.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring 事务支持</title><link>http://www.blogjava.net/hk2000c/archive/2007/11/01/157359.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Wed, 31 Oct 2007 16:41:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/11/01/157359.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/157359.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/11/01/157359.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/157359.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/157359.html</trackback:ping><description><![CDATA[spring 事务支持，需要事务支持。<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/157359.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-11-01 00:41 <a href="http://www.blogjava.net/hk2000c/archive/2007/11/01/157359.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring bean 继承父类property方法 </title><link>http://www.blogjava.net/hk2000c/archive/2007/10/31/157232.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Wed, 31 Oct 2007 08:32:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/31/157232.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/157232.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/31/157232.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/157232.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/157232.html</trackback:ping><description><![CDATA[<p>xxAction继承BaseAction,BaseAction注入了一个CommonManager，BaseAction.commonSave()方法调用了commonManager。</p>
<p>本来想xxAction调用父类的commonSave方法将会导致commonManager为null的错误，因为jvm去初始化BaseAction时并不会去注入CommonManger。 <br />
其实解决这个问题只需要在子类xxAction bean配置文件中加上commonManager这个property，然后把父类BaseAction的commonManager 改为protected就 Ok了。这样初始化子类的时候会注入commonManager，调用commonSave方法也就不会抛出npe了。</p>
<p>配置文件中把xxAction 加上parent的配置也是可以的，这样会把父类的所有property都注入</p>
<img src ="http://www.blogjava.net/hk2000c/aggbug/157232.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-31 16:32 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/31/157232.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>增加CMS static page 预读功能</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/31/157076.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Tue, 30 Oct 2007 16:22:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/31/157076.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/157076.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/31/157076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/157076.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/157076.html</trackback:ping><description><![CDATA[<br />
增加CMS static page 预读功能<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/157076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-31 00:22 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/31/157076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用户密码使用动态密钥SHA-512位加密</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/30/156924.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Tue, 30 Oct 2007 06:17:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/30/156924.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/156924.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/30/156924.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/156924.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/156924.html</trackback:ping><description><![CDATA[用户密码使用动态密钥SHA-512位加密<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/156924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-30 14:17 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/30/156924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>系统会给出step by step 的配置表单</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/30/156912.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Tue, 30 Oct 2007 05:29:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/30/156912.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/156912.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/30/156912.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/156912.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/156912.html</trackback:ping><description><![CDATA[系统会给出step by step 的配置表单<br />
<br />
配置比如 密码密钥 等 关键数据 <br />
<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/156912.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-30 13:29 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/30/156912.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>增加系统配置文件</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/30/156911.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Tue, 30 Oct 2007 05:23:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/30/156911.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/156911.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/30/156911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/156911.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/156911.html</trackback:ping><description><![CDATA[增加系统配置文件<br />
<br />
在 StartupListener 内&nbsp;<br />
&nbsp;<br />
每次重启读取<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/156911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-30 13:23 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/30/156911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>支持动态读取系统配置Url列表</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/30/156910.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Tue, 30 Oct 2007 05:22:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/30/156910.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/156910.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/30/156910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/156910.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/156910.html</trackback:ping><description><![CDATA[<br />
支持动态读取系统配置的url列表，标记为 static , 权限可配置<br />
&nbsp;<br />
放在 StartupListener 内。<br />
&nbsp;<br />
做到每次系统重启都自动更新，有校验匹配的功能。<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/156910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-30 13:22 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/30/156910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>增加用户名即时校验机制</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/29/156703.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Mon, 29 Oct 2007 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/29/156703.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/156703.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/29/156703.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/156703.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/156703.html</trackback:ping><description><![CDATA[增加用户名即时校验机制，可以即时查询用户名是否被占用。<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/156703.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-29 16:00 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/29/156703.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>加紧开发用户权限</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/27/156370.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Sat, 27 Oct 2007 09:29:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/27/156370.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/156370.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/27/156370.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/156370.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/156370.html</trackback:ping><description><![CDATA[完成了灵活表单开发。<br />
<br />
加紧开发用户权限,修正用户列表，用户编辑，用户添加，数据库支持。<br />
<br />
开发好以后就可以全面开发CMS系统了。<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/156370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-27 17:29 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/27/156370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>改进了spring 的校验机制</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/26/156227.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Fri, 26 Oct 2007 10:35:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/26/156227.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/156227.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/26/156227.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/156227.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/156227.html</trackback:ping><description><![CDATA[改进了spring 的校验机制<br />
<br />
重写了几个类，使得应用程序更加自由，可以自定义formName,不用绑定pojo名字。<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/156227.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-26 18:35 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/26/156227.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BaseCommandController initApplicationContext() 分析</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/26/155990.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Thu, 25 Oct 2007 17:12:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/26/155990.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/155990.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/26/155990.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/155990.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/155990.html</trackback:ping><description><![CDATA[BaseCommandController extends AbstractController extends WebContentGenerator WebContentGenerator extends WebApplicationObjectSupport extends ApplicationObjectSupport implements ApplicationContextAware&nbsp;<br />
<br />
/**<br />
&nbsp; * Subclasses can override this for custom initialization behavior.<br />
&nbsp; * Gets called by &lt;code&gt;setApplicationContext&lt;/code&gt; after setting the context instance.<br />
&nbsp; * &lt;p&gt;Note: Does &lt;/i&gt;not&lt;/i&gt; get called on reinitialization of the context<br />
&nbsp; * but rather just on first initialization of this object's context reference.<br />
&nbsp; * @throws ApplicationContextException in case of initialization errors<br />
&nbsp; * @throws BeansException if thrown by ApplicationContext methods<br />
&nbsp; * @see #setApplicationContext<br />
&nbsp; */<br />
&nbsp;protected void initApplicationContext() throws BeansException {<br />
&nbsp;}<br />
<br />
愿意为子类可以把初始化bean 动作放入此方法，可以自定义一些动作。<br />
<br />
我们再来看看调用<br />
public final void setApplicationContext(ApplicationContext context) throws BeansException {<br />
&nbsp;&nbsp;if (context == null &amp;&amp; !isContextRequired()) {<br />
&nbsp;&nbsp;&nbsp;// Reset internal context state.<br />
&nbsp;&nbsp;&nbsp;this.applicationContext = null;<br />
&nbsp;&nbsp;&nbsp;this.messageSourceAccessor = null;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else if (this.applicationContext == null) {<br />
&nbsp;&nbsp;&nbsp;// Initialize with passed-in context.<br />
&nbsp;&nbsp;&nbsp;if (!requiredContextClass().isInstance(context)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;throw new ApplicationContextException(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Invalid application context: needs to be of type [" + requiredContextClass().getName() + "]");<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;this.applicationContext = context;<br />
&nbsp;&nbsp;&nbsp;this.messageSourceAccessor = new MessageSourceAccessor(context);<br />
&nbsp;&nbsp;&nbsp;initApplicationContext();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else {<br />
&nbsp;&nbsp;&nbsp;// Ignore reinitialization if same context passed in.<br />
&nbsp;&nbsp;&nbsp;if (this.applicationContext != context) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;throw new ApplicationContextException(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Cannot reinitialize with different application context: current one is [" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.applicationContext + "], passed-in one is [" + context + "]");<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
<br />
可以看到由 ApplicationObjectSupport&nbsp; 的 setApplicationContext 方法调用 <br />
而此方法为 ApplicationContextAware 的唯一接口方法，<br />
<p>public interface ApplicationContextAware {<br />
&nbsp;<br />
&nbsp;/** <br />
&nbsp; * Set the ApplicationContext that this object runs in.<br />
&nbsp; * Normally this call will be used to initialize the object.<br />
&nbsp; * &lt;p&gt;Invoked after population of normal bean properties but before an init callback such<br />
&nbsp; * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}<br />
&nbsp; * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},<br />
&nbsp; * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and<br />
&nbsp; * {@link MessageSourceAware}, if applicable.<br />
&nbsp; * @param applicationContext the ApplicationContext object to be used by this object<br />
&nbsp; * @throws ApplicationContextException in case of context initialization errors<br />
&nbsp; * @throws BeansException if thrown by application context methods<br />
&nbsp; * @see org.springframework.beans.factory.BeanInitializationException<br />
&nbsp; */<br />
&nbsp;void setApplicationContext(ApplicationContext applicationContext) throws BeansException;</p>
<p>}<br />
<br />
此方法被&nbsp;ApplicationContextAwareProcessor&nbsp;的 postProcessBeforeInitialization&nbsp; 调用 <br />
ApplicationContextAwareProcessor implements BeanPostProcessor&nbsp;<br />
&nbsp;public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {<br />
&nbsp;&nbsp;if (bean instanceof ResourceLoaderAware) {<br />
&nbsp;&nbsp;&nbsp;((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if (bean instanceof ApplicationEventPublisherAware) {<br />
&nbsp;&nbsp;&nbsp;((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if (bean instanceof MessageSourceAware) {<br />
&nbsp;&nbsp;&nbsp;((MessageSourceAware) bean).setMessageSource(this.applicationContext);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if (bean instanceof ApplicationContextAware) {<br />
&nbsp;&nbsp;&nbsp;((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return bean;<br />
&nbsp;}<br />
<br />
<br />
</p>
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/155990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-26 01:12 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/26/155990.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring validator 分析</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/26/155989.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Thu, 25 Oct 2007 16:48:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/26/155989.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/155989.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/26/155989.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/155989.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/155989.html</trackback:ping><description><![CDATA[<p>以 BaseCommandController 为例<br />
protected void initApplicationContext() {<br />
&nbsp;&nbsp;if (this.validators != null) {<br />
&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; this.validators.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (this.commandClass != null &amp;&amp; !this.validators[i].supports(this.commandClass))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new IllegalArgumentException("Validator [" + this.validators[i] +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"] does not support command class [" +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.commandClass.getName() + "]");<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
<br />
子类配置如下<br />
<br />
&nbsp;&lt;bean id="addNewsController" class="AddNewsController" scope="request"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="formView" value="/management/news/addNews"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="validator" ref="beanValidator"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="successView" value="forward:/management/news/newsList.html"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="commandClass" value="News"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="commandName" value="news"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
<br />
public final void setValidator(Validator validator) {<br />
&nbsp;&nbsp;this.validators = new Validator[] {validator};<br />
&nbsp;}<br />
<br />
设置Validator数组 <br />
<br />
在初始化的时候，检验 是否支持command 类型 <br />
this.validators[i].supports(this.commandClass)<br />
<br />
此support 为 org.springframework.validation.Validator 的所有 实现类的 方法，检验支持检验类的动作。<br />
<br />
<br />
举例 配置<br />
&nbsp;&lt;bean id="beanValidator" class="org.springmodules.validation.commons.DefaultBeanValidator"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="validatorFactory" ref="validatorFactory"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
<br />
DefaultBeanValidator extends AbstractBeanValidator implements Validator<br />
<br />
再看实现方法<br />
<br />
&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Checks if the validatorFactory is configured to handle this class.&nbsp; Will<br />
&nbsp;&nbsp;&nbsp;&nbsp; * convert the class into a form name, suitable for commons validator.<br />
&nbsp;&nbsp;&nbsp;&nbsp; *<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @return &lt;code&gt;true&lt;/code&gt; if the validatorFactory supports the class,<br />
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or &lt;code&gt;false&lt;/code&gt; if not<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see #getFormName(Class)<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public boolean supports(Class clazz) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean canSupport = validatorFactory.hasRulesForBean(getFormName(clazz), getLocale());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (log.isDebugEnabled()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.debug("validatorFactory " + (canSupport ? "does" : "does not")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + " support class " + clazz + " with form name " + getFormName(clazz));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return canSupport;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
检验是否支持输入类<br />
<br />
另一个方法<br />
&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * If &lt;code&gt;useFullyQualifiedClassName&lt;/code&gt; is false (default value), this function returns a<br />
&nbsp;&nbsp;&nbsp;&nbsp; * string containing the uncapitalized, short name for the given class<br />
&nbsp;&nbsp;&nbsp;&nbsp; * (e.g. myBean for the class com.domain.test.MyBean). Otherwise, it&nbsp; returns the value<br />
&nbsp;&nbsp;&nbsp;&nbsp; * returned by &lt;code&gt;Class.getName()&lt;/code&gt;.<br />
&nbsp;&nbsp;&nbsp;&nbsp; *<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param cls &lt;code&gt;Class&lt;/code&gt; of the bean to be validated.<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @return the bean name.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; protected String getFormName(Class cls) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (this.useFullyQualifiedClassName) ? cls.getName() : Introspector.decapitalize(ClassUtils.getShortName(cls));<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;Introspector.decapitalize(ClassUtils.getShortName(cls) 获得按照西班牙命名法的form 名 <br />
<br />
这个方法本意是获得以类名为formName 的所有校验配置。<br />
<br />
实际上有一个重大的设计缺陷 <br />
<br />
<br />
<br />
<br />
<br />
<br />
</p>
<img src ="http://www.blogjava.net/hk2000c/aggbug/155989.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-26 00:48 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/26/155989.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>还要增加command 的记忆功能</title><link>http://www.blogjava.net/hk2000c/archive/2007/10/25/155903.html</link><dc:creator>hk2000c</dc:creator><author>hk2000c</author><pubDate>Thu, 25 Oct 2007 09:01:00 GMT</pubDate><guid>http://www.blogjava.net/hk2000c/archive/2007/10/25/155903.html</guid><wfw:comment>http://www.blogjava.net/hk2000c/comments/155903.html</wfw:comment><comments>http://www.blogjava.net/hk2000c/archive/2007/10/25/155903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hk2000c/comments/commentRss/155903.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hk2000c/services/trackbacks/155903.html</trackback:ping><description><![CDATA[还要增加command 的记忆功能，主要是为了表单验证失败以后，在服务器端控制表单内容不丢失问题。<br />
<br />
<img src ="http://www.blogjava.net/hk2000c/aggbug/155903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hk2000c/" target="_blank">hk2000c</a> 2007-10-25 17:01 <a href="http://www.blogjava.net/hk2000c/archive/2007/10/25/155903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>