﻿<?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-kook-文章分类-J2EE</title><link>http://www.blogjava.net/kook/category/21959.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 10 Jul 2007 18:22:47 GMT</lastBuildDate><pubDate>Tue, 10 Jul 2007 18:22:47 GMT</pubDate><ttl>60</ttl><item><title>使用Struts Menu构造动态树 9</title><link>http://www.blogjava.net/kook/articles/114169.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Fri, 27 Apr 2007 09:43:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/114169.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/114169.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/114169.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/114169.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/114169.html</trackback:ping><description><![CDATA[AppFuse的作者Raible为我们提供了Struts Menu这样一个菜单组件，并且在AppFuse中使用它来进行了树形菜单的显示。不过AppFuse中做的是一个静态菜单，下面我们利用这个组件来显示一个使用数据库管理的动态树形菜单。<br>&nbsp;&nbsp;&nbsp; 原教程在<a href="http://www.thogau.net/tutorials/tree.html"><u><font color=#0000ff>http://www.thogau.net/tutorials/tree.html</font></u></a>，偶滴工作只是写一个&#8220;快速上手指南&#8221;。8过里面似乎还有点错误，反正偶照原样做下来的用不了，修正一下。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">1. 创建POJO Node.java<br>&nbsp;&nbsp;&nbsp; 最基本也是最重要的工作首先是建立这个菜单的POJO，源文件在<a href="http://www.thogau.net/tutorials/tree/files/Node.java"><strong><u><font color=#0000ff>这里</font></u></strong></a>下载吧，偶8多说了。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">2. 使用AppGen生成代码<br>&nbsp;&nbsp;&nbsp; 这一步偶也8想多说了，只要使用过AppFuse的都应该知道啦，8知道的看偶前面的<a href="http://blog.csdn.net/clearwater21cn/archive/2005/03/19/324075.aspx"><u><font color=#0000ff>文章</font></u></a>。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">3. 单元测试<br>&nbsp;&nbsp;&nbsp; 接下来当然就是要修改生成的代码了，首先是单元测试类NodeDAOTest.java。我们要给它加几个测试方法<br>&nbsp;&nbsp;&nbsp; - testChildren：测试添加和删除子节点<br>&nbsp;&nbsp;&nbsp; - testParent：测试两级的父子关系<br>&nbsp;&nbsp;&nbsp; - testDeleteMiddleNode：测试中间节点的删除<br>&nbsp;&nbsp;&nbsp; 具体怎么做的看<a href="http://www.thogau.net/tutorials/tree/files/NodeDAOTest.java"><strong><u><font color=#0000ff>这里</font></u></strong></a>吧，但是要注意最好不要直接下载替换原文件，如果AppFuse的版本不一样，测试方法也是不一样滴，最好把这几个方法单独copy过来。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">4. Form Bean<br>&nbsp;&nbsp;&nbsp; AppGen生产的NodeForm不能满足我们的要求了，所以把这个文件<a href="http://www.thogau.net/tutorials/tree/files/xdoclet-NodeForm.java"><u><font color=#0000ff>xdoclet-NodeForm.java</font></u></a>放到metadata\web下。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">5. Action<br>&nbsp;&nbsp;&nbsp; Action是这里最重要的类了，它修改的地方也很多，所以就直接<a href="http://www.thogau.net/tutorials/tree/files/NodeAction.java"><strong><u><font color=#0000ff>下载</font></u></strong></a>吧。不过偶有一点不太明白的是作者为虾米要把populate()方法的第二个参数设为long而不是Long，他传入的可是Long啊，自己手动改改吧。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">6. JSP<br>&nbsp;&nbsp;&nbsp; 接下来是JSP，自动生成的代码基本没用了。这里nodeList.jsp可以删除，<a href="http://www.thogau.net/tutorials/tree/files/nodeForm._jsp"><u><font color=#0000ff>nodeForm.jsp</font></u></a>被重新写过了。如果你的AppFuse版本比较新，是1.8版以上的，这个JSP下载下来后还需要改一下。搜索property="method"，这个是button里的属性，根据button的功能把他们分别修改成property="method.save"、property="method.delete"、property="method.add"等，否则按下按钮可是要报错的.<br>&nbsp;&nbsp;&nbsp; 修改了JSP也别忘了它的资源文件。把<a href="http://www.thogau.net/tutorials/tree/files/ApplicationResources.properties"><strong><u><font color=#0000ff>这个</font></u></strong></a>文件里关于nodeForm部分的内容copy到你自己的ApplicationResources下吧，当然可以汉化一下。<br>&nbsp;&nbsp;&nbsp; 接下来修改<a href="http://www.thogau.net/tutorials/tree/files/menuExpandable.css"><u><font color=#0000ff>menuExpandable.css</font></u></a>和<a href="http://www.thogau.net/tutorials/tree/files/menuExpandable.js"><u><font color=#0000ff>menuExpandable.js</font></u></a>，直接替换原文件就可以了。<br>&nbsp;&nbsp;&nbsp; 现在可能还是不能正常使用，因为我们的AppFuse下已经有一个菜单了，新的菜单会和原来的菜单起冲突，导致我们的新菜单打不开。到web\decorators下打开default.jsp文件，把含有&lt;c:import url="/WEB-INF/pages/menu.jsp"/&gt;的这一段代码挪到&lt;div id="content"&gt;&lt;/div&gt;代码段的下面，这样就可以正常使用了。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">7. 问题<br>&nbsp;&nbsp;&nbsp; 在使用中我还发现一个问题，就是这个菜单的target有点问题，只有末节点的target有效，其它节点的target设了也灭有效果，8知道哪位大虾有好的解决办法，偶8胜感激。</p>
<img src ="http://www.blogjava.net/kook/aggbug/114169.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-27 17:43 <a href="http://www.blogjava.net/kook/articles/114169.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>修改AppFuse 8</title><link>http://www.blogjava.net/kook/articles/114168.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Fri, 27 Apr 2007 09:42:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/114168.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/114168.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/114168.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/114168.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/114168.html</trackback:ping><description><![CDATA[<div>
<p>用AppFuse有一段时间了，也发现了它的一些问题，或者说不适合我们开发的地方。
<ol>
    <li><span style="FONT-SIZE: 10pt">build.xml中的setup：setup是安装数据库、tomcat、生成源代码并部署的target，在初次使用时很方便。但以后使用就有点问题了，因为每次执行这个命令就要把数据库删</span>除重新安装一遍，尤其是在多人同时开发的时候，每个人都setup一次实在有点麻烦。因此我在使用过一次setup后，就将命令depends="setup-db,setup-tomcat,deploy"修改为depends="package-dao,setup-tomcat,deploy"，以后再使用这个命令就不会再去动数据库了。如果有需要修改数据库的地方，单独运行ant setup-db。
    <li>ApplicationResources_zh_CN.properties &amp; ApplicationResources_zh.properties：这个前面提到过，这两个中文资源文件中存在乱码，需要把乱码的地方修改过来。
    <li>AppGen：使用AppGen生成文件的时候常常会在sample-data处报错。原因我没仔细研究，但自我认为sample-data.xml在这里没有生成的必要，所以在extras\appgen\build.xml中搜索sample-data.xdt，将该处的template标签注释掉了。
    <li>struts_form.xdt：\metadata\templates下的struts_form.xdt是用来根据POJO生成FormBean的xdoclet文件。当POJO中含有同样是POJO类型的属性时（通常是表中的父表关系），FormBean倒不会有问题，可validation.xml会自动将这个父亲中的所有属性也纳入当前FormBean里进行验证。这意味着我们在做子表单时必须包含父表单中的所有属性，麻烦！validation.xml是根据FormBean生成的，所以到struts_form.xdt下查找struts.validator，其中有一行：@struts.validator，仔细读代码就知道了这里是判断如果是org.appfuse.model.BaseObject类型的属性，就在该属性前加@struts.validator注释，所以把这一行去掉。如果需要验证，手动在POJO的get方法前加一行@struts.validator就可以了。不过不知道如果想要单独对父亲属性中的某个属性进行验证该怎么做？
    <li>DAO单元测试：AppGen生成的DAO单元测试类不能通过测试。原来在DAO的测试类中，测试了DAO的CRUD方法。在testAdd方法中，会添加一条主键值为1的记录，可是在testRemove的测试中，删除的主键值却成了3，系统找不到这条记录，当然会报错了。在extras\appgen\src\detailed下有生成DAOTest类的模版DAOTest.xdt，找到testRemove方法，把第一句修改为&lt;XDtMethodEx:idField getType="propertyType"/&gt; removeId = &lt;XDtForm:classNameLower/&gt;Id; 这样，删除的记录主键值就与添加的主键值就一致了。不过如果主键是随机生成的，这个办法就不行了，那么自己修改测试类吧。
    <li>密码加密：AppFuse默认是给用户密码加密的，如果不想加密，需要在properties.xml中设置属性encrypt.password为false，这样用户登录时系统就不会对密码加密了。但是用户注册和编辑信息时程序却没有进行判断，直接对密码加密。这里需要修改的地方有两个：SignupAction和UserAction，分别对加密的地方做一个判断。Boolean encrypt = (Boolean) getConfiguration().get(Constants.ENCRYPT_PASSWORD);一句可以拿到配置文件中的值。</li>
</ol>
</div>
<img src ="http://www.blogjava.net/kook/aggbug/114168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-27 17:42 <a href="http://www.blogjava.net/kook/articles/114168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse学习笔记-单元测试 7</title><link>http://www.blogjava.net/kook/articles/114167.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Fri, 27 Apr 2007 09:35:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/114167.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/114167.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/114167.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/114167.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/114167.html</trackback:ping><description><![CDATA[<span style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">AppFuse为几乎每一个类都提供了单元测试，&nbsp;它使用JUnit框架进行测试。我们还是以User为例仔细分析一下，阅读本篇的内容之前，你至少应该已经对单元测试有一个概念。<br>。<br>1. DAO测试<br>&nbsp;&nbsp;&nbsp; UserDAOTest用于测试UserDAO这个接口和它的实现UserDAOHibernate，它在test/dao/**/dao/中。<br>&nbsp;&nbsp;&nbsp; 所有的DAOTest都继承自BaseDAOTestCase，BaseDAOTestCase继承自TestCase。这个父类已经为我们写好了从Spring加载ApplicationContext的方法。<br>&nbsp;&nbsp;&nbsp; setUp()里做了在测试之前的初始化工作，创建了UserDAO和RoleDAO的实例，tearDown()里做销毁工作，这是每个Junit测试类都要做的事。<br>&nbsp;&nbsp;&nbsp; 以testUpdateUser()方法为例，该方法主要用于测试UserDAO的saveUser()方法是否正确。首先调用getUser()获得用户&#8220;tomcat&#8221;的信息，并修改其地址，然后调用saveUser()方法保存修改的记录。重新获得&#8220;tomcat&#8221;的信息，校验其地址是否为新地址，如果地址为新地址，测试成功。接下来把&#8220;tomcat&#8221;的version属性的值置空（version为验证当前记录是否为新记录的标志，null表示新纪录），重新保存&#8220;tomcat&#8221;，此时hibernate会认为该记录为新记录，进行insert操作，但username字段为主键不能重复，因此应该抛出异常。如果捕获到异常，测试成功。<br>&nbsp;&nbsp;&nbsp; 在控制台进入项目根目录，键入ant test-dao -Dtestcase=UserDAO，如果出现BUILD SUCCESSFUL，说明测试成功。这样，我们不需要写Manager、Action、JSP，不需要运行容器也可以确保我们的类正确了。</span>
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">2. Manager测试<br>&nbsp;&nbsp;&nbsp; 接下来继续看测试UserManager的类UserManagerTest。它在test/service/**/service/中，继承自BaseManagerTestCase，这个父类起着与BaseDAOTestCase类似的作用。<br>&nbsp;&nbsp;&nbsp; 与UserDAOTest不同的是UserManagerTest使用了jMock帮助其测试。jMock用于解决UserManager的依赖，因为UserManager中需要调用UserDAO的方法，而单元测试的基本规则是一次只测试一个对象，jMock帮助你把UserManager孤立起来，使它不会受到UserDAO的影响，我们来看它到底怎么做。<br>&nbsp;&nbsp;&nbsp; 在setUp()里，我们把UserDAO和RoleDAO放到Mock中，让Mock来做UserDAO和RoleDAO的代理，并将这两个&#8220;假冒的&#8221;DAO注入到UserManager中。<br>&nbsp;&nbsp;&nbsp; 还是以testSaveUser()为例来看这个test类怎么工作。首先创建User对象，设置用户名为&#8220;tomcat&#8221;，权限为&#8220;user&#8221;。然后我们告诉Mock当UserManager调用UserDAO的getUser()方法并参数是&#8220;tomcat&#8221;时，我们期待UserDAO返回我们刚刚创建的那个对象。接下来调用UserManager的getUser()方法以获得&#8220;tomcat&#8221;的信息。修改电话号码的内容。然后重置我们对Mock的要求。这次我们要求当UserManager调用UserDAO的saveUser方法时，不返回任何值。然后调用UserManager的saveUser()方法，校验user是否为新的电话号码和权限是否还是一个，若是，测试成功。verify()用于检查所有应该调用的方法是否都被调用了。通常来说，每对Mock对象调用了一次expects()，使用完后都要执行一次verify()。<br>&nbsp;&nbsp;&nbsp; 在控制台执行ant test-service -Dtestcase=UserManager，看看结果。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">3. Action测试<br>&nbsp;&nbsp;&nbsp; 我们继续看test/web/**/action下的UserActionTest。它继承自BaseStrutsTestCase，BaseStrutsTestCase继承MockStrutsTestCase，这个父类也做了类似BaseManagerTestCase的工作。<br>&nbsp;&nbsp;&nbsp; Action是一个控制器，主要用于接收视图层的请求，调用模型层的方法，然后返回视图层。在这里我们不关心模型层或视图层，我们只要关心Action是否能够正确的得到请求和响应请求，以及能够正确的根据请求转向。MockStrutsTestCase给了我们测试这方面很好的支持。<br>&nbsp;&nbsp;&nbsp; 以testSave()为例，首先创建一个UserForm，在里面放入部分数据，将UserForm放入该Action所对应的范围内。使用setRequestPathInfo()设置请求路径为&#8220;/saveUser&#8221;，使用addRequestParameter()添加好请求参数，actionPerform()方法将模拟请求的全过程。然后使用verifyForward()方法验证请求转发路径是否正确。并验证能不能在Action范围内得到UserForm。<br>&nbsp;&nbsp;&nbsp; 运行ant test-web -Dtestcase=UserAction，OK。<br>&nbsp;&nbsp;&nbsp; 要注意一点，这里的单元测试虽然继承自MockStrutsTestCase，但没有使用Mock，也就是说，它会真正执行到所有相关的方法，包括修改数据库。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">4. JSP测试<br>&nbsp;&nbsp;&nbsp; 我们同样可以对JSP进行测试。这里有一个工具叫做Canoo WebTest，它使用xml配置的方式来测试JSP。<br>&nbsp;&nbsp;&nbsp; 进入test/web/，有一个web-tests.xml文件，里面有所有struts-config.xml中存在的path的测试。<br>&nbsp;&nbsp;&nbsp; 以SaveUser这个target为例，我们做一个简单的说明。测试步骤包含在steps中，invoke中给这个step定一个ID号，设置请求的url：editProfile.html。接下来验证JSP页面的title是否与预期的一致。其中{webapp.prefix}和{userProfile.title}的内容在WEB-INF\classes中的ApplicationResources中定义。接下来给表单中的文本域填写内容，使用clickbutton点击保存按钮，验证保存后的页面标题是否为预期的标题。<br>&nbsp;&nbsp;&nbsp; 这一测试需要运行容器，因此首先运行Tomcat，再在控制台键入ant test-canoo -Dtestcase=UserTests或ant test-jsp -Dtestcase=PersonTests。使用ant run-all-tests无需运行Tomcat，Ant为你做这件事。</p>
<img src ="http://www.blogjava.net/kook/aggbug/114167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-27 17:35 <a href="http://www.blogjava.net/kook/articles/114167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse学习笔记-视图层 6</title><link>http://www.blogjava.net/kook/articles/114163.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Fri, 27 Apr 2007 09:27:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/114163.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/114163.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/114163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/114163.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/114163.html</trackback:ping><description><![CDATA[<div style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
<p>1. 程序描述<br>&nbsp;&nbsp;&nbsp; 视图层主要由JSP网页构成，此外还包括Resource Bundle资源文件及ActionForm Bean、Validation等，这些组件提供对国际化、接收用户输入的表单数据、表单验证和错误处理等的支持。<br>&nbsp;&nbsp;&nbsp; 与User的视图层有关的文件有：<br>&nbsp;&nbsp;&nbsp; userList.jsp：用户列表页面，用于具有管理权限的用户对其他用户的管理。<br>&nbsp;&nbsp;&nbsp; userForm.jsp：用户信息页面，用于对用户信息的增、删、改<br>&nbsp;&nbsp;&nbsp; UserForm.java：与用户信息表单对应的ActionForm Bean<br>&nbsp;&nbsp;&nbsp; validation.xml：对用户信息表单进行验证的配置文件<br>&nbsp;&nbsp;&nbsp; Resource Bundle资源文件，中文的就是ApplicationResource_Zh_cn.properties<br>&nbsp;&nbsp;&nbsp; default.jsp：用于复合网页的sitemesh文件<br>&nbsp;&nbsp;&nbsp; JavaScript、CSS文件
<p>2. JSP页面<br>&nbsp;&nbsp;&nbsp; 与用户相关的JSP页面包括用户列表和用户信息。head及foot等通用信息放置在head.jsp、foot.jsp中，因此userList.jsp及userForm.jsp只包含与业务相关的标签。下面介绍主要的标签功能：<br>&nbsp;&nbsp;&nbsp; &lt;logic:messagesPresent&gt;：判断指定的消息是否存在。若指定message属性为true，则从request范围内检索属性key为Globals.MESSAGE_KEY的ActionMessages对象。若不指定属性，则默认检索属性key为Globals.ERROR_KEY的ActionMessages对象。在本系统中一个检索Success消息，一个检索Error消息。<br>&nbsp;&nbsp;&nbsp; &lt;fmt:message&gt;：JSTL标签。用于输出Resource Bundle中的一条消息。<br>&nbsp;&nbsp;&nbsp; &lt;bean:struts&gt;：用于检索Struts框架内在的对象，如ActionFormBean、ActionForward、ActionMapping。在这里用于在JSP页面上定义一个ActionForward 变量以方便其它地方的引用。forward为struts-config.xml中定义的global-forward。<br>&nbsp;&nbsp;&nbsp; &lt;c:set&gt;：JSTL标签。用于定义一个变量，以方便其它地方的引用。<br>&nbsp;&nbsp;&nbsp; &lt;c:out&gt;：JSTL标签。用于在页面上显示一个EL表达式的值，如显示&lt;c:set&gt;定义的变量。EL是JSTL采用的简单的表达式语言，该语言提供一个访问和操作应用程序数据的简单方式。<br>&nbsp;&nbsp;&nbsp; &lt;c:if&gt;&lt;c:when&gt;&lt;c:forEach&gt;&lt;c:choose&gt;：JSTL标签。用于处理条件的标记，根据特定的逻辑条件来控制输出网页内容，或者循环遍历集合中的所有元素。<br>&nbsp;&nbsp;&nbsp; &lt;display&gt;：Display Tag的标签，用于显示控制层返回的List。可以方便的定制表格是否分页、对列排序、导出数据等。<br>&nbsp;&nbsp;&nbsp; &lt;html:form&gt;：用来定义HTML表单。Struts的HTML标签可以和标准的HTML元素完成相同的功能，Struts框架能够把表单中的数据自动映射到相应的ActionForm Bean中。<br>&nbsp;&nbsp;&nbsp; &lt;html:text&gt;&lt;html:password&gt;&lt;html:hidden&gt;：在表单上生成相应的HTML元素。<br>&nbsp;&nbsp;&nbsp; &lt;html:submit&gt;&lt;html:cancel&gt;：在表单上生成提交按钮和取消按钮。当用户按下按钮时，将产生一个提交事件或取消事件，由Action类捕获。本系统中&lt;html:submit&gt;&lt;html:cancel&gt;的属性相同（均为method），用户按下提交按钮或取消按钮后执行哪个方法由lookupMethods.properties决定。<br>&nbsp;&nbsp;&nbsp; &lt;html-el:multibox&gt;：在表单上生成HTML的CheckBox标签。html-el使用了JSTL扩展，可以使用EL表达式。<br>&nbsp;&nbsp;&nbsp; &lt;html:messages&gt;&lt;html:errors&gt;：用于在网页中输出消息。&lt;html:errors&gt;用于输出错误消息，本系统中用于显示表单中字段级的错误信息，&lt;html:messages&gt;显示全局的消息。<br>&nbsp;&nbsp;&nbsp; 自定义标签：<br>&nbsp;&nbsp;&nbsp; 在你最初运行ant new时，AppFuse就会根据你键入的项目名自动生成一个标签文件，在userForm.jsp中你会看到这个标签。<br>&nbsp;&nbsp;&nbsp; &lt;YOURAPPNAME:label&gt;：它用于显示表单输入域前的提示文本，对文本添加了一些特别的样式，如在必填项前自动加"*"号等。<br>&nbsp;&nbsp;&nbsp; &lt;YOURAPPNAME:country&gt;：userForm中有设置国家一项，该标签用于显示国家的下拉列表。<br>&nbsp;&nbsp;&nbsp; &lt;YOURAPPNAME:constants&gt;：用于在页面上显示常量类org.appfuse.Constants中的常量的值。
<p>3. ActionForm Bean<br>&nbsp;&nbsp;&nbsp; ActionForm Bean是Struts提供的表单数据传输对象，用于在视图层和控制层之间传递HTML表单数据。控制层可以从ActionForm Bean中读取用户输入的表单数据，也可以把来自模型层的数据存放到ActionForm Bean中，然后把它返回给视图。<br>&nbsp;&nbsp;&nbsp; User表单的ActionForm Bean为UserForm。UserForm继承BaseForm。BaseForm是ActionForm的子类对象，扩展了三个通用方法：toString()、equals(Object o) 和hashCode()。并定义了一个验证，用于允许用户在点击"删除"或"取消"按钮时表单无须验证。<br>&nbsp;&nbsp;&nbsp; UserForm中定义了与用户信息表单中的字段对应的属性。
<p>4. Validator验证框架<br>&nbsp;&nbsp;&nbsp; Validator验证框架负责数据验证，采用基于XML的配置文件来配置验证规则。其相关的文件有：<br>&nbsp;&nbsp;&nbsp; validation.xml：针对具体的Struts表单，为ActionForm配置所需的验证规则。<br>&nbsp;&nbsp;&nbsp; validator-rules.xml：框架自带文件，包含了一组通用的验证规则。<br>&nbsp;&nbsp;&nbsp; validator-rules-custom.xml：自定义验证规则。本系统中定义了验证两个指定的输入域值是否相等的规则。用于验证密码和确认密码是否相等。其实将这个方法稍微修改一下，把&#8220;=&#8221;变为&#8220;&lt;、&gt;&#8221;就可以验证一个域不能大于/小于另外一个域，非常的实用。<br>&nbsp;&nbsp;&nbsp; Resource Bundle：定义验证失败时显示的提示文本。Resource Bundle 中以errors为前缀的Key绝大部分用于Validator的错误提示。<br>&nbsp;&nbsp;&nbsp; 下面是在validation.xml 中配置的userForm验证规则<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;form name="userForm"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;field property="username"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; depends="required"&gt;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;arg0 key="userForm.username"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/field&gt;<br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br>&nbsp;&nbsp;&nbsp; &lt;/form&gt;<br>&nbsp;&nbsp;&nbsp; 该配置通过depends="required"定义了userForm的username字段即用户名是必填项。<br>&nbsp;&nbsp;&nbsp; &lt;arg0 key="userForm.username"/&gt;声明了该字段所对应的文本在Resource Bundle中的Key。Validator会在Resource Bundle中寻找errors.required对应的文本：'{0}' 为必填项，将userForm.username对应的文本带入{0}。如用户没有填写该项，Validator会提示&#8220;'用户名' 为必填项&#8221;的消息。<br>&nbsp;&nbsp;&nbsp; validation.xml中使用正则表达式定义了一些简单的全局的规则，如电话号码的格式等。<br>&nbsp;&nbsp;&nbsp; 默认情况下，Validator框架在Web服务器端执行表单验证。validator-rules.xml里已经定义了客户端JavaScript的生成规则，可以在JSP网页中生成JavaScript脚本。需要进行客户端验证时，在JSP中包含：<br>&nbsp;&nbsp;&nbsp; &lt;html:javascript formName="userForm" cdata="false"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dynamicJavascript="true" staticJavascript="false"/&gt;<br>&nbsp;&nbsp;&nbsp; &lt;script type="text/javascript"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; src="&lt;c:url value="/scripts/validator.jsp"/&gt;"&gt;&lt;/script&gt;<br>&nbsp;&nbsp;&nbsp; 并在&lt;html:form&gt;中定义onsubmit事件：<br>&nbsp;&nbsp;&nbsp; onsubmit="return validateUserForm(this)"<br>&nbsp;&nbsp;&nbsp; 在userForm表单的提交和取消按钮中包含了onclick="bCancel=false"事件。bCancel是Validator定义的是否进行验证的变量。当用户点击删除或取消按钮时，表单无须验证，此时bCancel= true</p>
</div>
<img src ="http://www.blogjava.net/kook/aggbug/114163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-27 17:27 <a href="http://www.blogjava.net/kook/articles/114163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse学习笔记-模型层 5</title><link>http://www.blogjava.net/kook/articles/114150.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Fri, 27 Apr 2007 09:11:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/114150.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/114150.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/114150.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/114150.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/114150.html</trackback:ping><description><![CDATA[<div style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">
<p>3.3 模型层结构<br>&nbsp;&nbsp;&nbsp; Model层为整个系统的核心部分，完成应用的业务逻辑及与数据库的通信。AppFuse中将Model分为两层：持久层和业务层。采用Spring＋Hibernate框架实现，这里以对用户User数据的操作为例详细阐述其实现方式。
<p>&nbsp;&nbsp;&nbsp; 对持久化数据的访问基于DAO（Data Access Object）模式实现。DAO模式提供了访问关系型数据库系统所需的所有接口操作的接口。DAO模式将底层数据访问操作与高层业务逻辑分离开，对上层提供面向对象的数据访问接口。
<p>&nbsp;&nbsp;&nbsp; Model层与User相关的类有：<br>&nbsp;&nbsp;&nbsp; POJO：<br>&nbsp;&nbsp;&nbsp; User：管理员表的业务对象。<br>&nbsp;&nbsp;&nbsp; 业务层：<br>&nbsp;&nbsp;&nbsp; UserManager：业务层接口，为控制层所调用。<br>&nbsp;&nbsp;&nbsp; UserManagerImpl：业务层接口的实现，调用持久层接口。<br>&nbsp;&nbsp;&nbsp; 持久层：<br>&nbsp;&nbsp;&nbsp; UserDAO：持久层接口，为业务层实现所调用。<br>&nbsp;&nbsp;&nbsp; UserDAOHibernate：持久层接口的实现。<br>&nbsp;&nbsp;&nbsp; XML配置文件：<br>&nbsp;&nbsp;&nbsp; applicationContext-service.xml：业务层接口的配置文件。<br>&nbsp;&nbsp;&nbsp; applicationContext-hibernate.xml：持久层接口的配置文件。
<p>3.3.2 Spring的IoC<br>&nbsp;&nbsp;&nbsp; Ioc（Inversion of Control）即反转控制。Ioc模式即Dependency Injection模式是依赖注射的意思，也就是将依赖先剥离，然后在适当时候再注射进入。<br>&nbsp;&nbsp;&nbsp; Spring的轻量级的bean容器为业务对象（business objects）、DAO对象和资源（如：JDBC数据源或者Hibernate SessionFactorie等）对象提供了IoC类型的装配能力。Spring使用一个xml格式的应用配置文件为开发者提供了一种通过解析定制的属性文件来手动管理单实例对象或者工厂对象的选择性。由于Spring将非入侵性做为一个重要的目标，因此可以由Spring配置管理的bean对象均不需要依赖Spring自有的接口和类就可以通过它们的bean属性完成配置。<br>&nbsp;&nbsp;&nbsp; 就实现上来讲Spring采取了配置文件的形式来实现依赖的注射，并且支持Type2 IOC（Setter Injection）以及Type3 IOC（Constructor Injection）。 <br>&nbsp;&nbsp;&nbsp; 在Model层，使用Spring提供的Setter Injection(type2)注入方式。以User为例，下面是其用法。<br>&nbsp;&nbsp;&nbsp; 在applicationContext- hibernate.xml中定义<br>&nbsp;&nbsp;&nbsp; </p>
<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: #008080">1</span><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">bean&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">userDAO</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">org.appfuse.dao.hibernate.UserDAOHibernate</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sessionFactory</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&lt;</span><span style="COLOR: #000000">ref&nbsp;local</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sessionFactory</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">bean</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp; 在UserManager类中有一句： <br>&nbsp;&nbsp;&nbsp; public void setUserDAO(UserDAO dao);<br>&nbsp;&nbsp;&nbsp; 这就是一个DAO Object设置方法（注射器）。UserDAO将被调用，和持久层通信。以这种方式创建UserDAO的实例，同样达到了由UserManager创建UserDao的目的。避免了直接实例化UserDAO的实现而使业务层和持久层紧密耦合。<br>&nbsp;
<p>&nbsp;&nbsp;&nbsp; 在控制层调用业务层方法时，使用服务定位器返回给Spring context，Spring的BeanFactory提供了getBean方法。BeanFactory是一个通用的Factory，它使对象能够按名称获取，并且能管理对象之间的关系。<br>&nbsp;&nbsp;&nbsp; 在applicationContext-service.xml中配置<br>&nbsp;&nbsp;&nbsp; </p>
<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: #008080">1</span><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">bean&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">userManager</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;parent</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">txProxyTemplate</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">target</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">bean&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">org.appfuse.service.impl.UserManagerImpl</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">userDAO</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&lt;</span><span style="COLOR: #000000">ref&nbsp;bean</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">userDAO</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">bean</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">6</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">bean</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">8</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp; 在控制层BaseAction定义通用方法：&nbsp;<br>&nbsp;&nbsp;&nbsp;</p>
<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: #008080">1</span><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;ApplicationContext&nbsp;ctx&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">2</span><span style="COLOR: #000000"><img id=Codehighlighter1_86_292_Open_Image onclick="this.style.display='none'; Codehighlighter1_86_292_Open_Text.style.display='none'; Codehighlighter1_86_292_Closed_Image.style.display='inline'; Codehighlighter1_86_292_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_86_292_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_86_292_Closed_Text.style.display='none'; Codehighlighter1_86_292_Open_Image.style.display='inline'; Codehighlighter1_86_292_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Object&nbsp;getBean(String&nbsp;name)&nbsp;</span><span id=Codehighlighter1_86_292_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">3</span><span style="COLOR: #000000"><img id=Codehighlighter1_113_252_Open_Image onclick="this.style.display='none'; Codehighlighter1_113_252_Open_Text.style.display='none'; Codehighlighter1_113_252_Closed_Image.style.display='inline'; Codehighlighter1_113_252_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_113_252_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_113_252_Closed_Text.style.display='none'; Codehighlighter1_113_252_Open_Image.style.display='inline'; Codehighlighter1_113_252_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(ctx&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_113_252_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"></span><span id=Codehighlighter1_113_252_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ctx&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WebApplicationContextUtils<br></span><span style="COLOR: #008080">5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getRequiredWebApplication<span id=Codehighlighter1_86_292_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"></span>Context(servlet.getServletContext());<br></span><span style="COLOR: #008080">6</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;ctx.getBean(name);<br></span><span style="COLOR: #008080">8</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">9</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp; 在UserAction中创建UserManager的实例：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UserManager mgr = (UserManager) getBean("userManager");<br>&nbsp;&nbsp;&nbsp; 这样，通过BeanFactory的getBean方法，以及xml配置文件，避免了在UserAction类中直接实例化UserManager，消除了控制层与业务层及业务层与持久层之间的耦合，实现了依赖的注射。<br>&nbsp;&nbsp;&nbsp; ApplicationContext 是BeanFactory的子接口，为下列东西提供支持： <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 信息查找，支持着国际化 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 事件机制，允许发布应用对象以及可选的注册以接收到事件 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可移植的文件和资源访问
<p>3.3.3 Spring的事务管理<br>&nbsp;&nbsp;&nbsp; 在数据持久层的杰出贡献，可能是Spring最为闪亮的优点。<br>&nbsp;&nbsp;&nbsp; Spring提供了通过容器的集约式参数化事务机制，实现事务的外部管理。容器管理的参数化事务为程序开发提供了相当的灵活性，同时因为将事务委托给容器进行管理，应用逻辑中无需再编写事务代码，大大节省了代码量（特别是针对需要同时操作多个事务资源的应用），从而提高了生产率。<br>&nbsp;&nbsp;&nbsp; AppFuse在applicationContext-service.xml文件中进行了对事务的配置<br>&nbsp;&nbsp;&nbsp; </p>
<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: #008080">&nbsp;1</span><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">bean&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">txProxyTemplate</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">abstract</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">true</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">org.springframework.transaction.interceptor.TransactionProxyFactoryBean</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">transactionManager</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&lt;</span><span style="COLOR: #000000">ref&nbsp;bean</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">transactionManager</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">transactionAttributes</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">props</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">save*</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">PROPAGATION_REQUIRED</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">remove*</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">PROPAGATION_REQUIRED</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">PROPAGATION_REQUIRED,readOnly</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">props</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">bean</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp; 这里定义了一个名为txProxyTemplate的TransactionProxyFactoryBean服务。它对包含实际数据逻辑的持久层对象进行了事务的封装。在这里，通过transactionAttributes属性，我们指定了事务的管理策略，即将所有的名称以save和remove开头的方法纳入事务管理范围。如果此方法中抛出异常，则Spring将当前事务回滚，如果方法正常结束，则提交事务。<br>&nbsp;&nbsp;&nbsp; 而对所有其它方法则以只读的事务处理机制进行处理。设为只读型事务，可以使持久层尝试对数据操作进行优化，如对于只读事务Hibernate将不执行flush操作，而某些数据库连接池和JDBC 驱动也对只读型操作进行了特别优化。<br>&nbsp;&nbsp;&nbsp; 如果有其他的方法需要进行写数据库操作，可以在相应的Manager配置中声明。如在UserManager中，就添加了属性<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<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: #008080">1</span><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">transactionAttributes</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">props</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">save*</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">PROPAGATION_REQUIRED</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">remove*</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">PROPAGATION_REQUIRED</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">*LoginCookie</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">PROPAGATION_REQUIRED</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">6</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">PROPAGATION_REQUIRED,readOnly</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">props</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">8</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">9</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp; 这样，以LoginCookie结尾的方法也可以写数据库了。<br>&nbsp;&nbsp;&nbsp; Spring可以将任意Java Class 纳入事务管理，而无需对其进行任何修改，因此我们的类可能完全不知道它正在被进行事务管理。
<p><br>3.3.3 Spring＋Hibernate操作持久层<br>&nbsp;&nbsp;&nbsp; Spring对Hibernate有很好的支持。<br>&nbsp;&nbsp;&nbsp; Hibernate中通过SessionFactory创建和维护Session。Spring对SessionFactory的配置进行了整合，无需再通过Hibernate.cfg.xml对SessionFactory进行设定。SessionFactory节点的mappingResources属性包含了映射文件的路径，list节点下可配置多个映射文件。hibernateProperties节点则容纳了所有的属性配置。可以对应传统的Hibernate.cfg.xml文件结构对这里的SessionFactory配置进行解读。<br>&nbsp;&nbsp;&nbsp; 下面是HibernateSessionFactory 和 HibernateTransactionManager的配置：<br>&nbsp;&nbsp;&nbsp; 在applicationContext-hibernate.xml中：<br>&nbsp;&nbsp;&nbsp; </p>
<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"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">bean&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sessionFactory</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">org.springframework.orm.hibernate.LocalSessionFactoryBean</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">dataSource</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&lt;</span><span style="COLOR: #000000">ref&nbsp;bean</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">dataSource</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">mappingResources</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">list</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">value</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">com</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">mycompany</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">model</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">User.hbm.xml</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">value</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">list</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hibernateProperties</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">props</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hibernate.dialect</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">@HIBERNATE</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">DIALECT@</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;!--</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hibernate.show_sql</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">--&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;!--</span><span style="COLOR: #000000">prop&nbsp;key</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hibernate.hbm2ddl.auto</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">update</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">prop</span><span style="COLOR: #000000">--&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">props</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">bean</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp; Spring 提供了一个 HibernateTransactionManager，采用面向Hibernate的TransactionManager实现：org.springframework.orm.hibernate.HibernateTransactionManager。他用线程捆绑了一个Hibernate Session，用它来支持transactions。<br>&nbsp;&nbsp;&nbsp; </p>
<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"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">bean&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">transactionManager</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">org.springframework.orm.hibernate.HibernateTransactionManager</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">property&nbsp;name</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sessionFactory</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&lt;</span><span style="COLOR: #000000">ref&nbsp;local</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sessionFactory</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;&lt;/</span><span style="COLOR: #000000">property</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">bean</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp; sessionFactory Bean引用了HibernateSessionFactory，而transactionManager Bean引用了HibernateTransactionManage。 transactionManager Bean中有个sessionFactory属性。 HibernateTransactionManager有个sessionFactory setter 和 getter方法，用来在Spring启动的时候实现&#8220;依赖注入&#8221; （dependency injection）的。 在sessionFactory 属性里引用sessionFactory Bean。这两个对象在Spring容器初始化后就被组装了起来了。<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; User使用一个TransactionProxyFactoryBean，它定义了一个setTransactionManager()。能很方便的处理申明的事物还有Service Object。TransactionProxyFactoryBean 还有个setter. 这会被Business service object（UserManager）引用， UserManager定义了业务层，并且它还有个属性，由setUserDAO()引用。
<p>&nbsp;&nbsp;&nbsp; 系统持久层中所有的类都继承自Spring提供的HibernateDaoSupport类，HibernateSupport实现了HibernateTemplate和SessionFactory实例的关联。HibernateTemplate对Hibernate Session操作进行了封装，提供了一个简单的方式实现了Hibernate-based DAO对象。借助HibernateTemplate我们可以脱离每次数据操作必须首先获得Session实例、启动事务、提交/回滚事务以及烦杂的try/catch/finally的繁琐操作。一个简单的Hibernate访问方法就完全解决了些麻烦! 无论是在多个DAO接口还是在多方事务的情况下，Spring使得多种DAO对象无缝地协同工作。<br>&nbsp;&nbsp;&nbsp; 对于简单的单步的动作，象find, load, saveOrUpdate或者delete的调用，HibernateTemplate提供更为便利的选择以代替象一行的回调的执行。此外HibernateDaoSupport类提供了setSessionFactory方法来接受一个SessionFactory，同时提供了getSessionFactory和getHibernateTemplate方法供其继承类使用。将这些结合起来，允许对于典型的需求给出了非常简单的DAO实现，如获得所有用户的方法：<br>&nbsp;&nbsp;&nbsp;</p>
<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"><img id=Codehighlighter1_33_125_Open_Image onclick="this.style.display='none'; Codehighlighter1_33_125_Open_Text.style.display='none'; Codehighlighter1_33_125_Closed_Image.style.display='inline'; Codehighlighter1_33_125_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_33_125_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_33_125_Closed_Text.style.display='none'; Codehighlighter1_33_125_Open_Image.style.display='inline'; Codehighlighter1_33_125_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;List&nbsp;getUsers(User&nbsp;user)&nbsp;</span><span id=Codehighlighter1_33_125_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"></span><span id=Codehighlighter1_33_125_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;getHibernateTemplate().find(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">from&nbsp;User&nbsp;u&nbsp;order&nbsp;by&nbsp;upper(u.username)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
</div>
<img src ="http://www.blogjava.net/kook/aggbug/114150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-27 17:11 <a href="http://www.blogjava.net/kook/articles/114150.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse学习笔记-控制层 4</title><link>http://www.blogjava.net/kook/articles/114144.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Fri, 27 Apr 2007 09:07:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/114144.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/114144.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/114144.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/114144.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/114144.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">1. 我们先详细介绍一下<strong>Struts的控制器</strong>的工作流程。<br>&nbsp;&nbsp;&nbsp; 首先，控制器（ActionServlet）进行初始化工作，读取配置文件struts-config.xml，为不同的Struts模块初始化相应的ModuleConfig对象。相应地有ControlConfig集合、FormBeanConfig集合、ForwardConfig集合和MessageResourcesConfig集合等。<br>&nbsp;&nbsp;&nbsp; AppFuse中设计了一个继承ActionServlet 的子类：LoginServlet做为控制器，对ActionServlet的功能进行了扩展。主要的功能是对本系统使用到的一些组件进行初始化工作，如用户身份的安全校验url、密码加密规则等。<br>&nbsp;&nbsp;&nbsp; 控制器接收到HTTP请求，并从ActionConfig中找出对应于该请求的Action子类，如果没有对应的Action，控制器直接将请求转发给JSP或者静态页面。否则控制器将请求分发至具体Action类进行处理。<br>&nbsp;&nbsp;&nbsp; 在控制器调用具体Action的方法之前，相应的ActionForm对象将利用HTTP请求中的参数来填充自己。此外，若所操作的ActionForm类配置了validate，系统会调用validate组件来检查请求参数的合法性，并且返回一个包含所有错误信息的ActionErrors对象。如果执行成功，ActionForm自动将这些参数信息以FormBean的方式保存在Servlet Context中，这样它们就可以被其它Action对象或者JSP调用。<br>&nbsp;&nbsp;&nbsp; 执行完成Action中的方法之后，返回一个ActionForward对象，控制器通过该ActionForward对象来进行转发工作。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">&nbsp;&nbsp;&nbsp; AppFuse实现的最主要的功能是对用户的管理。下面就以对用户的管理来说明一下AppFuse控制器的实现。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">&nbsp;&nbsp;&nbsp; 与用户信息表单数据相关的FormBean是UserForm。UserForm用来存放用户的基本信息。<br>&nbsp;&nbsp;&nbsp; UserForm的控制器是org.appfuse.webapp.action.UserAction。UserAction继承了BaseAction。BaseAction也是系统中几乎所有Action类的父类，它继承自Struts提供的DispatchAction，并提供了控制层通用的方法。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">2. <strong>Action</strong><br>Action是用户请求和业务逻辑之间的桥梁，每个Action充当客户的一项业务代理。主要完成以下任务：<br>&nbsp;&nbsp;&nbsp; 1.&nbsp;接收用户请求。<br>&nbsp;&nbsp;&nbsp; 2.&nbsp;根据用户请求，调用合适的模型组件来执行相应的业务逻辑。<br>&nbsp;&nbsp;&nbsp; 3.&nbsp;获取业务逻辑执行结果<br>&nbsp;&nbsp;&nbsp; 4.&nbsp;根据当前状态以及业务逻辑执行结果，选择合适的视图组件返回给用户。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">3. <strong>DispatchAction</strong><br>&nbsp;&nbsp;&nbsp; org.apache.struts.actions.DispatchAction是org.apache.struts.action.Action的子类。<br>&nbsp;&nbsp;&nbsp; Action的execute()方法是调用模型的业务方法，完成用户请求的业务逻辑，然后根据执行结果把请求转发给其它合适的Web组件。通常，在一个Action类中只能完成一种业务操作（通过execute()方法）。<br>&nbsp;&nbsp;&nbsp; DispatchAction允许用户将完成一个业务逻辑所需要的连续动作和相关动作集中于一个Action类中。无须覆盖execute()方法，而是可以创建一些实现实际业务操作的方法，用户通过method请求参数指定所需要使用的方法。
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">4. <strong>BaseAction</strong><br>&nbsp;&nbsp;&nbsp; BaseAction中实现了系统中Action子类需要用到的通用方法，主要有：<br>&nbsp;&nbsp;&nbsp; 1.&nbsp;public Object getBean(String name):通过读取Spring的applicationContext-service.xml配置文件来创建实例从而实现&#8220;依赖注入&#8221;的方法。<br>&nbsp;&nbsp;&nbsp; 2.&nbsp;public ActionMessages getMessages(HttpServletRequest request)：初始化Struts的ActionMessages，并返回。<br>&nbsp;&nbsp;&nbsp; 3.&nbsp;protected Object convert(Object o) ：POJO与FormBean之间的转换方法。<br>&nbsp;&nbsp;&nbsp; 4.&nbsp;execute()：置换了原始的execute()方法。作用是根据请求的url寻找相关的业务方法（没有method请求参数时）。例如请求的页面是editUser.html,则执行edit()方法。<br>&nbsp;&nbsp;&nbsp; 5.&nbsp;protected ActionForm getActionForm(ActionMapping mapping,&nbsp;HttpServletRequest request)：在mapping范围内得到一个Action FormBean。<br>&nbsp;&nbsp;&nbsp; 6.&nbsp;protected User getUser(HttpSession session) ：从Session中拿到当前登录用户信息。<br>&nbsp;&nbsp;&nbsp; 7.&nbsp;protected void updateFormBean(ActionMapping mapping,&nbsp;HttpServletRequest request, ActionForm form)：在指定的范围内更新当前Action 所对应的Form Bean对象。<br>&nbsp;&nbsp;&nbsp; 8. protected void removeFormBean(ActionMapping mapping, HttpServletRequest request)：去除无用的Form Bean。&nbsp;
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">5. <strong>UserAction</strong><br>&nbsp;&nbsp;&nbsp; UserAction是用户数据管理的控制器，提供了对用户数据的添加、修改、删除、查询等操作的控制，其包含的业务方法有：<br>&nbsp;&nbsp;&nbsp; 1.&nbsp;add()：进入添加用户页面。<br>&nbsp;&nbsp;&nbsp; 2.&nbsp;cancel()：当用户在表单中点击&#8220;取消&#8221;按钮时，执行该方法。如果用户是通过用户列表进入该表单，即当前用于拥有管理其它用户的权限，返回到用户列表，否则返回到主页面。<br>&nbsp;&nbsp;&nbsp; 3.&nbsp;delete()：根据请求的用户ID调用业务层的removeUser ()方法删除相应的记录，返回到用户列表。<br>&nbsp;&nbsp;&nbsp; 4.&nbsp;edit()：首先校验用户请求的URL是否为editProfile.html，若是，表示当前登录用户要查看自己的信息，此时请求路径中不应该含有用户ID（用户ID从Session中取得）或用于标识请求是通过用户列表的from参数，如果含有这两个参数，发出&#8220;无权限&#8221;的错误信息。若不是，表示当前用户是通过用户列表进行请求。根据请求的用户ID调用业务层的getUser ()方法取得相应的记录。更新相应的FormBean。<br>&nbsp;&nbsp;&nbsp; 5.&nbsp;save()：当需要要添加或修改用户信息时，执行该方法。首先校验请求参数中是否有&#8220;encryptPass&#8221;并值为&#8220;true&#8221;，若是，表示密码需要加密，随即将密码加密。然后调用业务层的getRole ()方法将提交的用户权限持久化。调用业务层的saveUser ()方法，保存用户信息。如果用户编辑的是自己的信息，更新Session中的当前登录用户信息。如果用户在登录时选择了&#8220;记住我&#8221;，更新保存的Cookie。如果用户编辑的是其它用户的信息，根据version判断是新添数据还是修改数据，在ActionMessages中存储不同的消息，返回到添加/修改用户信息页面。若是新添数据，调用sendNewUserEmail()给新用户发送一封Email。<br>&nbsp;&nbsp;&nbsp; 6.&nbsp;search()：具有管理权限的用户进入用户列表时执行该方法。调用业务层的getUsers ()方法，取得包含所有用户信息的List。返回到用户列表页面。<br>&nbsp;&nbsp;&nbsp; 7.&nbsp;unspecified()：如果请求的url没有包含method参数，通过BaseAction的execute()方法也找不到指定的方法时，执行该方法。在该方法中转到search()方法。<br>&nbsp;&nbsp;&nbsp; 以上是很多Action需要用到的基本的方法。<br>&nbsp;&nbsp;&nbsp; 8.&nbsp;sendNewUserEmail()：根据FormBean中的内容给用户发送一封Email。<br>&nbsp;&nbsp;&nbsp; 9.&nbsp;checkForCookieLogin()：如果用户是通过Cookie登录（用户在登录时选择了&#8220;记住我&#8221;），发出一个消息警告用户不能修改密码。</p>
<img src ="http://www.blogjava.net/kook/aggbug/114144.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-27 17:07 <a href="http://www.blogjava.net/kook/articles/114144.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse学习笔记-组件和工具 3</title><link>http://www.blogjava.net/kook/articles/114140.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Fri, 27 Apr 2007 09:03:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/114140.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/114140.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/114140.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/114140.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/114140.html</trackback:ping><description><![CDATA[<div style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">使用大量的第三方组件是Appfuse的主要特点，接下来我们就看看他都使用了什么组件。<br>&nbsp;&nbsp;&nbsp; 1. <strong>DisplayTag</strong>：自我觉得是AppFuse里降低编码量最大的组件，这里有一篇使用DisplayTag的文章，<a href="http://blog.csdn.net/clearwater21cn/archive/2005/02/21/296316.aspx"><u><font color=#0000ff>http://blog.csdn.net/clearwater21cn/archive/2005/02/21/296316.aspx</font></u></a>，这里就不说了。<br>&nbsp;&nbsp;&nbsp; 2.&nbsp;<strong>JSTL</strong>：JSP Standard Tag Library是建立在JSP上的某种custom actions（自定操作）或custom tags（自定标签）,类似于html语法中的标记。JSTL提供了诸如循环、条件、数据库访问、XML处理、国际化(i18n)等开发上的工具和流程。本系统中主要使用JSTL的核心标记库及格式化标记库标签实现动态的Web页和国际化支持。<br>&nbsp;&nbsp;&nbsp; 3.&nbsp;<strong>Sitemesh</strong>：用于建立复合视图。旨在提高页面的可维护性和复用性。sitemesh应用Decorator模式，用filter截取request和response,把页面组件head,content,banner结合为一个完整的视图，可方便的建立复合视图模式。<br>&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;<strong>Struts Menu</strong>：AppFuse作者写的基于JSP和Struts的应用程序的Web菜单框架。利用它可以很方便的通过XML定义及JSP标签构建树形菜单。<br>&nbsp;&nbsp;&nbsp; 5.&nbsp;<strong>OSCache</strong>：OSCache是OpenSymphony组织提供的一个J2EE架构中Web应用层的缓存技术实现组件。通过缓存页面的输出结果，可以很显著的改善系统运行性能。并能够改善系统的稳定性。<br>&nbsp;&nbsp;&nbsp; 6.&nbsp;<strong>UrlRewrite</strong>：地址变换技术，可以将应用中的url变换成自定义样式。<br>&nbsp;&nbsp;&nbsp;&nbsp;7. <strong>Acegi</strong>：1.8加入的新组件，属于Spring的子项目。它使用Spring的方式提供了安全和认证安全服务，包括使用Bean Context，拦截器和面向接口的编程方式。因此，Acegi安全系统能够轻松地适用于复杂的安全需求。AppFuse用它实现了用户的认证和授权管理。<br>&nbsp;&nbsp;&nbsp; 8.&nbsp;<strong>Quartz</strong>：AppFuse中没有使用这一组件，但我觉得它提供的功能很常用，并实现的很好，因此顺带提一下。Quartz是一个实现任务定时调度的框架，它提供了简单易用的接口，实现了可调度任务的接口，并实现了强大的任务调度运行时（可以独立运行、可以作为EJB部署于容器中、本身支持cluster，等等），这一组件由Spring提供。
<p>&nbsp;&nbsp;&nbsp; AppFuse还给我们提供或介绍了很多好用的工具，能大大加快我们的开发速度。如果能够很好的使用这些工具，我们可以只给出一个表的POJO，它们就能够自动生成所有的操作该POJO对应的数据表通常需要的增、删、改、查功能的模型层、控制层、视图层文件，几乎不用再修改就可以完成对这张表的所有基本操作。<br>1. <strong>AppGen</strong><br>&nbsp;&nbsp;&nbsp; AppFuse给我们提供了一个通过xdoclet生成代码的工具——AppGen，我们来看看它怎么用。<br>&nbsp;&nbsp;&nbsp; POJO（Plain Old Java Object）代表一个存储在持久性存储器（如数据库）中的实体的对象视图。它通过hbm.xml配置文件与存储器中的数据相映射。<br>&nbsp;&nbsp;&nbsp; 首先，你需要有这个表的POJO，放在src\dao\org\appfuse\model中。<br>&nbsp;&nbsp;&nbsp; 在控制台中进入项目下的extras\appgen路径，键入ant -Dmodel.name=XXX -Dmodel.name.lowercase=xxx，第一个XXX处写你的POJO类名，第二个xxx处写这个对象在小写时的名字。当控制台出现BUILD SUCCESSFUL时，代码就生成了。代码在extras\appgen\build\gen文件夹下，包括java源代码（DAO、Service、Action）、单元测试、JSP、资源文件、xml配置文件、源数据等，目录结构与原项目一致，你只要把需要的目录拖到相应的项目根目录下就可以了，当然了，有的代码是需要在已有的文件上进行修改的，主要是属性文件和xml文件，这时需要你把新的代码手动转移到原来的文件中。<br>&nbsp;&nbsp;&nbsp; AppGen也可以为你省去这个麻烦，只要在前面的那段命令中加一个install，即ant install -Dmodel.name=XXX -Dmodel.name.lowercase=xxx，AppGen会直接把代码生成到你的项目中去，包括修改已存在的文件。这时为了保险起见，最好先备份一下代码。
<p>2.&nbsp;<strong>xdoclet注释</strong><br>&nbsp;&nbsp;&nbsp; AppGen生成的文件缺少了hbm.xml和Action Form Bean，难道我们要自己写吗？不是的。仔细察看build.xml文件就会发现实际上我们下载的AppFuse最初的源代码中并没有hbm.xml、FormBean，甚至连web.xml、struts-config.xml、validation.xml都没有，这些文件都是在我们执行ant setup时build.xml使用xdoclet自动生成的。&nbsp;甚至连数据库和表、表里的数据也可以自动生成。奥秘都在POJO中。<br>&nbsp;&nbsp;&nbsp; 查看User.java这个POJO你会发现里面除了java代码，还有很多注释，有@hibernate开头的，@struts开头的，这些都是xdoctlet的标签。我们大致讲解一下：<br>&nbsp;&nbsp;&nbsp; <strong>@struts.form</strong>：用来生成Form Bean，如User.java中写了@struts.form include-all="true" extends="BaseForm"，意思是该POJO中每一个属性在Form Bean中都要有，并且生成的Form Bean文件要继承BaseForm。如果不希望生成的FormBean包含POJO的所有属性，可以在相关的属性get方法前填写注释@struts.form-field，意思是该属性要在FormBean中生成。那么如果我们要在FormBean中添加一些POJO没有的属性或方法怎么做呢？打开metadata\web文件夹，可以看到有一个xdoclet-UserForm.java文件，里面是User.java在生成Form Bean时新加入的代码，我们同样可以把我们自己在FormBean中增加的代码新建到一个xdoclet-POJOFrom.java文件中就好了。<br>&nbsp;&nbsp;&nbsp; <strong>@struts.validator</strong>：用来生成validation.xml文件。最常用的如@struts.validator type="required"，意为该属性在表单中需要有必填的验证。当然前提是这个属性也在FormBean中。validation还有一项配置是自定义的校验规则，使用正则表达式表示。metadata\web中有一个文件validation-global.xml，里面就有邮编等规则的配置。<br>&nbsp;&nbsp;&nbsp; <strong>@hibernate</strong>：这个是比较复杂的，用来生成hbm.xml文件。其实内容与hbm.xml基本一致，所以如果会写hbm.xml，这个也就会写了。初学者可以先建表，使用工具生成hbm.xml，再仿照生成的hbm.xml内容写这个标签。一旦标签写好了，不光可以生成hbm.xml，build.xml还可以自动在数据库中建表。<br>&nbsp;&nbsp;&nbsp; <strong>@struts.action/@struts.action-forward</strong>：POJO不能生成struts-config.xml，这个标签是要写到Action中的。如果使用AppGen生成Action，你会看到@struts.action已经写好了，这个标签的作用就是生成当前Action在struts-config.xml中的映射代码，写法与struts-config.xml中一致，其实就是把xml中的配置移植到Action中。还有一个问题，如果我们要在struts-config.xml中进行与Action无关的全局的配置，如global-forwards呢？浏览metadata\web文件夹你会发现里面有多个xml文件，其中以global和struts开头的文件就是写这些配置的。build.xml在setup时会自动将这些文件联合Action中的注释生成一个完整的struts-config.xml文件。<br>&nbsp;&nbsp;&nbsp; 接下来还有web.xml文件，你一定猜到了同样需要在metadata\web中配置。除了刚才提到的那些xml文件，剩下的基本都是用于配置web.xml的了。我们自定义的filter和listener是有具体类的，所以我们同样可以在这些filter和listener类中添加注释，具体例子参考AppFuse中的filter吧，很简单的。<br>&nbsp;&nbsp;&nbsp; 进行了所有配置后，运行ant setup，build.xml会根据POJO、Action等自动生成FormBean、hbm.xml、struts-config.xml、validation.xml、web.xml，并在数据库中创建相应的表。看起来可能有点复杂，但如无特殊要求，对数据表的增、删、改、查，只需要写好POJO，一切都可以搞定。<br><br>3. <strong>Commonclipse</strong><br>&nbsp;&nbsp;&nbsp; org.appfuse.model中有一个抽象类BaseObject，定义了三个抽象方法：hashCode()、equals()和toString()，其中前两个是Hibernate要求POJO必须实现的方法。所有的POJO都继承自这个类，当然也要实现这三个方法，这个工具可以帮助你实现这三个方法。<br>&nbsp;&nbsp;&nbsp; 我们可以使用Eclipse在线获得这个工具。步骤：依次点击"Help" -&gt; "Software updates" -&gt; "Find and Install" -&gt; "Search for new features to install"，点击"add update site"，输入http://commonclipse.sourceforge.net，OK。<br>&nbsp;&nbsp;&nbsp; 接下来需要对Commonclipse进行一些配置。点击"Window"-&gt;"Preferences"，选择"Java"，你会在菜单中看到Commonclipse。点击General标签，将复选框全部钩掉（全不选）。点击"OK"。<br>&nbsp;&nbsp;&nbsp; 选中一个类，右击，你会在菜单中看到Commonclipse。选择要生成的方法，就这么简单。</p>
</div>
<img src ="http://www.blogjava.net/kook/aggbug/114140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-27 17:03 <a href="http://www.blogjava.net/kook/articles/114140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse学习笔记2-框架总揽</title><link>http://www.blogjava.net/kook/articles/114139.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Fri, 27 Apr 2007 09:01:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/114139.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/114139.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/114139.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/114139.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/114139.html</trackback:ping><description><![CDATA[<div style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">安装好了系统，我先来对它做一个总体介绍。<br>&nbsp;&nbsp;&nbsp; Raible给AppFuse这个Web应用写了好几种实现方式，有Struts Spring Hibernate、Spring iBATIS、WebWork Spring Hibernate、JSF Spring Hibernate、Tapestry Spring Hibernate 等等。目前在国内最流行的应该就是Struts Spring Hibernate了，就以这种框架为例介绍AppFuse吧。<br>&nbsp;&nbsp;&nbsp; Struts Spring Hibernate使用了基于MVC模式的struts的框架，并使用hibernate进行持久层操作，使用Spring对各个组件进行&#8220;依赖注射&#8221;。通过这种设计模型把应用逻辑，处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用，具有组件化的优点从而更易于实现对大规模系统的开发和管理。使用AppFuse，你应该对Struts和Hibernate有一定的了解。
<p>下面分别介绍各层的功能：<br>&nbsp;&nbsp;&nbsp; 1.&nbsp;<strong>Controller</strong>：控制器的作用是从客户端接受请求，并且选择执行相应的业务逻辑，然后把响应结果送回到客户端。Controller功能核心是一个Servlet类型的对象ActionServlet，它用来接受客户端的请求。ActionServlet包括一组基于配置的ActionMapping对象，每个ActionMapping对象实现了一个请求到一个具体的Action控制器对象之间的映射。所有的Action对象都是从Struts的Action类派生的子类。Action对象封装了具体的控制逻辑，调用Model层的业务逻辑模块，并且把响应提交到合适的View组件以产生响应。Struts提供的ActionForm组件对象为显示提供一个模型，可以通过定义属性描述客户端表单数据。从它派生子类对象，利用它和Struts提供的自定义标记库结合可以实现对客户端的表单数据的良好封装和支持。通过ActionForm组件对象实现了对View和Model之间交互的支持。同时，控制器会负责处理异常及UI验证<br>&nbsp;&nbsp;&nbsp; 2.&nbsp;<strong>Model</strong>：代表的是应用的业务逻辑。Model分为两层：持久层和业务层，用这种模式将底层数据访问操作与高层业务逻辑分离开。持久层使用ORM开源框架：Hibernate。 Hibernate为java提供了OR持久化机制和查询服务。业务层框架使用Spring。Spring着手于&#8220;依赖注入&#8221;这样的概念。Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction management handler（事物管理控制）、Object Factoris(对象工厂)、service objects（服务组件）——都通过XML来配置联系起来，降低了各个组件的耦合度。<br>&nbsp;&nbsp;&nbsp; 3.&nbsp;<strong>View</strong>：View是应用的表示面，通过JSP技术实现。Struts提供了自定义的标记库可以使用，通过这些自定义标记可以非常好地和系统的Model部分交互，通过使用这些自定义标记创建的JSP表单，可以实现和ActionForm的映射，完成对用户数据的封装。<br><br>&nbsp;&nbsp;&nbsp; Action调用Model层方法时通过读取Spring框架配置文件来创建实例。Spring框架控制主体公共部分，而把用户要使用的部分定义了接口，然后用Spring框架调用这个接口，实现回调。Model层分为两层：业务层（Manager）和持久层（DAO），每一层又分接口和实现两部分。Action调用Manager层的接口，Manager的Implement实现高层业务逻辑并调用DAO接口实现对数据库的操作。这三层之间的调用均通过Spring的&#8220;依赖注入&#8221;机制实现。</p>
</div>
<img src ="http://www.blogjava.net/kook/aggbug/114139.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-27 17:01 <a href="http://www.blogjava.net/kook/articles/114139.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse开发环境</title><link>http://www.blogjava.net/kook/articles/113332.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Tue, 24 Apr 2007 13:57:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/113332.html</guid><wfw:comment>http://www.blogjava.net/kook/comments/113332.html</wfw:comment><comments>http://www.blogjava.net/kook/articles/113332.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kook/comments/commentRss/113332.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kook/services/trackbacks/113332.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt">最近开始学习AppFuse了，至于什么是AppFuse这里就不罗嗦了，网上一箩筐，随便百度下都是。<br>首先来构件自己的第一个AppFuse应用。<br>&nbsp;第一步：下载相关资源。主要包括：<br>1、JDK<br>2、Tomcat<br>3、Ant<br>4、Eclipse<br>5、MySql<br>6、AppFuse<br>前面5个这里就不废话了，弄不到也就没必要接着往下看了。第6个的下载地址为：<a href="https://appfuse.dev.java.net/">https://appfuse.dev.java.net/</a>这也是他的官方地址。E文牛的人，可以参考里面的文档，里面有很多指南。但是有些太罗嗦，而且弄得很悬乎，觉得有些复杂。<br>我下载的是appfuse-1.9.4-src.zip，解压后，可以从Eclipse直接导入。<br><br>第二步：全部下载完成后，需要配置相关环境变量，大家可以根据自己的习惯配置，我的配置情况如下：<br>HOME<br>D:\AppConfig\Source<br><br>TOOLS_HOME<br>D:\AppConfig\Tools</p>
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">MYSQL_HOME<br>%TOOLS_HOME%\mysql-5.0.24-win32</p>
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">SDKS_HOME<br>D:\AppConfig\SDKs</p>
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">ANT_HOME<br>%TOOLS_HOME%\apache-ant-1.7.0</p>
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">CATALINA_HOME<br>%TOOLS_HOME%\apache-tomcat-5.5.17</p>
<p style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana">JAVA_HOME<br>%SDKS_HOME%\jdk1.5.0_06</p>
<p style="FONT-SIZE: 10pt">PATH<br>%JAVA_HOME%\bin;%ANT_HOME%\bin;%CATALINA_HOME%\bin;%MYSQL_HOME%\bin&nbsp;<br><br>看这个配置，应该很容易知道相关的目录结构。<br><br>第三步：Eclipse相关配置<br>1、解压appfuse-1.9.4-src.zip文件，并复制appfuse\lib\junit3.8.1目录下的junit.jar文件，粘贴到ant的lib目录下（也可以之后在Eclipse的Ant运行环境中加入）；<br>2、打开Elipse，依次找到Window——Preferences——Ant——Runtime——Classpath——Ant&nbsp;Home，点击后从打开目录对话框中选定你的Ant的所在目录，我这里的目录是：D:\AppConfig\Tools\apache-ant-1.7.0当然你也可以用Elipse缺省的Ant，但是这里你要把appfuse\lib\junit3.8.1目录下的junit.jar文件从外部导入进来。<br>3、将解压appfuse-1.9.4-src.zip后的文件从Elipse中导入进来，假设项目名称为：appfuse。<br>4、打开Ant运行窗口，导入appfuse下Buile.xml并执行new指令，来创建你的第一个AppFuse项目Hello。要注意项目名称不能使用"test"或者包含"appfuse"或者以数字开头。然后按照向导提示完成相关设置就可以了。&nbsp;这是在Eclipse下创建你的第一个AppFuse应用，当然，如果你喜欢，也可以在控制下完成同样的动作，因为已经在环境变量中加入了相关映射，从而使得在控制台下运行成为可能。你还需要添加支持Tomcat的jar包和属性文件。同样在Window &#8594; Preferences &#8594; Ant &#8594; Runtime中，点击Add External JARs按钮，在Tomcat安装目录的/server/lib中选择catalina-ant.jar。添加到classpath中。然后点击Properties书签，点击Add Files按钮，选择项目Hello\lib\ant-contrib-1.0b1中的tomcatTasks.properties作为全局的属性文件。<br>5、在Eclipse中将刚刚创建的名为Hello的应用导入进来。他就在你解压appfuse-1.9.4-src.zip后appfuse文件的同级目录下。&nbsp;打开Ant运行窗口，导入Hello下Buile.xml并执行setup指令,如果你的MySql设置了密码的话，他会提示出错，新项目的缺省密码为空。这时候你可以打开Hello下的properties.xml文件，找到&lt;property name="database.admin.username" value="root"/&gt;&lt;property name="database.admin.password" value=""/&gt;修改你的用户名和密码，保存后重新运行setup，Ant会自动完成资料库及相关代码的创建。运行start.tomcat启动Tomcat服务器。访问：<a href="http://localhost:8080/Hello">http://localhost:8080/Hello</a>访问你创建的第一个应用，看看AppFuse的效果吧！<br>至此，第一个AppFuse应用完成。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<img src ="http://www.blogjava.net/kook/aggbug/113332.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-24 21:57 <a href="http://www.blogjava.net/kook/articles/113332.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclise 插件收集</title><link>http://www.blogjava.net/kook/articles/113142.html</link><dc:creator>kook</dc:creator><author>kook</author><pubDate>Tue, 24 Apr 2007 04:36:00 GMT</pubDate><guid>http://www.blogjava.net/kook/articles/113142.html</guid><description><![CDATA[Commonclipse<br><a href="http://commonclipse.sourceforge.net/"><span style="FONT-SIZE: 12pt">http://commonclipse.sourceforge.net</span></a><br><br><span style="FONT-SIZE: 12pt">Subclipse——http://subclipse.tigris.org/<br></span><a href="http://subclipse.tigris.org/update_1.2.x"><span style="FONT-SIZE: 12pt">http://subclipse.tigris.org/update_1.2.x</span></a><br><br>Implementors<br>http://eclipse-tools.sourceforge.net/updates/<br><br>Cubictest<br><a href="http://www.cubictest.org/update">http://www.cubictest.org/update</a> <br><br>log4E<br>http://log4e.jayefem.de/update<br><br>RMI Plug-in for Eclipse<br>version 2.0<br>http://www.genady.net/rmi/v20/install/
<img src ="http://www.blogjava.net/kook/aggbug/113142.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kook/" target="_blank">kook</a> 2007-04-24 12:36 <a href="http://www.blogjava.net/kook/articles/113142.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>