﻿<?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-贫以智为贵,富以仁为贵.-文章分类-Spring专题</title><link>http://www.blogjava.net/LeungXin/category/26009.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 18 Dec 2007 17:34:55 GMT</lastBuildDate><pubDate>Tue, 18 Dec 2007 17:34:55 GMT</pubDate><ttl>60</ttl><item><title>OpenSessionInView模式（转）</title><link>http://www.blogjava.net/LeungXin/articles/167651.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Fri, 14 Dec 2007 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/167651.html</guid><description><![CDATA[Spring+Hibernate中，&nbsp; 集合映射如果使用lazy="true"， 当PO传到View层时， 出现未初始化session已关闭的错误，只能在dao先初始化
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">parent.getChilds().size();</span></div>
<a href="www.blogjava.net/waterye/archive/2005/08/23/10836.aspx">www.blogjava.net/waterye/archive/2005/08/23/10836.aspx</a>转自<br />
<br />
Spring提供Open Session In View来解决这个问题, 有两种方式<br />
1. Interceptor
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008000">&nbsp;&nbsp;&nbsp; &lt;!--</span><span style="color: #008000">&nbsp;===========&nbsp;OpenSession&nbsp;In&nbsp;View&nbsp;pattern&nbsp;==============</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">bean&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="openSessionInViewInterceptor"</span><span style="color: #ff0000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff">="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">property&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="sessionFactory"</span><span style="color: #ff0000">&nbsp;ref</span><span style="color: #0000ff">="sessionFactory"</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">bean&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="urlMapping"</span><span style="color: #ff0000">&nbsp;class</span><span style="color: #0000ff">="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">property&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="interceptors"</span><span style="color: #ff0000">&nbsp;ref</span><span style="color: #0000ff">="openSessionInViewInterceptor"</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">property&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="mappings"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">props</span><span style="color: #0000ff">&gt;<br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">props</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">property</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></div>
2. Filter
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">&lt;</span><span style="color: #800000">web-app</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;<br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">hibernateFilter</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter-class</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
org.springframework.orm.hibernate.support.OpenSessionInViewFilter<br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter-class</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;<br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter-mapping</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">hibernateFilter</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter-name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">url-pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">*.do</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">url-pattern</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">filter-mapping</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">web-app</span><span style="color: #0000ff">&gt;</span></div>
<br />
说明： 个人更喜欢用Interceptor方式， filter是在web.xml中定义<br />
有了OpenSessionInView，并不是一切就ok了。简单的crud可以，但对于复杂业务逻辑就要想点法子。<br />
<br />
OSIV默认是request per session的, 所以即使没有显式update(po)，Hibernate也会帮你保存的，dao的业务判断就无效，还好有evict()可用。<br />
update code
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">// Controller<br />
</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;ModelAndView&nbsp;update()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;dao.getVo(id);<br />
&nbsp;&nbsp;&nbsp;&nbsp;bindObject(request);<br />
&nbsp;&nbsp;&nbsp;&nbsp;dao.update(p);<br />
}<br />
<br />
// Dao<br />
</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Object&nbsp;getVo(id)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;getHibernateTemplate().get(clazz,&nbsp;id);<br />
&nbsp;&nbsp;&nbsp;&nbsp;p.getChilds().size();<br />
&nbsp;&nbsp;&nbsp;&nbsp;getHibernateTemplate().evict(p);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;p;<br />
}<br />
<br />
</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;update(p)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;oldP&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;getVo(id);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;++--(oldP);</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;getHibernateTemplate().update(p);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;++--(p);</span><span style="color: #008000"><br />
</span><span style="color: #000000">}</span></div>
<p class="postfoot">posted on 2005-08-23 21:58 <a href="http://www.blogjava.net/waterye/">water ye</a> 阅读(3370) <a href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#Post">评论(7)</a> &nbsp;<a href="http://www.blogjava.net/waterye/admin/EditPosts.aspx?postid=10836">编辑</a> &nbsp;<a href="http://www.blogjava.net/waterye/AddToFavorite.aspx?id=10836">收藏</a> 所属分类: <a href="http://www.blogjava.net/waterye/category/2864.html">spring</a> </p>
<img height="1" src="http://www.blogjava.net/waterye/aggbug/10836.html?webview=1" width="1"  alt="" /> <!-- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://www.blogjava.net/waterye/archive/2005/08/23/10836.html" dc:identifier="http://www.blogjava.net/waterye/archive/2005/08/23/10836.html" dc:title="OpenSessionInView模式" trackback:ping="http://www.blogjava.net/waterye/services/trackbacks/10836.aspx"  />
</rdf:RDF>
--><script type="text/javascript">
//<![cdata[ Sys.WebForms.PageRequestManager._initialize('AjaxHolder$scriptmanager1', document.getElementById('Form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tAjaxHolder$UpdatePanel1'], [], [], 90);
//]]&gt;
</script>
<div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a>
<div id="comments">
<h3>Feedback</h3>
<h4><a title="permalink: re: OpenSessionInView模式" href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#11010">#</a>&nbsp;<a name="11010"></a>re: OpenSessionInView模式 <span>2005-08-25 12:35 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://www.blogjava.net/calvin" target="_blank">江南白衣@ITO</a> </h4>
<p>load,get对evict()的影响呢?&nbsp;&nbsp;<a onclick='return SetReplyAuhor("江南白衣@ITO")' href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#post">回复</a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.blogjava.net/comment?author=%e6%b1%9f%e5%8d%97%e7%99%bd%e8%a1%a3%40ITO" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl00$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </p>
<h4><a title="permalink: re: OpenSessionInView模式" href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#11021">#</a>&nbsp;<a name="11021"></a>re: OpenSessionInView模式 <span>2005-08-25 13:00 </span><a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.blogjava.net/waterye" target="_blank">Water Ye@ITO</a> </h4>
<p>load大概是从cache中查询数据, get是从db查询数据, 所以evict()要和get()结合来使用&nbsp;&nbsp;<a onclick='return SetReplyAuhor("Water Ye@ITO")' href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#post">回复</a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.blogjava.net/comment?author=Water+Ye%40ITO" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl01$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a> </p>
<h4><a title="permalink: re: OpenSessionInView模式" href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#11124">#</a>&nbsp;<a name="11124"></a>re: OpenSessionInView模式 <span>2005-08-25 21:30 </span><a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" href="http://www.blogjava.net/calvin" target="_blank">江南白衣@ITO</a> </h4>
<p>网上讲这种Open session in view 与 evict()结合的文章好象没有阿，难道大家没遇到同样的问题，如果做ERP应改很经常遇到。&nbsp;&nbsp;<a onclick='return SetReplyAuhor("江南白衣@ITO")' href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#post">回复</a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.blogjava.net/comment?author=%e6%b1%9f%e5%8d%97%e7%99%bd%e8%a1%a3%40ITO" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl02$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a> </p>
<h4><a title="permalink: re: OpenSessionInView模式" href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#11128">#</a>&nbsp;<a name="11128"></a>re: OpenSessionInView模式 <span>2005-08-25 21:38 </span><a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" href="http://www.blogjava.net/waterye" target="_blank">Water Ye@ITO</a> </h4>
<p>估计大家都没有开OSIV吧&nbsp;&nbsp;<a onclick='return SetReplyAuhor("Water Ye@ITO")' href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#post">回复</a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.blogjava.net/comment?author=Water+Ye%40ITO" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl03$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a> </p>
<h4><a title="permalink: re: OpenSessionInView模式" href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#11471">#</a>&nbsp;<a name="11471"></a>re: OpenSessionInView模式 <span>2005-08-29 17:16 </span><a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" href="http://www.blogjava.net/waterye" target="_blank">Water Ye@ITO</a> </h4>
<p>或许可以用Detached queries来代替evict()&nbsp;&nbsp;<a onclick='return SetReplyAuhor("Water Ye@ITO")' href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#post">回复</a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.blogjava.net/comment?author=Water+Ye%40ITO" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl04_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl04$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl04_EditLink"></a> </p>
<h4><a title="permalink: re: OpenSessionInView模式" href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#51360">#</a>&nbsp;<a name="51360"></a>re: OpenSessionInView模式 <span>2006-06-08 14:57 </span><a id="AjaxHolder_Comments_CommentList_ctl05_NameLink" target="_blank">Ghost</a> </h4>
<p>我项目中采用了OpenSessionInView!&nbsp;&nbsp;<a onclick='return SetReplyAuhor("Ghost")' href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#post">回复</a>&nbsp;&nbsp;<a title="查看该作者发表过的评论" href="http://www.blogjava.net/comment?author=Ghost" target="_blank">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl05_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl05$DeleteLink','')"></a>&nbsp;&nbsp;<a id="AjaxHolder_Comments_CommentList_ctl05_EditLink"></a> </p>
<h4><a title="permalink: re: OpenSessionInView模式[未登录]" href="http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx#129350">#</a>&nbsp;<a name="129350"></a>re: OpenSessionInView模式[未登录]<a name="Post"></a> <span>2007-07-10 15:27 </span><a id="AjaxHolder_Comments_CommentList_ctl06_NameLink" target="_blank">Chris</a> </h4>
<p>p.getChilds().size();<br />
是做什么用的。</p>
</div>
</div>
<img src ="http://www.blogjava.net/LeungXin/aggbug/167651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-12-14 09:09 <a href="http://www.blogjava.net/LeungXin/articles/167651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用P6SPY测试程序</title><link>http://www.blogjava.net/LeungXin/articles/167385.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Thu, 13 Dec 2007 01:35:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/167385.html</guid><description><![CDATA[<p>运行环境Tomcat5.5.16,Windows2000 Adv</p>
<p>程序架构Spring+hibernate</p>
<p>首先从<a href="http://www.p6spy.com/">www.p6spy.com</a>下载jar文件,下载最新软件包p6spy-install.zip,从压缩包中取出p6spy.jar和spy.properties文件.</p>
<p>把p6spy.jar放到classpath下,我是放到project下的WEB/INF/lib里,把spy.properties放到src/下.</p>
<p>打开hibernate.xml,我的是application-hibernate.xml,进行如下配置</p>
<p>&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;<br />
&lt;!--&nbsp;&nbsp;&nbsp; <font color="#00ff00">&lt;property name="driverClassName"&gt;&lt;value&gt;net.sourceforge.jtds.jdbc.Driver&lt;/value&gt;&lt;/property&gt;</font> --&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">&lt;property name="driverClassName"&gt;&lt;value&gt;com.p6spy.engine.spy.P6SpyDriver&lt;/value&gt;&lt;/property&gt;<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="url"&gt;&lt;value&gt;jdbc:jtds:sqlserver://127.0.0.1:1433/jspd10&lt;/value&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="username"&gt;&lt;value&gt;sa&lt;/value&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- Make sure &lt;value&gt; tags are on same line - if they're not, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; authentication will fail --&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="password"&gt;&lt;value&gt;&lt;/value&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
<br />
绿字为以前的driver,红字为替换后的</p>
<p>接下来在spy.properties下的realdriver加上</p>
<p># sql servler Driver<br />
&nbsp; realdriver=net.sourceforge.jtds.jdbc.Driver</p>
<p>这里的realdriver是<font color="#00ff00">绿字</font>的</p>
<p>我的是windows系统,所以我把log文件放在D:\spy.log下<br />
<br />
# name of logfile to use, note Windows users should make sure to use forward slashes in their pathname (e:/test/spy.log) (used for file logger only)<br />
logfile&nbsp;&nbsp;&nbsp;&nbsp; = d:/spy.log<br />
<br />
重新启动Tomcat,发现D盘下存在spy.log,运行程序产生log,配置完毕</p>
<img src ="http://www.blogjava.net/LeungXin/aggbug/167385.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-12-13 09:35 <a href="http://www.blogjava.net/LeungXin/articles/167385.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简化Spring--配置文件</title><link>http://www.blogjava.net/LeungXin/articles/146904.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Thu, 20 Sep 2007 12:10:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/146904.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 人人都爱Spring加Hibernate。&nbsp;&nbsp;&nbsp;&nbsp;但Spring MVC+hibernate的Sample如Appfuse的代码却算不得最简洁优美好读，如果在自己的项目中继续发挥我们最擅长的依样画葫芦大法，美好愿望未必会实现。 &nbsp;&nbsp;&nbsp;&nbsp; 所以，Pramatic精神不灭。这个系列就是探寻最适合自己的Spring+...&nbsp;&nbsp;<a href='http://www.blogjava.net/LeungXin/articles/146904.html'>阅读全文</a><img src ="http://www.blogjava.net/LeungXin/aggbug/146904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-09-20 20:10 <a href="http://www.blogjava.net/LeungXin/articles/146904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring事务探索</title><link>http://www.blogjava.net/LeungXin/articles/146654.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Wed, 19 Sep 2007 18:35:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/146654.html</guid><description><![CDATA[<p>spring自建事务管理模块。而且这个事务管理是一个抽象设计，可以应用到很多场合，包括普通的DataSource，jta，jms和hibernate上。</p>
<p>要正确使用spring的事务，首先需要了解spring在事务设计上的一些概念<br />
统观spring事务，围绕着两个核心PlatformTransactionManager和TransactionStatus</p>
<p>PlatformTransactionManager直译过来就是平台相关事务，这里的平台指的是&#8220;事务源&#8221;，包括刚才我说的 DataSource，jta等等。这些无一不是一个事务源。广义的说，凡是可以完成事务性操作的对象，都可以设计出相对应的 PlatformTransactionManager，只要这个事务源支持commit，rollback和getTransaction语意。</p>
<p>查看spring代码，可以发现这些manager实现事务，就是调用事务源的事务操作方法</p>
<p>比如</p>
<p>HibernateTransactionManager<br />
那么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中的一段代码</p>
<p>这是直接使用transactionManager的例子，可以看到真正执行business logic 的地方是在try当中那段，前后的代码都是为了完成事务管理的。如果每个business logic都要写上那么一段，我肯定是疯了。我们翻出TransactionTemplate的代码看看他怎么化简了我们的代码<br />
同上面的代码如出一辙，前后是事务处理代码，当中那段result = action.doInTransaction(status);是我们的应用代码。至于action是什么，全看各位的需要了。但是有一点要主要，如果 利用TransactionTemplate，那么他不管你扔出什么异常都会回滚事务，但是回滚的是哪个事务呢？继续挖代码</p>
<p>真相大白，是对template所持有的某个transactionManager进行回滚。所以如果你的应用代码用的是事务源a的一些资源，比 如到服务器a的一个datasource，但是你的transactionManager管理的是另一些资源，比如服务器b的一个datasource， 代码铁定不会正常运行特别是在一些多事务源的程序里，这点千万不能搞错。如果多个事务源之间要完成全局事务，还是老老实实用分布式事务管理服务吧（jta）</p>
<p>那么TransactionInterceptor是干什么的？这个是spring 的声明式事务的支持方式。因为用TransactionTemplate要硬编码，而且调整事务策略很麻烦（不是说不能调。举个例子原来程序抛出异常A需 要回滚，现在不需要要，我就可以把a catch吃掉。这时候template就不会回滚了。但是每次调整都要重写编码。）而用TransactionInterceptor就可以将这些调整 写在配置中。我们再来挖TransactionInterceptor的代码</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>
<img src ="http://www.blogjava.net/LeungXin/aggbug/146654.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-09-20 02:35 <a href="http://www.blogjava.net/LeungXin/articles/146654.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring AOP中文教程 </title><link>http://www.blogjava.net/LeungXin/articles/146653.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Wed, 19 Sep 2007 18:29:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/146653.html</guid><description><![CDATA[<p>AOP正在成为软件开发的下一个圣杯。使用AOP，你可以将处理aspect的代码注入主程序，通常主程序的主要目的并不在于处理这些aspect。AOP可以防止代码混乱。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 为了理解AOP如何做到这点，考虑一下记日志的工作。日志本身不太可能是你开发的主程序的主要任务。如果能将&#8220;不可见的&#8221;、通用的日志代码注入主程序中，那该多好啊。AOP可以帮助你做到。<br />
Spring framework是很有前途的AOP技术。作为一种非侵略性的，轻型的AOP framework，你无需使用预编译器或其他的元标签，便可以在Java程序中使用它。这意味着开发团队里只需一人要对付AOP framework，其他人还是象往常一样编程。<br />
&nbsp;&nbsp;&nbsp;&nbsp; AOP是很多直觉难以理解的术语的根源。幸运的是，你只要理解三个概念，就可以编写AOP模块。这三个概念是：advice，pointcut和 advisor。advice是你想向别的程序内部不同的地方注入的代码。pointcut定义了需要注入advice的位置，通常是某个特定的类的一个 public方法。advisor是pointcut和advice的装配器，是将advice注入主程序中预定义位置的代码。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 既然我们知道了需要使用advisor向主要代码中注入&#8220;不可见的&#8221;advice，让我们实现一个Spring AOP的例子。在这个例子中，我们将实现一个before advice，这意味着advice的代码在被调用的public方法开始前被执行。以下是这个before advice的实现代码：<br />
<br />
代码:<br />
package com.company.springaop.test;<br />
<br />
import java.lang.reflect.Method;<br />
import org.springframework.aop.MethodBeforeAdvice;<br />
<br />
public class TestBeforeAdvice implements MethodBeforeAdvice {<br />
<br />
&nbsp;&nbsp; public void before(Method m, Object[] args, Object target)<br />
&nbsp;&nbsp; throws Throwable {<br />
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Hello world! (by "<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + this.getClass().getName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ")");<br />
&nbsp;&nbsp; }<br />
}<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 接口MethodBeforeAdvice只有一个方法before需要实现，它定义了advice的实现。before方法共用三个参数，它们提供了相当丰富的信息。参数Method m是advice开始后执行的方法。方法名称可以用作判断是否执行代码的条件。Object[] args是传给被调用的public方法的参数数组。当需要记日志时，参数args和被执行方法的名称，都是非常有用的信息。你也可以改变传给m的参数，但要小心使用这个功能；编写最初主程序的程序员并不知道主程序可能会和传入参数的发生冲突。Object target是执行方法m对象的引用。<br />
<br />
在下面的BeanImpl类中，每个public方法调用前，都会执行advice：<br />
<br />
代码:<br />
package com.company.springaop.test;<br />
<br />
public class BeanImpl implements Bean {<br />
<br />
&nbsp;&nbsp; public void theMethod() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(this.getClass().getName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "." + new Exception().getStackTrace()[0].getMethodName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "()"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + " says HELLO!");<br />
&nbsp;&nbsp; }<br />
}<br />
<br />
<br />
类BeanImpl实现了下面的接口Bean：<br />
<br />
代码:<br />
package com.company.springaop.test;<br />
<br />
public interface Bean {<br />
&nbsp;&nbsp; public void theMethod();<br />
}<br />
<br />
<br />
<br />
虽然不是必须使用接口，但面向接口而不是面向实现编程是良好的编程实践，Spring也鼓励这样做。<br />
<br />
pointcut和advice通过配置文件来实现，因此，接下来你只需编写主方法的Java代码：<br />
代码:<br />
<br />
<br />
package com.company.springaop.test;<br />
<br />
import org.springframework.context.ApplicationContext;<br />
import org.springframework.context.support.FileSystemXmlApplicationContext;<br />
<br />
public class Main {<br />
<br />
&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; //Read the configuration file<br />
&nbsp;&nbsp;&nbsp;&nbsp; ApplicationContext ctx<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = new FileSystemXmlApplicationContext("springconfig.xml");<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; //Instantiate an object<br />
&nbsp;&nbsp;&nbsp;&nbsp; Bean x = (Bean) ctx.getBean("bean");<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; //Execute the public method of the bean (the test)<br />
&nbsp;&nbsp;&nbsp;&nbsp; x.theMethod();<br />
&nbsp;&nbsp; }<br />
}<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 我们从读入和处理配置文件开始，接下来马上要创建它。这个配置文件将作为粘合程序不同部分的&#8220;胶水&#8221;。读入和处理配置文件后，我们会得到一个创建工厂ctx。任何一个Spring管理的对象都必须通过这个工厂来创建。对象通过工厂创建后便可正常使用。</p>
<p>仅仅用配置文件便可把程序的每一部分组装起来。<br />
代码:<br />
<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE beans PUBLIC&nbsp;&nbsp; "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&gt;<br />
<br />
&lt;beans&gt;<br />
&nbsp;&nbsp; &lt;!--CONFIG--&gt;<br />
&nbsp;&nbsp; &lt;bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="proxyInterfaces"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;com.company.springaop.test.Bean&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="beanTarget"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="interceptorNames"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;theAdvisor&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp; &lt;/bean&gt;<br />
<br />
&lt;!--CLASS--&gt;<br />
&nbsp;&nbsp; &lt;bean id="beanTarget" class="com.company.springaop.test.BeanImpl"/&gt;<br />
<br />
&nbsp;&nbsp; &lt;!--ADVISOR--&gt;<br />
&nbsp;&nbsp; &lt;!--Note: An advisor assembles pointcut and advice--&gt;<br />
&nbsp;&nbsp; &lt;bean id="theAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="advice"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="theBeforeAdvice"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="pattern"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;com\.company\.springaop\.test\.Bean\.theMethod&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp; &lt;/bean&gt;<br />
<br />
&nbsp;&nbsp; &lt;!--ADVICE--&gt;<br />
&nbsp;&nbsp; &lt;bean id="theBeforeAdvice" class="com.company.springaop.test.TestBeforeAdvice"/&gt;<br />
&lt;/beans&gt;<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 四个bean定义的次序并不重要。我们现在有了一个advice，一个包含了正则表达式pointcut的advisor，一个主程序类和一个配置好的接口，通过工厂ctx，这个接口返回自己本身实现的一个引用。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; BeanImpl和TestBeforeAdvice都是直接配置。我们用一个唯一的ID创建一个bean元素，并指定了一个实现类。这就是全部的工作。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; advisor通过Spring framework提供的一个RegexMethodPointcutAdvisor类来实现。我们用advisor的一个属性来指定它所需的 advice-bean。第二个属性则用正则表达式定义了pointcut，确保良好的性能和易读性。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 最后配置的是bean，它可以通过一个工厂来创建。bean的定义看起来比实际上要复杂。bean是ProxyFactoryBean的一个实现，它是Spring framework的一部分。这个bean的行为通过一下的三个属性来定义：<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 属性proxyInterface定义了接口类。<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 属性target指向本地配置的一个bean，这个bean返回一个接口的实现。<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 属性interceptorNames是唯一允许定义一个值列表的属性。这个列表包含所有需要在beanTarget上执行的advisor。注意，advisor列表的次序是非常重要的。<br />
<br />
<br />
<br />
<strong>Spring工具</strong><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 虽然你可以手工修改Ant构建脚本，但使用SpringUI（译注：SpringUI现在是Spring framework的一部分，并改名为spring-ide），使用Spring AOP变得很简单，只要点点鼠标即可。你可以把SpringUI安装成Eclipse的一个plug-in。然后，你只需在你的project上右击鼠标，并选择&#8220;add Spring Project Nature&#8221;。在project属性中，你可以在&#8220;Spring Project&#8221;下添加Spring配置文件。在编译前把下面的类库加入project：aopalliance.jar，commons- logging.jar，jakarta-oro-2.0.7.jar和spring.jar。运行程序时你会看到下面的信息：<br />
<br />
... (logging information)<br />
Hello world! (by com.company.springaop.test.TestBeforeAdvice)<br />
com.company.springaop.test.BeanImpl.theMethod() says HELLO!<br />
<br />
<br />
<strong>优点和缺点</strong><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; Spring比起其他的framework更有优势，因为除了AOP以外，它提供了更多别的功能。作为一个轻型framework，它在J2EE 不同的部分都可以发挥作用。因此，即使不想使用Spring AOP，你可能还是想使用Spring。另一个优点是，Spring并不要求开发团队所有的人员都会用它。学习Spring应该从Spring reference的第一页开始。读了本文后，你应该可以更好地理解Spring reference了。Spring唯一的缺点是缺乏更多的文档，但它的mailing list是个很好的补充，而且会不断地出现更多的文档。</p>
<img src ="http://www.blogjava.net/LeungXin/aggbug/146653.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-09-20 02:29 <a href="http://www.blogjava.net/LeungXin/articles/146653.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring框架的事务管理应用分析 </title><link>http://www.blogjava.net/LeungXin/articles/146652.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Wed, 19 Sep 2007 18:27:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/146652.html</guid><description><![CDATA[在<a href="http://www.5iask.com/" target="_blank">软件开发</a>中出现过各种各样的框架，开源软件的兴起，使得各种各样的框架纷纷出现，例如，Apache组织下就拥有诸多的框架类产品。框架就是一组协同工作的类，它们为特定类型的软件构筑了一个可重用的设计。然而，传统的框架使得应用程序组件过分依赖于框架中的类，这种耦合度的提高降低了组件的复用性。Spring框架的出现，使得组件之间更松散的耦合成为了可能。<br />
<br />
　　<strong>Spring框架简介</strong><br />
<br />
　　Spring框架是一个2003年2月才出现的开源项目，该开源项目起源自Rod Johnson在2002年末出版的《Expert One-on-One J2EE Design and Development》一书中的<a href="http://www.5iask.com/java/base/" target="_blank">基础</a>性代码。在该书中，Rod Johnson倡导J2EE实用主义的设计思想，而Spring框架正是这一思想的更全面和具体的实现。Spring框架由一个容器，一个配置和组织组件的框架，和一组内置的为事务、持久化和<a title="web开发" href="http://www.5iask.com/asp">web</a>用户接口提供的服务组成。作为一种轻量级的J2EE框架，Spring提供了一种有效的方式来建立和组织J2EE应用程序。<br />
<br />
　　1、Spring特性<br />
<br />
　　IoC(Inversion of Control；控制反转)；又称DI(Dependency Injection；依赖注入)；是面向对象领域新兴的编程思想；也是Spring的精髓所在。简单地说；IoC就是指程序之间的关系由容器来控制；而不是传统实现中由程序代码直接操控。这也就是所谓&#8220;控制反转&#8221;的概念所在：控制权由应用代码转到外部容器，控制权的转移，也就是所谓的反转。IoC将控制创建的职责搬进了框架中；并把它从应用代码脱离开来。当使用Spring的IoC容器时只需指出组件需要的对象，在运行时Spring的IoC容器会根据<a href="http://www.5iask.com/web/xml/" target="_blank">XML</a>配置数据提供给它。<br />
<br />
　　Spring IoC，借助于依赖注入<a href="http://www.5iask.com/java/adv/pattern/" target="_blank">设计模式</a>，使得开发者不用理会对象自身的生命周期极其关系，而且能够改善开发者对模式的使用。对于一个对象的管理不是什么困难，难就难在对整个对象群的管理。依赖注入可以让容器管理对象，即&#8220;Don&#8217;t call me, I will call you&#8221;。这样对象本身的生命周期以及对象之间的关系就不再让开发者费神了。 <br />
<br />
　　Spring AOP，借助于Spring实现拦截器，开发者能够实现以声名方式使用企业级服务，比如安全性服务、事务服务。AOP 合理的补充了OOP，借助于Spring AOP，开发者能够高效的使用J2EE服务。<br />
<br />
　　Spring服务抽象，借助于各种J2EE API抽象，使得开发者能够一致地使用J2EE 技术，而不管具体是使用什么J2EE API，借助于Spring服务抽象，使代码大大减少，满足&#8220;更少代码，更少BUG&#8221;的软件设计原则。<br />
<br />
　　Spring IoC+Spring AOP+Spring服务抽象，一起形成Spring，这样一个有机体，使构建轻量级J2EE成为可能。<br />
<br />
　　<strong>Spring提供的事务管理</strong><br />
<br />
　　Spring提供的事务管理可以分为两类：编程式的和声明式的。编程式的，比较灵活，但是代码量大，存在重复的代码比较多；声明式的比编程式的更灵活方便。<br />
<br />
　　1、传统使用<a href="http://www.5iask.com/java/adv/jdbc/" target="_blank">JDBC</a>的事务管理<br />
<br />
　　以往使用JDBC进行数据操作，使用DataSource，从数据源中得到Connection，我们知道数据源是<a href="http://www.5iask.com/java/adv/thread/" target="_blank">线程</a>安全的，而连接不是线程安全的，所以对每个请求都是从数据源中重新取出一个连接。一般的数据源由容器进行管理，包括连接池。例如TOMCAT，<a title="web开发" href="http://www.5iask.com/asp">web</a>SPHERE，<a title="web开发" href="http://www.5iask.com/asp">web</a>LOGIC等这些J2EE商业容器都提供了这个功能。<br />
<br />
　　以往的我们使用JDBC在写代码时，事务管理可能会是这样：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>Connection conn = null;<br />
            try{<br />
            　conn = DBConnectionFactory.getConnection;<br />
            　conn.setAutoCommit(false);<br />
            　//do something<br />
            　conn.commit(); //commit transcation<br />
            }catch(Exception e){<br />
            　conn.rollback();<br />
            }<br />
            finally{<br />
            　try{<br />
            　　conn.close();<br />
            　} catch(SQLException se){ //do sth.}<br />
            　//close ResultSet,PreparedStatement,Connection <br />
            　//notice:Maybe ocurr Exception when u close rs,pstmt,conn<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　按照以往的思路来写代码，代码量比较长，而且容易疏忽，忘掉一些try/catch，引发一些异常无法catch，虽然有时候我们会写DBTool类，来关闭这些资源，并且保证在关闭这些资源时，不向外抛异常，但是这样做会导致额外的麻烦。<br />
<br />
　　2、Spring提供的编程式的事务处理<br />
<br />
　　Spring提供了几个关于事务处理的类：TransactionDefinition //事务属性定义<br />
<br />
　　TranscationStatus //代表了当前的事务，可以提交，回滚。 <br />
<br />
　　PlatformTransactionManager这个是spring提供的用于管理事务的基础接口，其下有一个实现的抽象类AbstractPlatformTransactionManager，我们使用的事务管理类例如DataSourceTransactionManager等都是这个类的子类。<br />
<br />
　　我们使用编程式的事务管理流程可能如下：<br />
<br />
　　(1) 声明数据源。<br />
<br />
　　(2) 声明一个事务管理类，例如：DataSourceTransactionManager,<a href="http://www.5iask.com/java/struts/" target="_blank">Hibernate</a>TransactionManger,JTATransactionManager等<br />
<br />
　　(3) 在我们的代码中加入事务处理代码：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>TransactionDefinition td = new TransactionDefinition();<br />
            TransactionStatus ts = transactionManager.getTransaction(td);<br />
            try{<br />
            　//do sth<br />
            　transactionManager.commit(ts);<br />
            }catch(Exception e){transactionManager.rollback(ts);}</td>
        </tr>
    </tbody>
</table>
<br />
　　使用Spring提供的事务模板TransactionTemplate：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>void add()<br />
            {<br />
            　transactionTemplate.execute( new TransactionCallback(){<br />
            　　pulic Object doInTransaction(TransactionStatus ts)<br />
            　　{ //do sth}<br />
            　}<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　TransactionTemplate也是为我们省去了部分事务提交、回滚代码；定义事务模板时，需注入事务管理对象。<br />
<br />
　　3、Spring声明式事务处理<br />
<br />
　　Spring声明式事务处理也主要使用了IoC，AOP思想，提供了TransactionInterceptor拦截器和常用的代理类TransactionProxyFactoryBean，可以直接对组件进行事务代理。<br />
<br />
　　使用TransactionInterceptor的步骤：<br />
<br />
　　（1）定义数据源，事务管理类<br />
<br />
　　（2）定义事务拦截器,例如：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>＜bean id = "transactionInterceptor" <br />
            class="org.spring<a href="http://www.5iask.com/dotnet/framework/" target="_blank">Framework</a>.transaction.interceptor.TransactionInterceptor"＞<br />
            ＜property name="transactionManager"＞＜ref bean="transactionManager"/＞＜/property＞<br />
            ＜property name="transactionAttributeSource"＞<br />
            ＜value＞<br />
            com.test.UserManager.*r=PROPAGATION_REQUIRED<br />
            ＜/value＞<br />
            ＜/property＞<br />
            ＜/bean＞</td>
        </tr>
    </tbody>
</table>
<br />
　　（3）为组件声明一个代理类：ProxyFactoryBean<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>＜bean id="userManager" class="org.springframework.aop.framework.ProxyFactoryBean"＞<br />
            ＜property name="proxyInterfaces"＞＜value＞com.test.UserManager＜/value＞＜/property＞<br />
            ＜property name="interceptorNames"＞<br />
            ＜list＞<br />
            ＜idref local="transactionInterceptor"/＞<br />
            ＜/list＞<br />
            ＜/property＞<br />
            ＜/bean＞</td>
        </tr>
    </tbody>
</table>
<br />
　　使用TransactionProxyFactoryBean：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>＜bean id="userManager"<br />
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"＞<br />
            ＜property name="transactionManager"＞＜ref bean="transactionManager"/＞＜/property＞<br />
            ＜property name="target"＞＜ref local="userManagerTarget"/＞＜/property＞<br />
            ＜property name="transactionAttributes"＞<br />
            ＜props＞<br />
            ＜prop key="insert*"＞PROPAGATION_REQUIRED＜/prop＞<br />
            ＜prop key="update*"＞PROPAGATION_REQUIRED＜/prop＞<br />
            ＜prop key="*"＞PROPAGATION_REQUIRED,readOnly＜/prop＞<br />
            ＜/props＞<br />
            ＜/property＞<br />
            ＜/bean＞</td>
        </tr>
    </tbody>
</table>
<br />
　　TransactionProxyFactoryBean只是为组件的事务代理，如果我们要给组件添加一些业务方面的验证等，可以使用TransactionTemplate加拦截器方式，为组件添加多个拦截器，spring AOP中提供了三类Advice,即前增强，后增强，抛出异常时的增强，可以灵活使用。<br />
<br />
　　<strong>结束语</strong><br />
<br />
　　Spring可以简单的把普通的<a title="java" href="http://www.5iask.com/">java</a> class纳入事务管理，声明性的事务操作起来也很容易。有了Spring之后，声明性事务不再是<a href="http://www.5iask.com/java/ejb/" target="_blank">EJB</a>独有，我们不必为了获得声明性事务的功能而去忍受EJB带来的种种不便。Spring还提供了惟一的事务管理抽象，它能够在各种底层事务管理技术(如JTA或者JDBC)之上提供一个一致的编程模型。&nbsp;
 <img src ="http://www.blogjava.net/LeungXin/aggbug/146652.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-09-20 02:27 <a href="http://www.blogjava.net/LeungXin/articles/146652.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring事务管理</title><link>http://www.blogjava.net/LeungXin/articles/146651.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Wed, 19 Sep 2007 18:21:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/146651.html</guid><description><![CDATA[<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">对于传统的基于特定事务资源的事务处理而言（如基于JDBC 的数据库访问），Spring并不会对其产生什么影响，我们照样可以成功编写并运行这样的代码。同时，Spring还提供了一些辅助类可供我们选择使用，这些辅助类简化了传统的数据库操作流程，在一定程度上节省了工作量，提高了编码效率。对于依赖容器的参数化事务管理而言，Spring 则表现出了极大的价值。Spring本身也是一个容器，只是相对EJB容器而言，Spring显得更为轻便小巧。我们无需付出其他方面的代价，即可通过Spring实现基于容器的事务管理（本质上来讲，Spring的事务管理是基于动态AOP）。</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">下面这段xml配置片断展示了Spring中的事务设定方式：</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;beans&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">destroy-method="close"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;property name="driverClassName"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;value&gt;org.gjt.mm.mysql.Driver&lt;/value&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;/property&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;property name="url"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;value&gt;jdbc:mysql://localhost/sample&lt;/value&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;/property&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;property name="username"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;value&gt;user&lt;/value&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;/property&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;property name="password"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;value&gt;mypass&lt;/value&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;/property&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;/bean&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;bean id="transactionManager"</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;property name="dataSource"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;ref local="dataSource" /&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;/property&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;/bean&gt;</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;bean id="userDAO" class="net.xiaxin.dao.UserDAO"&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;property name="dataSource"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;ref local="dataSource" /&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;/property&gt;</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;/bean&gt;</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;bean id="userDAOProxy"</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; class="org.springframework.transaction.interceptor.TransactionProxyF&nbsp;actoryBean"&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;property name="transactionManager"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;ref bean="transactionManager" /&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;/property&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;ref local="userDAO" /&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;/property&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;property name="transactionAttributes"&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;props&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;prop key="insert*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;prop key="get*"&gt;&lt;/prop&gt;</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;/props&gt;</span></div>
<div style="text-indent: 21pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;/property&gt;</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &lt;/bean&gt;</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&lt;/beans&gt;</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">&nbsp;&nbsp;&nbsp; &nbsp;</span><span style="font-size: 12pt; line-height: 150%">配置中包含了dataSource，transactionManager 等资源定义。这些资源都为</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">一个名为userDAOProxy 的TransactionProxyFactoryBean 服务， userDAOProxy 则对包含实际数据逻辑的userDAO进行了事务性封装。可以看到，在userDAOProxy 的"transactionAttributes"属性中，我们定义了针对userDAO 的事务策略，即将所有名称以insert 开始的方法（如UserDAO.insertUser方法）纳入事务管理范围。如果此方法中抛出异常，则Spring将当前事务回滚，如果方法正常结束，则提交事务。而对所有名称以get 开始的方法（如UserDAO.getUser 方法）则以只读的事务</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">处理机制进行处理。（设为只读型事务，可以使持久层尝试对数据操作进行优化，如对于只读事务Hibernate将不执行flush操作，而某些数据库连接池和JDBC 驱动也对只读型操作进行了特别优化。）结合上面这段申明带来的感性认知，看看Spring 的事务管理机制与EJB 中事务管理有何不同，或者有何优势。这里自然有许多方面可以比较，不过，笔者认为其中最为关键的两点是：</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">1</span><span style="font-size: 12pt; line-height: 150%">． Spring可以将任意Java Class 纳入事务管理这里的UserDAO只是我们编写的一个普通Java Class，其中包含了一些基本的数据应用逻辑。通过Spring，我们即可简单的实现事务的可配置化。也就是说，我们可以随意为某个类的某个方法指定事务管理机制。与之对比，如果使用EJB容器提供的事务管理功能，我们不得不按照EJB规范编将UserDAO 进行改造，将其转换为一个标准的EJB。</span></div>
<div style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%">2</span><span style="font-size: 12pt; line-height: 150%">． Spring事务管理并不依赖特定的事务资源。EJB 容器必须依赖于JTA 提供事务支持。而Spring 的事务管理则支持JDBC、JTA 等多种事务资源。这为我们提供了更多的选择，从而也使得我们的系统部署更加灵活。对Spring事务管理机制进行简单分析之后，我们将结合持久层封装的具体事务应用机制，对Spring中的事务管理进行更具实效的探讨。</span></div>
<img src ="http://www.blogjava.net/LeungXin/aggbug/146651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-09-20 02:21 <a href="http://www.blogjava.net/LeungXin/articles/146651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 Spring 更好地处理 Struts 动作</title><link>http://www.blogjava.net/LeungXin/articles/146649.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Wed, 19 Sep 2007 18:13:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/146649.html</guid><description><![CDATA[<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="100%">
            <p id="subtitle"><em>三种整合 Struts 应用程序与 Spring 的方式</em></p>
            <img class="display-img" height="6" alt="" src="http://www.ibm.com/i/c.gif" width="1" /></td>
            <td class="no-print" width="192"><img height="18" alt="developerWorks" src="http://www-128.ibm.com/developerworks/i/dw.gif" width="192" /></td>
        </tr>
    </tbody>
</table>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td width="100%">
            <table class="no-print" cellspacing="0" cellpadding="0" width="160" align="right" border="0">
                <tbody>
                    <tr>
                        <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
                        <td>
                        <table cellspacing="0" cellpadding="0" width="150" border="0">
                            <tbody>
                                <tr>
                                    <td class="v14-header-1-small">文档选项</td>
                                </tr>
                            </tbody>
                        </table>
                        <table class="v14-gray-table-border" cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td class="no-padding" width="150">
                                    <table cellspacing="0" cellpadding="0" width="143" border="0">
                                        <img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" />
                                        <form name="email" action="https://www.ibm.com/developerworks/secure/email-it.jsp">
                                            <input type="hidden" value="Struts Recipes 的合著者 George Franciscus 将介绍另一个重大的 Struts 整合窍门 —— 这次是将 Struts 应用程序导入 Spring 框架。请跟随 George，他将向您展示如何改变 Struts 动作，使得管理 Struts 动作就像管理 Spring beans 那样。结果是一个增强的 web 框架， 这个框架可以方便地利用 Spring AOP 的优势。" name="body" /><input type="hidden" value="使用 Spring 更好地处理 Struts 动作" name="subject" /><input type="hidden" value="cn" name="lang" /> <script language="JavaScript" type="text/javascript">
<!-- document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt="" /></td><td width="16"><img src="//www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="将此页作为电子邮件发送"  /></td><td width="122"><p><a class="smallplainlink" href="javascript:document.email.submit();"><strong>将此页作为电子邮件发送</strong></a></p></td></tr>');
//-->
</script>
                                            <tbody>
                                                <tr valign="top">
                                                    <td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td>
                                                    <td width="16"><img height="16" alt="将此页作为电子邮件发送" src="http://www.ibm.com/i/v14/icons/em.gif" width="16" vspace="3" /></td>
                                                    <td width="122">
                                                    <p><a class="smallplainlink" href="javascript:document.email.submit();"><strong>将此页作为电子邮件发送</strong></a></p>
                                                    </td>
                                                </tr>
                                                <noscript>
                                                <tr valign="top">
                                                    <td width="8"><img alt="" height="1" width="8" src="//www.ibm.com/i/c.gif"    /></td>
                                                    <td width="16"><img alt="" width="16" height="16" src="//www.ibm.com/i/c.gif"    /></td>
                                                    <td class="small" width="122">
                                                    <p><span class="ast">未显示需要 JavaScript 的文档选项</span></p>
                                                    </td>
                                                </tr>
                                                </noscript>
                                            </form>
                                            <tr valign="top">
                                                <td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td>
                                                <td width="16"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/fw_bold.gif" width="16" vspace="3" border="0" /></td>
                                                <td width="122">
                                                <p><a class="smallplainlink" href="http://www.ibm.com/developerworks/community/"><strong>讨论</strong></a></p>
                                                </td>
                                            </tr>
                                            <tr valign="top">
                                                <td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td>
                                                <td width="16"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/dn.gif" width="16" vspace="3" border="0" /></td>
                                                <td width="122">
                                                <p><a class="smallplainlink" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#download"><strong>样例代码</strong></a></p>
                                                </td>
                                            </tr>
                                        </tbody>
                                    </table>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas --><br />
                        <!--end RESERVED FOR FUTURE USE INCLUDE FILES--><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>级别： 中级</p>
            <p><a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#author">George Franciscus</a> (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#103;&#101;&#111;&#114;&#103;&#101;&#46;&#102;&#114;&#97;&#110;&#99;&#105;&#115;&#99;&#117;&#115;&#64;&#110;&#101;&#120;&#99;&#101;&#108;&#46;&#99;&#97;&#63;&#115;&#117;&#98;&#106;&#101;&#99;&#116;&#61;&#20351;&#29992;&#32;&#83;&#112;&#114;&#105;&#110;&#103;&#32;&#26356;&#22909;&#22320;&#22788;&#29702;&#32;&#83;&#116;&#114;&#117;&#116;&#115;&#32;&#21160;&#20316;">george.franciscus@nexcel.ca</a>), 负责人, Nexcel<br />
            </p>
            <p>2005 年 10 月 11 日</p>
            <blockquote><em>Struts Recipes</em> 的合著者 George Franciscus 将介绍另一个重大的 Struts 整合窍门 —— 这次是将 Struts 应用程序导入 Spring 框架。请跟随 George，他将向您展示如何改变 Struts 动作，使得管理 Struts 动作就像管理 Spring beans 那样。结果是一个增强的 web 框架，这个框架可以方便地利用 Spring AOP 的优势。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
            <p>您肯定已经听说过控制反转 (IOC) 设计模式，因为很长一段时间以来一直在流传关于它的信息。如果您在任何功能中使用过 Spring 框架，那么您就知道其原理的作用。在本文中，我利用这一原理把一个 Struts 应用程序注入 Spring 框架，您将亲身体会到 IOC 模式的强大。</p>
            <p>将一个 Struts 应用程序整合进 Spring 框架具有多方面的优点。首先，Spring 是为解决一些关于 JEE 的真实世界问题而设计的，比如复杂性、低性能和可测试性，等等。第二，Spring 框架包含一个 AOP 实现，允许您将面向方面技术应用于面向对象的代码。第三，一些人可能会说 Spring 框架只有<em>处理</em> Struts 比 Struts 处理自己好。但是这是观点问题，我演示三种将 Struts 应用程序整合到 Spring 框架的方法后，具体由您自己决定使用哪一种。</p>
            <p>我所演示的方法都是执行起来相对简单的，但是它们却具有明显不同的优点。我为每一种方法创建了一个独立而可用的例子，这样您就可以完全理解每种方法。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#resources">下载</a> 部分获得完整例子源代码。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#resources">参考资料</a>，下载 Struts MVC 和 Spring 框架。</p>
            <p><a name="N10099"><span class="atitle">为什么 Spring 这么了不起？</span></a></p>
            <p>Spring 的创立者 Rod Johnson 以一种批判的眼光看待 Java&#8482; 企业软件开发，并且提议很多企业难题都能够通过战略地使用 IOC 模式（也称作依赖注入）来解决。当 Rod 和一个具有奉献精神的开放源码开发者团队将这个理论应用于实践时，结果就产生了 Spring 框架。简言之，Spring 是一个轻型的容器，利用它可以使用一个外部 XML 配置文件方便地将对象连接在一起。每个对象都可以通过显示一个 JavaBean 属性收到一个到依赖对象的引用，留给您的简单任务就只是在一个 XML 配置文件中把它们连接好。</p>
            <table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
                <tbody>
                    <tr>
                        <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
                        <td>
                        <table cellspacing="0" cellpadding="5" width="100%" border="1">
                            <tbody>
                                <tr>
                                    <td bgcolor="#eeeeee"><a name="N100A6"><strong>IOC 和 Spring</strong></a><br />
                                    <p>IOC 是一种使应用程序逻辑外在化的设计模式，所以它是被注入而不是被写入客户机代码中。将 IOC 与接口编程应用结合，就像 Spring 框架那样，产生了一种架构，这种架构能够减少客户机对特定实现逻辑的依赖。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#resources">参考资料</a> 了解更多关于 IOC 和 Spring 的信息。</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>依赖注入是一个强大的特性，但是 Spring 框架能够提供更多特性。Spring 支持可插拔的事务管理器，可以给您的事务处理提供更广泛的选择范围。它集成了领先的持久性框架，并且提供一个一致的异常层次结构。Spring 还提供了一种使用面向方面代码代替正常的面向对象代码的简单机制。</p>
            <p>Spring AOP 允许您使用<em>拦截器</em> 在一个或多个执行点上拦截应用程序逻辑。加强应用程序在拦截器中的日志记录逻辑会产生一个更可读的、实用的代码基础，所以拦截器广泛用于日志记录。您很快就会看到，为了处理横切关注点，Spring AOP 发布了它自己的拦截器，您也可以编写您自己的拦截器。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N100BD"><span class="atitle">整合 Struts 和 Spring</span></a></p>
            <p>与 Struts 相似，Spring 可以作为一个 MVC 实现。这两种框架都具有自己的优点和缺点，尽管大部分人同意 Struts 在 MVC 方面仍然是最好的。很多开发团队已经学会在时间紧迫的时候利用 Struts 作为构造高品质软件的基础。Struts 具有如此大的推动力，以至于开发团队宁愿整合 Spring 框架的特性，而不愿意转换成 Spring MVC。没必要进行转换对您来说是一个好消息。Spring 架构允许您将 Struts 作为 Web 框架连接到基于 Spring 的业务和持久层。最后的结果就是现在一切条件都具备了。</p>
            <p>在接下来的小窍门中，您将会了解到三种将 Struts MVC 整合到 Spring 框架的方法。我将揭示每种方法的缺陷并且对比它们的优点。 一旦您了解到所有三种方法的作用，我将会向您展示一个令人兴奋的应用程序，这个程序使用的是这三种方法中我最喜欢的一种。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N100C9"><span class="atitle">三个小窍门</span></a></p>
            <p>接下来的每种整合技术（或者窍门）都有自己的优点和特点。我偏爱其中的一种，但是我知道这三种都能够加深您对 Struts 和 Spring 的理解。在处理各种不同情况的时候，这将给您提供一个广阔的选择范围。方法如下：</p>
            <ul>
                <li>使用 Spring 的 <code>ActionSupport</code> 类整合 Structs
                <li>使用 Spring 的 <code>DelegatingRequestProcessor</code> 覆盖 Struts 的 <code>RequestProcessor </code>
                <li>将 Struts <code>Action</code> 管理委托给 Spring 框架 </li>
            </ul>
            <p><a name="N100EE"><span class="smalltitle">装载应用程序环境</span></a></p>
            <p>无论您使用哪种技术，都需要使用 Spring 的 <code>ContextLoaderPlugin</code> 为 Struts 的 <code>ActionServlet</code> 装载 Spring 应用程序环境。就像添加任何其他插件一样，简单地向您的 struts-config.xml 文件添加该插件，如下所示：</p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;plug-in className=
                        "org.springframework.web.struts.ContextLoaderPlugIn"&gt;
                        &lt;set-property property=
                        "contextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
                        &lt;/plug-in&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>前面已经提到过，在 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#download">下载</a> 部分，您能够找到这三个完全可使用的例子的完整源代码。每个例子都为一个书籍搜索应用程序提供一种不同的 Struts 和 Spring 的整合方法。您可以在这里看到例子的要点，但是您也可以下载应用程序以查看所有的细节。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N1010B"><span class="atitle">窍门 1. 使用 Spring 的 ActionSupport</span></a></p>
            <p>手动创建一个 Spring 环境是一种整合 Struts 和 Spring 的最直观的方式。为了使它变得更简单，Spring 提供了一些帮助。为了方便地获得 Spring 环境，<code>org.springframework.web.struts.ActionSupport</code> 类提供了一个 <code>getWebApplicationContext()</code> 方法。您所做的只是从 Spring 的 <code>ActionSupport</code> 而不是 Struts <code>Action</code> 类扩展您的动作，如清单 1 所示：</p>
            <br />
            <a name="N10129"><strong>清单 1. 使用 ActionSupport 整合 Struts</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">package ca.nexcel.books.actions;
                        import java.io.IOException;
                        import javax.servlet.ServletException;
                        import javax.servlet.http.HttpServletRequest;
                        import javax.servlet.http.HttpServletResponse;
                        import org.apache.struts.action.ActionError;
                        import org.apache.struts.action.ActionErrors;
                        import org.apache.struts.action.ActionForm;
                        import org.apache.struts.action.ActionForward;
                        import org.apache.struts.action.ActionMapping;
                        import org.apache.struts.action.DynaActionForm;
                        import org.springframework.context.ApplicationContext;
                        import org.springframework.web.struts.ActionSupport;
                        import ca.nexcel.books.beans.Book;
                        import ca.nexcel.books.business.BookService;
                        public class SearchSubmit extends ActionSupport {   <span class="boldcode">|(1)</span>
                        public ActionForward execute(
                        ActionMapping mapping,
                        ActionForm form,
                        HttpServletRequest request,
                        HttpServletResponse response)
                        throws IOException, ServletException {
                        DynaActionForm searchForm = (DynaActionForm) form;
                        String isbn = (String) searchForm.get("isbn");
                        //the old fashion way
                        //BookService bookService = new BookServiceImpl();
                        ApplicationContext ctx =
                        getWebApplicationContext();    <span class="boldcode">|(2)</span>
                        BookService bookService =
                        (BookService) ctx.getBean("bookService");   <span class="boldcode">|(3)</span>
                        Book book = bookService.read(isbn.trim());
                        if (null == book) {
                        ActionErrors errors = new ActionErrors();
                        errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
                        ("message.notfound"));
                        saveErrors(request, errors);
                        return mapping.findForward("failure") ;
                        }
                        request.setAttribute("book", book);
                        return mapping.findForward("success");
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>让我们快速思考一下这里到底发生了什么。在 (1) 处，我通过从 Spring 的 <code>ActionSupport</code> 类而不是 Struts 的 <code>Action</code> 类进行扩展，创建了一个新的 <code>Action</code>。在 (2) 处，我使用 <code>getWebApplicationContext()</code> 方法获得一个 <code>ApplicationContext</code>。为了获得业务服务，我使用在 (2) 处获得的环境在 (3) 处查找一个 Spring bean。</p>
            <p>这种技术很简单并且易于理解。不幸的是，它将 Struts 动作与 Spring 框架耦合在一起。如果您想替换掉 Spring，那么您必须重写代码。并且，由于 Struts 动作不在 Spring 的控制之下，所以它不能获得 Spring AOP 的优势。当使用多重独立的 Spring 环境时，这种技术可能有用，但是在大多数情况下，这种方法不如另外两种方法合适。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N10153"><span class="atitle">窍门 2. 覆盖 RequestProcessor</span></a></p>
            <p>将 Spring 从 Struts 动作中分离是一个更巧妙的设计选择。分离的一种方法是使用 <code>org.springframework.web.struts.DelegatingRequestProcessor</code> 类来覆盖 Struts 的 <code>RequestProcessor</code> 处理程序，如清单 2 所示：</p>
            <br />
            <a name="N10169"><strong>清单 2. 通过 Spring 的 DelegatingRequestProcessor 进行整合</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
                        &lt;!DOCTYPE struts-config PUBLIC
                        "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
                        "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt;
                        &lt;struts-config&gt;
                        &lt;form-beans&gt;
                        &lt;form-bean name="searchForm"
                        type="org.apache.struts.validator.DynaValidatorForm"&gt;
                        &lt;form-property name="isbn"    type="java.lang.String"/&gt;
                        &lt;/form-bean&gt;
                        &lt;/form-beans&gt;
                        &lt;global-forwards type="org.apache.struts.action.ActionForward"&gt;
                        &lt;forward   name="welcome"                path="/welcome.do"/&gt;
                        &lt;forward   name="searchEntry"            path="/searchEntry.do"/&gt;
                        &lt;forward   name="searchSubmit"           path="/searchSubmit.do"/&gt;
                        &lt;/global-forwards&gt;
                        &lt;action-mappings&gt;
                        &lt;action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/&gt;
                        &lt;action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/&gt;
                        &lt;action    path="/searchSubmit"
                        type="ca.nexcel.books.actions.SearchSubmit"
                        input="/searchEntry.do"
                        validate="true"
                        name="searchForm"&gt;
                        &lt;forward name="success" path="/WEB-INF/pages/detail.jsp"/&gt;
                        &lt;forward name="failure" path="/WEB-INF/pages/search.jsp"/&gt;
                        &lt;/action&gt;
                        &lt;/action-mappings&gt;
                        &lt;message-resources parameter="ApplicationResources"/&gt;
                        &lt;controller processorClass="org.springframework.web.struts.
                        DelegatingRequestProcessor"/&gt; <span class="boldcode">|(1)</span>
                        &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
                        &lt;set-property property="pathnames"
                        value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
                        &lt;/plug-in&gt;
                        &lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
                        &lt;set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
                        &lt;/plug-in&gt;
                        &lt;/struts-config&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>我利用了 <code>&lt;controller&gt;</code> 标记来用 <code>DelegatingRequestProcessor</code> 覆盖默认的 Struts <code>RequestProcessor</code>。下一步是在我的 Spring 配置文件中注册该动作，如清单 3 所示：</p>
            <br />
            <a name="N10186"><strong>清单 3. 在 Spring 配置文件中注册一个动作</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
                        "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
                        &lt;beans&gt;
                        &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;
                        &lt;bean name="/searchSubmit"
                        class="ca.nexcel.books.actions.SearchSubmit"&gt; <span class="boldcode">|(1)</span>
                        &lt;property name="bookService"&gt;
                        &lt;ref bean="bookService"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;/beans&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>注意：在 (1) 处，我使用名称属性注册了一个 bean，以匹配 struts-config 动作映射名称。<code>SearchSubmit</code> 动作揭示了一个 JavaBean 属性，允许 Spring 在运行时填充属性，如清单 4 所示：</p>
            <br />
            <a name="N1019B"><strong>清单 4. 具有 JavaBean 属性的 Struts 动作</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">package ca.nexcel.books.actions;
                        import java.io.IOException;
                        import javax.servlet.ServletException;
                        import javax.servlet.http.HttpServletRequest;
                        import javax.servlet.http.HttpServletResponse;
                        import org.apache.struts.action.Action;
                        import org.apache.struts.action.ActionError;
                        import org.apache.struts.action.ActionErrors;
                        import org.apache.struts.action.ActionForm;
                        import org.apache.struts.action.ActionForward;
                        import org.apache.struts.action.ActionMapping;
                        import org.apache.struts.action.DynaActionForm;
                        import ca.nexcel.books.beans.Book;
                        import ca.nexcel.books.business.BookService;
                        public class SearchSubmit extends Action {
                        private BookService bookService;
                        public BookService getBookService() {
                        return bookService;
                        }
                        public void setBookService(BookService bookService) { <span class="boldcode">| (1)</span>
                        this.bookService = bookService;
                        }
                        public ActionForward execute(
                        ActionMapping mapping,
                        ActionForm form,
                        HttpServletRequest request,
                        HttpServletResponse response)
                        throws IOException, ServletException {
                        DynaActionForm searchForm = (DynaActionForm) form;
                        String isbn = (String) searchForm.get("isbn");
                        Book book = getBookService().read(isbn.trim());  <span class="boldcode">|(2)</span>
                        if (null == book) {
                        ActionErrors errors = new ActionErrors();
                        errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
                        saveErrors(request, errors);
                        return mapping.findForward("failure") ;
                        }
                        request.setAttribute("book", book);
                        return mapping.findForward("success");
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>在清单 4 中，您可以了解到如何创建 Struts 动作。在 (1) 处，我创建了一个 JavaBean 属性。<code>DelegatingRequestProcessor</code>自动地配置这种属性。这种设计使 Struts 动作并不知道它正被 Spring 管理，并且使您能够利用 Sping 的动作管理框架的所有优点。由于您的 Struts 动作注意不到 Spring 的存在，所以您不需要重写您的 Struts 代码就可以使用其他控制反转容器来替换掉 Spring。</p>
            <p><code>DelegatingRequestProcessor</code> 方法的确比第一种方法好，但是仍然存在一些问题。如果您使用一个不同的 <code>RequestProcessor</code>，则需要手动整合 Spring 的 <code>DelegatingRequestProcessor</code>。添加的代码会造成维护的麻烦并且将来会降低您的应用程序的灵活性。此外，还有过一些使用一系列命令来代替 Struts <code>RequestProcessor</code> 的传闻。 这种改变将会对这种解决方法的使用寿命造成负面的影响。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N101C1"><span class="atitle">窍门 3. 将动作管理委托给 Spring</span></a></p>
            <p>一个更好的解决方法是将 Strut 动作管理委托给 Spring。您可以通过在 <code>struts-config</code> 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查找 Struts 动作。由于动作在 Spring 的控制之下，所以它可以填充动作的 JavaBean 属性，并为应用诸如 Spring 的 AOP 拦截器之类的特性带来了可能。 </p>
            <p>清单 5 中的 <code>Action</code> 类与清单 4 中的相同。但是 struts-config 有一些不同：</p>
            <br />
            <a name="N101DA"><strong>清单 5. Spring 整合的委托方法</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
                        &lt;!DOCTYPE struts-config PUBLIC
                        "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
                        "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt;
                        &lt;struts-config&gt;
                        &lt;form-beans&gt;
                        &lt;form-bean name="searchForm"
                        type="org.apache.struts.validator.DynaValidatorForm"&gt;
                        &lt;form-property name="isbn"    type="java.lang.String"/&gt;
                        &lt;/form-bean&gt;
                        &lt;/form-beans&gt;
                        &lt;global-forwards type="org.apache.struts.action.ActionForward"&gt;
                        &lt;forward   name="welcome"                path="/welcome.do"/&gt;
                        &lt;forward   name="searchEntry"            path="/searchEntry.do"/&gt;
                        &lt;forward   name="searchSubmit"           path="/searchSubmit.do"/&gt;
                        &lt;/global-forwards&gt;
                        &lt;action-mappings&gt;
                        &lt;action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/&gt;
                        &lt;action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/&gt;
                        &lt;action    path="/searchSubmit"
                        type="org.springframework.web.struts.DelegatingActionProxy" <span class="boldcode">|(1)</span>
                        input="/searchEntry.do"
                        validate="true"
                        name="searchForm"&gt;
                        &lt;forward name="success" path="/WEB-INF/pages/detail.jsp"/&gt;
                        &lt;forward name="failure" path="/WEB-INF/pages/search.jsp"/&gt;
                        &lt;/action&gt;
                        &lt;/action-mappings&gt;
                        &lt;message-resources parameter="ApplicationResources"/&gt;
                        &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
                        &lt;set-property
                        property="pathnames"
                        value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
                        &lt;/plug-in&gt;
                        &lt;plug-in
                        className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
                        &lt;set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
                        &lt;/plug-in&gt;
                        &lt;/struts-config&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>清单 5 是一个典型的 struts-config.xml 文件，只有一个小小的差别。它注册 Spring 代理类的名称，而不是声明动作的类名，如（1）处所示。DelegatingActionProxy 类使用动作映射名称查找 Spring 环境中的动作。这就是我们使用 <code>ContextLoaderPlugIn</code> 声明的环境。</p>
            <p>将一个 Struts 动作注册为一个 Spring bean 是非常直观的，如清单 6 所示。我利用动作映射使用 <code>&lt;bean&gt;</code> 标记的名称属性（在这个例子中是 "<code>/searchSubmit</code>"）简单地创建了一个 bean。这个动作的 JavaBean 属性像任何 Spring bean 一样被填充： </p>
            <br />
            <a name="N101FA"><strong>清单 6. 在 Spring 环境中注册一个 Struts 动作</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
                        "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
                        &lt;beans&gt;
                        &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;
                        &lt;bean name="/searchSubmit"
                        class="ca.nexcel.books.actions.SearchSubmit"&gt;
                        &lt;property name="bookService"&gt;
                        &lt;ref bean="bookService"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;/beans&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N10201"><span class="atitle">动作委托的优点</span></a></p>
            <p>动作委托解决方法是这三种方法中最好的。Struts 动作不了解 Spring，不对代码作任何改变就可用于非 Spring 应用程序中。<code>RequestProcessor</code> 的改变不会影响它，并且它可以利用 Spring AOP 特性的优点。 </p>
            <p>动作委托的优点不止如此。一旦让 Spring 控制您的 Struts 动作，您就可以使用 Spring 给动作补充更强的活力。例如，没有 Spring 的话，所有的 Struts 动作都必须是线程安全的。如果您设置 <code>&lt;bean&gt;</code> 标记的 singleton 属性为&#8220;false&#8221;，那么不管用何种方法，您的应用程序都将在每一个请求上有一个新生成的动作对象。您可能不需要这种特性，但是把它放在您的工具箱中也很好。您也可以利用 Spring 的生命周期方法。例如，当实例化 Struts 动作时，<code>&lt;bean&gt;</code> 标记的 init-method 属性被用于运行一个方法。类似地，在从容器中删除 bean 之前，destroy-method 属性执行一个方法。这些方法是管理昂贵对象的好办法，它们以一种与 Servlet 生命周期相同的方式进行管理。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N1021A"><span class="atitle">拦截 Struts</span></a></p>
            <p>前面提到过，通过将 Struts 动作委托给 Spring 框架而整合 Struts 和 Spring 的一个主要的优点是：您可以将 Spring 的 AOP 拦截器应用于您的 Struts 动作。通过将 Spring 拦截器应用于 Struts 动作，您可以用最小的代价处理横切关注点。</p>
            <p>虽然 Spring 提供很多内置拦截器，但是我将向您展示如何创建自己的拦截器并把它应用于一个 Struts 动作。为了使用拦截器，您需要做三件事：</p>
            <ol>
                <li>创建拦截器。
                <li>注册拦截器。
                <li>声明在何处拦截代码。 </li>
            </ol>
            <p>这看起来非常简单的几句话却非常强大。例如，在清单 7 中，我为 Struts 动作创建了一个日志记录拦截器。 这个拦截器在每个方法调用之前打印一句话：</p>
            <br />
            <a name="N1023A"><strong>清单 7. 一个简单的日志记录拦截器</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">package ca.nexcel.books.interceptors;
                        import org.springframework.aop.MethodBeforeAdvice;
                        import java.lang.reflect.Method;
                        public class LoggingInterceptor implements MethodBeforeAdvice {
                        public void before(Method method, Object[] objects, Object o) throws Throwable {
                        System.out.println("logging before!");
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>这个拦截器非常简单。<code>before()</code> 方法在拦截点中每个方法之前运行。在本例中，它打印出一句话，其实它可以做您想做的任何事。下一步就是在 Spring 配置文件中注册这个拦截器，如清单 8 所示：</p>
            <br />
            <a name="N1024C"><strong>清单 8. 在 Spring 配置文件中注册拦截器</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
                        "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
                        &lt;beans&gt;
                        &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;
                        &lt;bean name="/searchSubmit"
                        class="ca.nexcel.books.actions.SearchSubmit"&gt;
                        &lt;property name="bookService"&gt;
                        &lt;ref bean="bookService"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;!--  Interceptors --&gt;
                        &lt;bean name="logger"
                        class="ca.nexcel.books.interceptors.LoggingInterceptor"/&gt; <span class="boldcode">|(1)</span>
                        &lt;!-- AutoProxies --&gt;
                        &lt;bean name="loggingAutoProxy"
                        class="org.springframework.aop.framework.autoproxy.
                        BeanNameAutoProxyCreator"&gt; <span class="boldcode">|(2)</span>
                        &lt;property name="beanNames"&gt;
                        &lt;value&gt;/searchSubmit&lt;/valuesgt; <span class="boldcode">|(3)</span>
                        &lt;/property&gt;
                        &lt;property name="interceptorNames"&gt;
                        &lt;list&gt;
                        &lt;value&gt;logger&lt;/value&gt; <span class="boldcode">|(4)</span>
                        &lt;/list&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;/beans&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>您可能已经注意到了，清单 8 扩展了 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#code6">清单 6</a> 中所示的应用程序以包含一个拦截器。具体细节如下：</p>
            <ul>
                <li>在 (1) 处，我注册了这个拦截器。
                <li>在 (2) 处，我创建了一个 bean 名称自动代理，它描述如何应用拦截器。还有其他的方法定义拦截点，但是这种方法常见而简便。
                <li>在 (3) 处，我将 Struts 动作注册为将被拦截的 bean。如果您想要拦截其他的 Struts 动作，则只需要在 "beanNames" 下面创建附加的 <code>&lt;value&gt;</code> 标记。
                <li>在 (4) 处，当拦截发生时，我执行了在 (1) 处创建的拦截器 bean 的名称。这里列出的所有拦截器都应用于&#8220;beanNames&#8221;。 </li>
            </ul>
            <p>就是这样。就像这个例子所展示的，将您的 Struts 动作置于 Spring 框架的控制之下，为处理您的 Struts 应用程序提供了一系列全新的选择。在本例中，使用动作委托可以轻松地利用 Spring 拦截器提高 Struts 应用程序中的日志记录能力。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N1027C"><span class="atitle">结束语</span></a></p>
            <p>在本文中，您已经学习了将 Struts 动作整合到 Spring 框架中的三种窍门。使用 Spring 的 <code>ActionSupport</code> 来整合 Struts（第一种窍门中就是这样做的）简单而快捷，但是会将 Struts 动作与 Spring 框架耦合在一起。如果您需要将应用程序移植到一个不同的框架，则需要重写代码。第二种解决方法通过委托 <code>RequestProcessor</code> 巧妙地解开代码的耦合，但是它的可扩展性不强，并且当 Struts 的 <code>RequestProcessor</code> 变成一系列命令时，这种方法就持续不了很长时间。第三种方法是这三种方法中最好的：将 Struts 动作委托给 Spring 框架可以使代码解耦，从而使您可以在您的 Struts 应用程序中利用 Spring 的特性（比如日志记录拦截器）。</p>
            <p>三种 Struts-Spring 整合窍门中的每一种都被实现成一个完整可用的应用程序。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#download">下载</a> 部分仔细研究它们。</p>
            </td>
        </tr>
    </tbody>
</table>
<p><span class="atitle"><a name="download">下载</a></span></p>
<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <th scope="col">描述</th>
            <th scope="col">名字</th>
            <th scope="col" align="right">大小</th>
            <th scope="col">下载方法</th>
        </tr>
        <tr>
            <th class="tb-row" scope="row">ActionSupport sample code</th>
            <td noWrap>j-sr2-actionsupport.zip</td>
            <td noWrap align="right">5 MB</td>
            <td noWrap><a class="fbox" href="http://download.boulder.ibm.com/ibmdl/pub/software/dw/library/j-sr2-actionsupport.zip"><strong>HTTP</strong></a></td>
        </tr>
        <tr>
            <th class="tb-row" scope="row">RequestProcessor sample code</th>
            <td noWrap>j-sr2-requestprocessor.zip</td>
            <td noWrap align="right">5 MB</td>
            <td noWrap><a class="fbox" href="http://download.boulder.ibm.com/ibmdl/pub/software/dw/library/j-sr2-requestprocessor.zip"><strong>HTTP</strong></a></td>
        </tr>
        <tr>
            <th class="tb-row" scope="row">Delegate sample code</th>
            <td noWrap>j-sr2-delegate.zip</td>
            <td noWrap align="right">5 MB</td>
            <td noWrap><a class="fbox" href="http://download.boulder.ibm.com/ibmdl/pub/software/dw/library/j-sr2-delegate.zip"><strong>HTTP</strong></a></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/LeungXin/aggbug/146649.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-09-20 02:13 <a href="http://www.blogjava.net/LeungXin/articles/146649.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>