??xml version="1.0" encoding="utf-8" standalone="yes"?>午夜影视日本亚洲欧洲精品一区,亚洲欧洲一区二区三区,亚洲av永久无码精品秋霞电影秋 http://www.tkk7.com/xixidabao/category/15382.htmlGROW WITH JAVAzh-cnSat, 21 Apr 2007 02:48:12 GMTSat, 21 Apr 2007 02:48:12 GMT60?Spring 更好地处?Struts 动作三种整合 Struts 应用E序?Spring 的方?/title><link>http://www.tkk7.com/xixidabao/archive/2007/04/21/112404.html</link><dc:creator>JAVA之\</dc:creator><author>JAVA之\</author><pubDate>Sat, 21 Apr 2007 02:43:00 GMT</pubDate><guid>http://www.tkk7.com/xixidabao/archive/2007/04/21/112404.html</guid><description><![CDATA[<p><a name=N1008F><span id="tqjfqyt" class=atitle><font size=4>Z?Spring q么了不P</font></span></a></p> <p>Spring 的创立?Rod Johnson 以一U批判的眼光看待 Java™ 企业软g开发,q且提议很多企业N都能够通过战略C?IOC 模式Q也UC依赖注入Q来解决。当 Rod 和一个具有奉献精的开放源码开发者团队将q个理论应用于实跉|Q结果就产生?Spring 框架。简a之,Spring 是一个轻型的容器Q利用它可以使用一个外?XML 配置文g方便地将对象q接在一赗每个对象都可以通过昄一?JavaBean 属性收C个到依赖对象的引用,留给您的单Q务就只是在一?XML 配置文g中把它们q接好?/p> <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=N1009C><strong>IOC ?Spring</strong></a><br> <p>IOC 是一U应用E序逻辑外在化的设计模式Q所以它是被注入而不是被写入客户Z码中。将 IOC 与接口编E应用结合,像 Spring 框架那样Q生了一U架构,q种架构能够减少客户机对特定实现逻辑的依赖。请参阅 <a ><font color=#996699><u>参考资?/u></font></a> 了解更多关于 IOC ?Spring 的信息?/p> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> </p> <p>依赖注入是一个强大的Ҏ,但是 Spring 框架能够提供更多Ҏ。Spring 支持可插拔的事务理器,可以l您的事务处理提供更q泛的选择范围。它集成了领先的持久性框Ӟq且提供一个一致的异常层次l构。Spring q提供了一U用面向方面代码代替正常的面向对象代码的简单机制?/p> <p>Spring AOP 允许您?em>拦截?/em> 在一个或多个执行点上拦截应用E序逻辑。加强应用程序在拦截器中的日志记录逻辑会生一个更可读的、实用的代码基础Q所以拦截器q泛用于日志记录。您很快׃看到Qؓ了处理横切关注点QSpring AOP 发布了它自己的拦截器Q您也可以编写您自己的拦截器?/p> <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> <table cellSpacing=0 cellPadding=0 border=0> <tbody> <tr> <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td> <td vAlign=top align=right><a class=fbox ><strong><font color=#996699><u>回页?/u></font></strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br><br></p> <p><a name=N100B3><span id="jnuhiuj" class=atitle><font size=4>整合 Struts ?Spring</font></span></a></p> <p>?Struts 怼QSpring 可以作ؓ一?MVC 实现。这两种框架都具有自q优点和缺点,管大部分h同意 Struts ?MVC 斚w仍然是最好的。很多开发团队已l学会在旉紧迫的时候利?Struts 作ؓ构造高品质软g的基。Struts h如此大的推动力,以至于开发团队宁愿整?Spring 框架的特性,而不愿意转换?Spring MVC。没必要q行转换Ҏ来说是一个好消息。Spring 架构允许您将 Struts 作ؓ Web 框架q接到基?Spring 的业务和持久层。最后的l果是现在一切条仉具备了?/p> <p>在接下来的小H门中,您将会了解到三种?Struts MVC 整合?Spring 框架的方法。我揭C每U方法的~陷q且Ҏ它们的优炏V?一旦您了解到所有三U方法的作用Q我会向您展示一个o人兴奋的应用E序Q这个程序用的是这三种Ҏ中我最喜欢的一U?/p> <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> <table cellSpacing=0 cellPadding=0 border=0> <tbody> <tr> <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td> <td vAlign=top align=right><a class=fbox ><strong><font color=#996699><u>回页?/u></font></strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br><br></p> <p><a name=N100BF><span id="xglluaq" class=atitle><font size=4>三个窍?/font></span></a></p> <p>接下来的每种整合技术(或者窍门)都有自己的优点和特点。我偏爱其中的一U,但是我知道这三种都能够加深您?Struts ?Spring 的理解。在处理各种不同情况的时候,q将l您提供一个广阔的选择范围。方法如下:</p> <ul> <li>使用 Spring ?<code>ActionSupport</code> cL?Structs <li>使用 Spring ?<code>DelegatingRequestProcessor</code> 覆盖 Struts ?<code>RequestProcessor </code> <li>?Struts <code>Action</code> 理委托l?Spring 框架 </li> </ul> <p><a name=N100E4><span id="etdszcy" class=smalltitle><strong><font size=3>装蝲应用E序环境</font></strong></span></a></p> <p>无论您用哪U技术,都需要?Spring ?<code>ContextLoaderPlugin</code> ?Struts ?<code>ActionServlet</code> 装蝲 Spring 应用E序环境。就像添加Q何其他插件一P单地向您?struts-config.xml 文gd该插Ӟ如下所C:</p> <p> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console"><plug-in className= "org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property= "contextConfigLocation" value="/WEB-INF/beans.xml"/> </plug-in> </font></code></pre> </td> </tr> </tbody> </table> <br></p> <p>前面已经提到q,?<a ><font color=#996699><u>下蝲</u></font></a> 部分Q您能够扑ֈq三个完全可使用的例子的完整源代码。每个例子都Z个书c搜索应用程序提供一U不同的 Struts ?Spring 的整合方法。您可以在这里看C子的要点Q但是您也可以下载应用程序以查看所有的l节?/p> <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> <table cellSpacing=0 cellPadding=0 border=0> <tbody> <tr> <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td> <td vAlign=top align=right><a class=fbox ><strong><font color=#996699><u>回页?/u></font></strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br><br></p> <p><a name=N10101><span id="dfxtmeo" class=atitle><font size=4>H门 1. 使用 Spring ?ActionSupport</font></span></a></p> <p>手动创徏一?Spring 环境是一U整?Struts ?Spring 的最直观的方式。ؓ了它变得更单,Spring 提供了一些帮助。ؓ了方便地获得 Spring 环境Q?code>org.springframework.web.struts.ActionSupport</code> cL供了一?<code>getWebApplicationContext()</code> Ҏ。您所做的只是?Spring ?<code>ActionSupport</code> 而不?Struts <code>Action</code> cL展您的动作,如清?1 所C:</p> <p><br><a name=N1011F><strong>清单 1. 使用 ActionSupport 整合 Struts</strong></a><br> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console">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 id="wjtznxl" class=boldcode><strong>|(1)</strong></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 id="mvcqhzg" class=boldcode><strong>|(2)</strong></span> BookService bookService = (BookService) ctx.getBean("bookService"); <span id="gekykxa" class=boldcode><strong>|(3)</strong></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"); } } </font></code></pre> </td> </tr> </tbody> </table> <br></p> <p>让我们快速思考一下这里到底发生了什么。在 (1) 处,我通过?Spring ?<code>ActionSupport</code> c而不?Struts ?<code>Action</code> c进行扩展,创徏了一个新?<code>Action</code>。在 (2) 处,我?<code>getWebApplicationContext()</code> Ҏ获得一?<code>ApplicationContext</code>。ؓ了获得业务服务,我用在 (2) 处获得的环境?(3) 处查找一?Spring bean?/p> <p>q种技术很单ƈ且易于理解。不q的是,它将 Struts 动作?Spring 框架耦合在一赗如果您x换掉 SpringQ那么您必须重写代码。ƈ且,׃ Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优ѝ当使用多重独立?Spring 环境Ӟq种技术可能有用,但是在大多数情况下,q种Ҏ不如另外两种Ҏ合适?/p> <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> <table cellSpacing=0 cellPadding=0 border=0> <tbody> <tr> <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td> <td vAlign=top align=right><a class=fbox ><strong><font color=#996699><u>回页?/u></font></strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br><br></p> <p><a name=N10149><span id="ouesgnx" class=atitle><font size=4>H门 2. 覆盖 RequestProcessor</font></span></a></p> <p>?Spring ?Struts 动作中分L一个更巧妙的设计选择。分ȝ一U方法是使用 <code>org.springframework.web.struts.DelegatingRequestProcessor</code> cL覆盖 Struts ?<code>RequestProcessor</code> 处理E序Q如清单 2 所C:</p> <p><br><a name=N1015F><strong>清单 2. 通过 Spring ?DelegatingRequestProcessor q行整合</strong></a><br> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console"><?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> <form-beans> <form-bean name="searchForm" type="org.apache.struts.validator.DynaValidatorForm"> <form-property name="isbn" type="java.lang.String"/> </form-bean> </form-beans> <global-forwards type="org.apache.struts.action.ActionForward"> <forward name="welcome" path="/welcome.do"/> <forward name="searchEntry" path="/searchEntry.do"/> <forward name="searchSubmit" path="/searchSubmit.do"/> </global-forwards> <action-mappings> <action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/> <action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/> <action path="/searchSubmit" type="ca.nexcel.books.actions.SearchSubmit" input="/searchEntry.do" validate="true" name="searchForm"> <forward name="success" path="/WEB-INF/pages/detail.jsp"/> <forward name="failure" path="/WEB-INF/pages/search.jsp"/> </action> </action-mappings> <message-resources parameter="ApplicationResources"/> <controller processorClass="org.springframework.web.struts. DelegatingRequestProcessor"/> <span id="ikqaoru" class=boldcode><strong>|(1)</strong></span> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/> </plug-in> </struts-config> </font></code></pre> </td> </tr> </tbody> </table> <br></p> <p>我利用了 <code><controller></code> 标记来用 <code>DelegatingRequestProcessor</code> 覆盖默认?Struts <code>RequestProcessor</code>。下一步是在我?Spring 配置文g中注册该动作Q如清单 3 所C:</p> <p><br><a name=N1017C><strong>清单 3. ?Spring 配置文g中注册一个动?/strong></a><br> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/> <bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit"> <span id="hxsgmhk" class=boldcode><strong>|(1)</strong></span> <property name="bookService"> <ref bean="bookService"/> </property> </bean> </beans> </font></code></pre> </td> </tr> </tbody> </table> <br></p> <p>注意Q在 (1) 处,我用名U属性注册了一?beanQ以匚w struts-config 动作映射名称?code>SearchSubmit</code> 动作揭示了一?JavaBean 属性,允许 Spring 在运行时填充属性,如清?4 所C:</p> <p><br><a name=N10191><strong>清单 4. h JavaBean 属性的 Struts 动作</strong></a><br> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console">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 id="wocxdgq" class=boldcode><strong>| (1)</strong></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 id="cuthvji" class=boldcode><strong>|(2)</strong></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"); } } </font></code></pre> </td> </tr> </tbody> </table> <br></p> <p>在清?4 中,您可以了解到如何创徏 Struts 动作。在 (1) 处,我创Z一?JavaBean 属性?code>DelegatingRequestProcessor</code>自动地配|这U属性。这U设计 Struts 动作q不知道它正?Spring 理Qƈ且您能够利?Sping 的动作管理框架的所有优炏V由于您?Struts 动作注意不到 Spring 的存在,所以您不需要重写您?Struts 代码可以用其他控制反转容器来替换?Spring?/p> <p><code>DelegatingRequestProcessor</code> Ҏ的确比第一U方法好Q但是仍然存在一些问题。如果您使用一个不同的 <code>RequestProcessor</code>Q则需要手动整?Spring ?<code>DelegatingRequestProcessor</code>。添加的代码会造成l护的麻烦ƈ且将来会降低您的应用E序的灵zL。此外,q有q一些用一pd命o来代?Struts <code>RequestProcessor</code> 的传闅R?q种改变会对这U解x法的使用寿命造成负面的媄响?/p> <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> <table cellSpacing=0 cellPadding=0 border=0> <tbody> <tr> <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td> <td vAlign=top align=right><a class=fbox ><strong><font color=#996699><u>回页?/u></font></strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br><br></p> <p><a name=N101B7><span id="kvqtzgu" class=atitle><font size=4>H门 3. 动作管理委托给 Spring</font></span></a></p> <p>一个更好的解决Ҏ是将 Strut 动作理委托l?Spring。您可以通过?<code>struts-config</code> 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查?Struts 动作。由于动作在 Spring 的控制之下,所以它可以填充动作?JavaBean 属性,qؓ应用诸如 Spring ?AOP 拦截器之cȝҎ带来了可能?</p> <p>清单 5 中的 <code>Action</code> cM清单 4 中的相同。但?struts-config 有一些不同:</p> <p><br><a name=N101D0><strong>清单 5. Spring 整合的委托方?/strong></a><br> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console"><?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> <form-beans> <form-bean name="searchForm" type="org.apache.struts.validator.DynaValidatorForm"> <form-property name="isbn" type="java.lang.String"/> </form-bean> </form-beans> <global-forwards type="org.apache.struts.action.ActionForward"> <forward name="welcome" path="/welcome.do"/> <forward name="searchEntry" path="/searchEntry.do"/> <forward name="searchSubmit" path="/searchSubmit.do"/> </global-forwards> <action-mappings> <action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/> <action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/> <action path="/searchSubmit" type="org.springframework.web.struts.DelegatingActionProxy" <span id="gcbhvyb" class=boldcode><strong>|(1)</strong></span> input="/searchEntry.do" validate="true" name="searchForm"> <forward name="success" path="/WEB-INF/pages/detail.jsp"/> <forward name="failure" path="/WEB-INF/pages/search.jsp"/> </action> </action-mappings> <message-resources parameter="ApplicationResources"/> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/> </plug-in> </struts-config> </font></code></pre> </td> </tr> </tbody> </table> <br></p> <p>清单 5 是一个典型的 struts-config.xml 文gQ只有一个小的差别。它注册 Spring 代理cȝ名称Q而不是声明动作的cdQ如Q?Q处所C。DelegatingActionProxy cM用动作映名U查?Spring 环境中的动作。这是我们使用 <code>ContextLoaderPlugIn</code> 声明的环境?/p> <p>一?Struts 动作注册Z?Spring bean 是非常直观的Q如清单 6 所C。我利用动作映射使用 <code><bean></code> 标记的名U属性(在这个例子中?"<code>/searchSubmit</code>"Q简单地创徏了一?bean。这个动作的 JavaBean 属性像M Spring bean 一栯填充Q?</p> <p><br><a name=N101F0><strong>清单 6. ?Spring 环境中注册一?Struts 动作</strong></a><br> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/> <bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit"> <property name="bookService"> <ref bean="bookService"/> </property> </bean> </beans> </font></code></pre> </td> </tr> </tbody> </table> <br><br> <table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td><font face="Lucida Console"><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></font></td> </tr> </tbody> </table> <table class=no-print cellSpacing=0 cellPadding=0 align=right> <tbody> <tr align=right> <td><font face="Lucida Console"><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br></font> <table cellSpacing=0 cellPadding=0 border=0> <tbody> <tr> <td vAlign=center><font face="Lucida Console"><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></font></td> <td vAlign=top align=right><a class=fbox ><strong><font color=#996699><u>回页?/u></font></strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br><br></p> <p><a name=N101F7><span id="hkjtzgu" class=atitle><font size=4>动作委托的优?/font></span></a></p> <p>动作委托解决Ҏ是这三种Ҏ中最好的。Struts 动作不了?SpringQ不对代码作M改变可用于?Spring 应用E序中?code>RequestProcessor</code> 的改变不会媄响它Qƈ且它可以利用 Spring AOP Ҏ的优点?</p> <p>动作委托的优点不止如此。一旦让 Spring 控制您的 Struts 动作Q您可以?Spring l动作补充更强的zd。例如,没有 Spring 的话Q所有的 Struts 动作都必LU程安全的。如果您讄 <code><bean></code> 标记?singleton 属性ؓ“false”Q那么不用何种ҎQ您的应用程序都在每一个请求上有一个新生成的动作对象。您可能不需要这U特性,但是把它攑֜您的工具׃也很好。您也可以利?Spring 的生命周期方法。例如,当实例化 Struts 动作Ӟ<code><bean></code> 标记?init-method 属性被用于q行一个方法。类似地Q在从容器中删除 bean 之前Qdestroy-method 属性执行一个方法。这些方法是理昂贵对象的好办法Q它们以一U与 Servlet 生命周期相同的方式进行管理?/p> <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> <table cellSpacing=0 cellPadding=0 border=0> <tbody> <tr> <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td> <td vAlign=top align=right><a class=fbox ><strong><font color=#996699><u>回页?/u></font></strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br><br></p> <p><a name=N10210><span id="ufymwoy" class=atitle><font size=4>拦截 Struts</font></span></a></p> <p>前面提到q,通过?Struts 动作委托l?Spring 框架而整?Struts ?Spring 的一个主要的优点是:您可以将 Spring ?AOP 拦截器应用于您的 Struts 动作。通过?Spring 拦截器应用于 Struts 动作Q您可以用最的代h处理横切x炏V?/p> <p>虽然 Spring 提供很多内置拦截器,但是我将向您展示如何创徏自己的拦截器q把它应用于一?Struts 动作。ؓ了用拦截器Q您需要做三g事:</p> <ol> <li>创徏拦截器? <li>注册拦截器? <li>声明在何处拦截代码?</li> </ol> <p>q看h非常单的几句话却非常强大。例如,在清?7 中,我ؓ Struts 动作创徏了一个日志记录拦截器?q个拦截器在每个Ҏ调用之前打印一句话Q?/p> <p><br><a name=N10230><strong>清单 7. 一个简单的日志记录拦截?/strong></a><br> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console">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!"); } } </font></code></pre> </td> </tr> </tbody> </table> <br></p> <p>q个拦截器非常简单?code>before()</code> Ҏ在拦截点中每个方法之前运行。在本例中,它打印出一句话Q其实它可以做您惛_的Q何事。下一步就是在 Spring 配置文g中注册这个拦截器Q如清单 8 所C:</p> <p><br><a name=N10242><strong>清单 8. ?Spring 配置文g中注册拦截器</strong></a><br> <table cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1> <tbody> <tr> <td> <pre><code class=section> <font face="Lucida Console"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/> <bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit"> <property name="bookService"> <ref bean="bookService"/> </property> </bean> <!-- Interceptors --> <bean name="logger" class="ca.nexcel.books.interceptors.LoggingInterceptor"/> <span id="frdgmea" class=boldcode><strong>|(1)</strong></span> <!-- AutoProxies --> <bean name="loggingAutoProxy" class="org.springframework.aop.framework.autoproxy. BeanNameAutoProxyCreator"> <span id="itguazg" class=boldcode><strong>|(2)</strong></span> <property name="beanNames"> <value>/searchSubmit</valuesgt; <span id="szjidvf" class=boldcode><strong>|(3)</strong></span> </property> <property name="interceptorNames"> <list> <value>logger</value> <span id="phkfawv" class=boldcode><strong>|(4)</strong></span> </list> </property> </bean> </beans> </font></code></pre> </td> </tr> </tbody> </table> <br></p> <p>您可能已l注意到了,清单 8 扩展?<a ><font color=#996699><u>清单 6</u></font></a> 中所C的应用E序以包含一个拦截器。具体细节如下:</p> <ul> <li>?(1) 处,我注册了q个拦截器? <li>?(2) 处,我创Z一?bean 名称自动代理Q它描述如何应用拦截器。还有其他的Ҏ定义拦截点,但是q种Ҏ常见而简ѝ? <li>?(3) 处,我将 Struts 动作注册为将被拦截的 bean。如果您惌拦截其他?Struts 动作Q则只需要在 "beanNames" 下面创徏附加?<code><value></code> 标记? <li>?(4) 处,当拦截发生时Q我执行了在 (1) 处创建的拦截?bean 的名U。这里列出的所有拦截器都应用于“beanNames”?</li> </ul> <p>是q样。就像这个例子所展示的,您?Struts 动作|于 Spring 框架的控制之下,为处理您?Struts 应用E序提供了一pd全新的选择。在本例中,使用动作委托可以L地利?Spring 拦截器提?Struts 应用E序中的日志记录能力?/p> <img src ="http://www.tkk7.com/xixidabao/aggbug/112404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/xixidabao/" target="_blank">JAVA之\</a> 2007-04-21 10:43 <a href="http://www.tkk7.com/xixidabao/archive/2007/04/21/112404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Observer http://www.tkk7.com/xixidabao/archive/2007/04/18/111546.htmlJAVA之\JAVA之\Wed, 18 Apr 2007 03:14:00 GMThttp://www.tkk7.com/xixidabao/archive/2007/04/18/111546.html设计模式之Observer

Java深入C定程?׃可避免的到设计模式(design pattern)q一概念,了解设计模式,自己对java中的接口或抽象类应用有更q理解.设计模式在java的中型系l中应用q泛,遵@一定的~程模式,才能使自q代码便于理解,易于交流,Observer(观察?模式是比较常用的一个模?其在界面设计中应用q泛,而本站所x的是Java在电子商务系l中应用,因此想从电子商务实例中分析Observer的应?

虽然|上商店形式多样,每个站点有自q特色,但也有其一般的共?单就"商品的变?以便及时通知订户"q一?是很多网上商店共有的模式,q一模式cMObserver patern.

具体的说,如果|上商店中商品在名称 h{方面有变化,如果pȝ能自动通知会员,是|上商店区别传统商店的一大特?q就需要在商品product中加入Observerq样角色,以便productl节发生变化?Observer能自动观察到q种变化,q能q行及时的update或notify动作.

Java的APIqؓ为我们提供现成的Observer接口Java.util.Observer.我们只要直接使用它就可以.

我们必须extends Java.util.Observer才能真正使用?
1.提供Add/Delete observer的方?
2.提供通知(notisfy) 所有observer的方?

import java.util.Observable;

public class product extends Observable {

 private String name;

 private float price;
 public product(){
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
  //讄变化?
  setChanged();
  notifyObservers(name);

 }

 public float getPrice() {
  return price;
 }

 public void setPrice(float price) {
  this.price = price;
  //讄变化?br>  setChanged();
  notifyObservers(new Float(price));

 }

 //以下可以是数据库更新 插入命o.
 public void saveToDb() {
  //  .....................

 }

 public static void main(String[] args) {
  product p=new product();
  p.addObserver(new NameObserver());
  p.addObserver(new PriceObserver());
  p.setPrice(100);
  p.setName("name");
 }
}


我们注意?在productcM 的setXXXҎ?我们讄?notify(通知)Ҏ, 当调用setXXX,实际上就触发了notisfyObserversҎ,q将通知相应观察者应该采取行动了.

下面看看q些观察者的代码,他们I竟采取了什么行?

//观察者NameObserver主要用来对品名U?name)q行观察?br>public class NameObserver implements Observer{

  private String name=null;

  public void update(Observable obj,Object arg){

    if (arg instanceof String){

     name=(String)arg;
     //产品名称改变值在name?br>     System.out.println("NameObserver :name changet to "+name);

    }

  }

}

//观察者PriceObserver主要用来对品h?price)q行观察?br>public class PriceObserver implements Observer{

  private float price=0;

  public void update(Observable obj,Object arg){

    if (arg instanceof Float){

     price=((Float)arg).floatValue();
  
     System.out.println("PriceObserver :price changet to "+price);

    }

  }

}

输出l果如下Q?br>PriceObserver :price changet to 100.0
NameObserver :name changet to name

转自Q?a href="http://www.tkk7.com/Sprite-bei/archive/2007/04/16/110976.html">http://www.tkk7.com/Sprite-bei/archive/2007/04/16/110976.html

JAVA之\ 2007-04-18 11:14 发表评论
]]>
Struts,Spring,Hibernate优缺?http://www.tkk7.com/xixidabao/archive/2007/04/14/110605.htmlJAVA之\JAVA之\Sat, 14 Apr 2007 02:38:00 GMThttp://www.tkk7.com/xixidabao/archive/2007/04/14/110605.html
struts框架hlg的模块化Q灵zL和重用性的优点Q同时简化了ZMVC的web应用E序的开发?br>
优点Q?br>Struts跟Tomcat、Turbine{诸多Apache目一P是开源YӞq是它的一大优炏V开发者能更深入的了解其内部实现机制?br>除此之外QStruts的优点主要集中体现在两个斚wQTaglib和页面导航。Taglib是Struts的标记库Q灵zd用,能大大提高开发效率。另外,q前国内的JSP开发者而言Q除了用JSP自带的常用标记外Q很开发自q标记Q或许Struts是一个很好的L?br>关于面DQ我认ؓ那将是今后的一个发展方向,事实上,q样做,使系l的脉络更加清晰。通过一个配|文Ӟ卛_把握整个pȝ各部分之间的联系Q这对于后期的维护有着莫大的好处。尤其是当另一批开发者接手这个项目时Q这U优势体现得更加明显?br>

另外Qstruts是业?标准"Q很多成功案例)Q学习资源丰富,HTML标签非常优秀

~点Q?br>Taglib是Struts的一大优势,但对于初学者而言Q却需要一个持l学习的q程Q甚臌会打׃|页~写的习惯,但是Q当你习惯了它时Q你会觉得它真的很棒?br>StrutsMVC的Controller一分ؓ三,在获得结构更加清晰的同时Q也增加了系l的复杂度?br>ActionForms使用不便、无法进行单元测试(StrutsTestCase只能用于集成Q?br>

【IT168技术文?/strong>?
    Struts跟Tomcat、Turbine{诸多Apache目一P是开源YӞq是它的一大优炏V开发者能更深入的了解其内部实现机制?Struts开放源码框架的创徏是ؓ了开发者在构徏ZJava Servlet和JavaServer PagesQJSPQ技术的Web应用时更加容易。Struts框架为开放者提供了一个统一的标准框Ӟ通过使用Struts作ؓ基础Q开发者能够更专注于应用程序的商业逻辑。Struts框架本n是用Java Servlet和JavaServer Pages技术的一UModel-View-ControllerQMVCQ实?
具体来讲,Struts的优Ҏ: 

    1. 实现MVC模式Q结构清?使开发者只x业务逻辑的实? 

    2. 有丰富的tag可以?,Struts的标记库(Taglib)Q如能灵zd用,则能大大提高开发效率。另外,q前国内的JSP开发者而言Q除了用JSP自带的常用标记外Q很开发自q标记Q或许Struts是一个很好的L?nbsp;

    3. 面D.面D是今后的一个发展方向,事实上,q样做,使系l的脉络更加清晰。通过一个配|文Ӟ卛_把握整个pȝ各部分之间的联系Q这对于后期的维护有着莫大的好处。尤其是当另一批开发者接手这个项目时Q这U优势体现得更加明显?nbsp;

    4. 提供Exception处理机制 . 

    5. 数据库链接池理 

    6. 支持I18N 

    ~点: 
    一?转到展示层时Q需要配|forwardQ每一ơ{到展C层Q相信大多数都是直接转到jspQ而涉及到转向Q需要配|forwardQ如果有十个展示层的jspQ需要配|十ơstrutsQ而且q不包括有时候目录、文件变_需要重C改forwardQ注意,每次修改配置之后Q要求重新部|整个项目,而tomcateq样的服务器Q还必须重新启动服务器,如果业务变更复杂频繁的系l,q样的操作简单不可想象。现在就是这P几十上百个h同时在线使用我们的系l,大家可以惌一下,我的烦恼有多大?br> 
    二?Struts 的Action必需是threadQsafe方式Q它仅仅允许一个实例去处理所有的h。所以action用到的所有的资源都必需l一同步Q这个就引v了线E安全的问题?nbsp;

    三?试不方? Struts的每个Action都同Web层耦合在一Pq样它的试依赖于Web容器Q单元测试也很难实现。不q有一个Junit的扩展工具Struts TestCase可以实现它的单元试?nbsp;

    四?cd的{? Struts的FormBean把所有的数据都作为StringcdQ它可以使用工具Commons-Beanutilsq行cd转化。但它的转化都是在ClassU别Q而且转化的类型是不可配置的。类型{化时的错误信息返回给用户也是非常困难的?nbsp;

    五?对Servlet的依赖性过? Struts处理Action时必需要依赖ServletRequest 和ServletResponseQ所有它摆脱不了Servlet容器?nbsp;

    六?前端表达式语a斚w.Struts集成了JSTLQ所以它主要使用JSTL的表辑ּ语言来获取数据。可是JSTL的表辑ּ语言在Collection和烦引属性方面处理显得很弱?nbsp;

    七?对Action执行的控制困? Struts创徏一个ActionQ如果想控制它的执行序会非常困难。甚至你要重新去写Servlet来实C的这个功能需求?nbsp;

    八?对Action 执行前和后的处理. Struts处理Action的时候是Zclass的hierarchiesQ很隑֜action处理前和后进行操作?nbsp;

    九?对事件支持不? 在struts中,实际是一个表单Form对应一个Actionc?或DispatchAction)Q换一句话_在Struts中实际是一个表单只能对应一个事Ӟstrutsq种事g方式UCؓapplication eventQapplication event和component event相比是一U粗_度的事件?nbsp;
    
    Struts重要的表单对象ActionForm是一U对象,它代表了一U应用,q个对象中至包含几个字D,q些字段是Jsp面表单中的input字段Q因Z个表单对应一个事Ӟ所以,当我们需要将事g_度l化到表单中q些字段Ӟ也就是说Q一个字D对应一个事件时Q单U用Struts׃太可能,当然通过l合JavaScript也是可以转弯实现的?br>



2QHibernate
Hibernate是一个开放源代码的对象关pL框Ӟ它对JDBCq行了非常轻量的对象封装,使得JavaE序员可以随心所Ʋ的使用对象~程思维来操U|据库?br>Hibernate可以应用在Q何用JDBC的场合,既可以在Java的客LE序实用Q也可以在Servlet/JSP的Web应用中用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMPQ完成数据持久化的重仅R?br>大多数开发机构经帔R取创建各自独立的数据持久层。一旦底层的数据l构发生改变Q那么修改应用的其余部分使之适应q种改变的代价将是十分巨大的。Hibernate适时的填补了q一I白Q它为Java应用提供了一个易用的、高效率的对象关pL框架。hibernate是个轻量U的持久性框Ӟ功能却非怸富?br>
优点Q?br>a.??????? Hibernate 使用 Java 反射机制 而不是字节码增强E序来实现透明性?br>b.??????? ?Hibernate 的性能非常好,因ؓ它是个轻量框架?映射的灵zL很?br>c.??????? 它支持各U关pL据库Q从一对一到多对多的各U复杂关pR?


~点Q它限制您所使用的对象模型?例如Q一个持久性类不能映射到多个表)其独有的界面和可怜的市场份额也让Z安,管如此QHibernate q是以其强大的发展动力减Mq些风险。其他的开源持久性框架也有一些,不过都没?Hibernate q样有市场冲d?br>
上面回脓情A有点Ȁ动,希望谅解Q我不是因ؓ有h批评Hibernate而感C快,而是因ؓ帖子里面的观点实在让我觉得荒谬。不觉得Hibernate好也吧,不好也吧Q我唯一觉得遗憾的是Q在中文论坛里面找不C个对Hibernate的真正高水^的评仗在TSS上有一个关于Hibernate的hot threadQ跟了几百脓Q其中包括Hibernate作者Gavin和LiDO JDO的CTOQ对于JDO和Hibernate有过一些激烈的争论Q我曄耐心的看了一遍,仍然没有发现针对Hibernate真正有力的攻击,那些所谓的d无非针对Hibernate没有一个GUI的配|工P没有商业公司支持Q没有标准化{等q些站不住脚的理由?br>
补充几点我的意见Q?br>
一、Hibernate是JDBC的轻量的对象封装,它是一个独立的对象持久层框Ӟ和App ServerQ和EJB没有什么必然的联系。Hibernate可以用在MJDBC可以使用的场合,例如Java应用E序的数据库讉K代码QDAO接口的实现类Q甚臛_以是BMP里面的访问数据库的代码。从q个意义上来_Hibernate和EB不是一个范畴的东西Q也不存在非此即彼的关系?br>
二、Hibernate是一个和JDBC密切兌的框Ӟ所以Hibernate的兼Ҏ和JDBC驱动Q和数据库都有一定的关系Q但是和使用它的JavaE序Q和App Server没有M关系Q也不存在兼Ҏ问题?br>
三、Hibernate不能用来直接和Entity Bean做对比,只有攑֜整个J2EE目的框架中才能比较。ƈ且即使是攑֜软g整体框架中来看,Hibernate也是做ؓJDBC的替代者出现的Q而不是Entity Bean的替代者出现的Q让我再列一ơ我已经列nơ的框架l构Q?br>
传统的架构:
1) Session Bean <-> Entity Bean <-> DB
Z解决性能障碍的替代架构:
2) Session Bean <-> DAO <-> JDBC <-> DB
使用Hibernate来提高上面架构的开发效率的架构Q?br>3) Session Bean <-> DAO <-> Hibernate <-> DB

׃?个架构来分析Q?br>1、内存消耗:采用JDBC的架?无疑是最省内存的QHibernate的架?ơ之QEB的架?最差?br>
2、运行效率:如果JDBC的代码写的非怼化,那么JDBC架构q行效率最高,但是实际目中,q一点几乎做不到Q这需要程序员非常_NJDBCQ运用Batch语句Q调整PreapredStatement的Batch Size和Fetch Size{参敎ͼ以及在必要的情况下采用结果集cache{等。而一般情况下E序员是做不到这一点的。因此Hibernate架构表现出最快的q行效率。EB的架构效率会差的很远?br>
3、开发效率:在有JBuilder的支持下以及单的目QEB架构开发效率最高,JDBCơ之QHibernate最差。但是在大的目Q特别是持久层关pL很复杂的情况下QHibernate效率高的惊hQJDBCơ之Q而EB架构很可能会p|?br>
4、分布式Q安全检查,集群Q负载均衡的支持
׃有SB做ؓFacadeQ?个架构没有区别?br>
四、EB和Hibernate学习隑ֺ在哪里?

EB的难度在哪里Q不在复杂的XML配置文g上,而在于EBq用E微不慎Q就有严重的性能障碍。所以难在你需要学习很多EJB设计模式来避开性能问题Q需要学习App Server和EB的配|来优化EB的运行效率。做EB的开发工作,E序员的大部分精力都被放CEB的性能问题上了Q反而没有更多的_֊x本n׃要投入精力去考虑的对象持久层的设计上来?br>
Hibernate隑֜哪里Q不在Hibernate本n的复杂,实际上Hibernate非常的简单,隑֜Hibernate太灵zM?br>
当你用EB来实现持久层的时候,你会发现EB实在是太W拙了,W拙CҎ没有什么可以选择的余圎ͼ所以你Ҏ׃用花费精力去设计ҎQ去qҎ的好坏,去费脑筋考虑选择哪个ҎQ因为只有唯一的方案摆在你面前Q你只能q么做,没得选择?br>
Hibernate相反Q它太灵zMQ相同的问题Q你臛_可以设计出十几种Ҏ来解冻I所以特别的犯难Q究竟用q个Q还是用那个呢?q些Ҏ之间到底有什么区别呢Q他们的q行原理有什么不同?q行效率哪个比较好?光是主键生成Q就有七八种Ҏ供你选择Q你为难不ؓ难?集合属性可以用SetQ可以用ListQ还可以用BagQ到底哪个效率高Q你为难不ؓ难?查询可以用iteratorQ可以用listQ哪个好Q有什么区别?你ؓ难不为难Q复合主键你可以直接在hbm里面配置Q也可以自定义CustomerTypeQ哪U比较好些?你ؓ难不为难Q对于一个表Q你可以选择单一映射一个对象,也可以映成父子对象Q还可以映射成两?:1的对象,在什么情况下用哪U方案比较好Q你为难不ؓ难?

q个列表可以一直开列下去,直到你不惛_看下Mؓ止。当你面前摆着无数的眼q݋qҎ的时候,你会觉得q福呢?q是悲哀呢?如果你是一个负责的E序员,那么你一定会仔细研究每种Ҏ的区别,每种Ҏ的效率,每种Ҏ的适用场合Q你会觉得你已经陷入q去拔不出来了。如果是用EBQ你W一U种已l做Z军_Q根本没得选择Q比如说集合属性,你只能用CollectionQ如果是HibernateQ你会在BagQList和Set之间来回犹U不决Q甚x不清楚的话,E序都没有办法写?br>





3Q?Spring
它是一个开源的目Q而且目前非常z跃Q它ZIoCQInversion of ControlQ反向控Ӟ和AOP的构架多层j2eepȝ的框Ӟ但它不强q你必须在每一?中必M用SpringQ因为它模块化的很好Q允怽Ҏ自己的需要选择使用它的某一个模块;它实C很优雅的MVCQ对不同的数据访问技术提供了l一?接口Q采用IoC使得可以很容易的实现bean的装配,提供了简z的AOPq据此实现Transcation ManagmentQ等{?br>优点
? ?a. Spring能有效地l织你的中间层对象,不管你是否选择使用了EJB。如果你仅仅使用了Struts或其他ؓJ2EE?API特制的frameworkQSpring致力于解军_下的问题?
? ?b. Spring能消除在许多工程中常见的对Singleton的过多用。根据我的经验,q是一个很大的问题Q它降低了系l的可测试性和面向对象的程度?
? ?c. 通过一U在不同应用E序和项目间一致的Ҏ来处理配|文ӞSpring能消除各U各栯定义格式的属性文件的需要。曾l对某个c要L的是哪个法般的属性项或系l属性感C解,为此不得不去读Javadoc甚至源编码?有了SpringQ你仅仅需要看看类的JavaBean属性。Inversion of Control的用(在下面讨论)帮助完成了这U简化?
??d.? 通过把对接口~程而不是对cȝE的代h几乎减少到没有,Spring能够促进L好的~程习惯?
??e. Spring被设计ؓ让用它创徏的应用尽可能的依赖于他的APIs。在Spring应用中的大多C务对象没有依赖于Spring?
??f. 使用Spring构徏的应用程序易于单元测试?
??g.? Spring能EJB的用成Z个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实C务接口,却不会媄响调用代码?
??h. Spring帮助你解册多问题而无需使用EJB。Spring能提供一UEJB的替换物Q它们适用于许多web应用。例如,Spring能用AOP提供声明性事务管理而不通过EJB容器Q如果你仅仅需要与单个数据库打交道Q甚至不需要一个JTA实现?
? i. ?Spring为数据存取提供了一个一致的框架,不论是用的是JDBCq是O/R mapping产品Q如HibernateQ?
Spring实使你能通过最单可行的解决办法来解决你的问题。而这是有有很大h值的?br>
?~点Q用hC多、jsp中要写很多代码、控制器q于灉|Q缺一个公用控制器

JAVA之\ 2007-04-14 10:38 发表评论
]]>
设计模式Q用Java动态代理实现AOP http://www.tkk7.com/xixidabao/archive/2007/04/08/109208.htmlJAVA之\JAVA之\Sun, 08 Apr 2007 02:55:00 GMThttp://www.tkk7.com/xixidabao/archive/2007/04/08/109208.html 设计模式Q用Java动态代理实现AOP http://www.itisedu.com   2006-12-7 15:08:52   中科永联 [关键字]设计模式 Java 动?代理 AOP 目前整个开发社区对AOP(Aspect Oriented Programing)推崇备至Q也涌现出大量支持AOP的优UFramework,--Spring, JACJboss AOP {等。AOPg一时之间成了潮。Java初学者不要发出感慨Q?a target=_new>OOPq没有学通呢Q又来AOP。本文不是要在理Z具体阐述何ؓAOP, Z要进行AOP . 要详l了解学习AOP可以到它老家http://aosd.netȝ瞧。这里只是意N过一个简单的例子向初学者展CZ下如何来q行AOP.

  Z单v见,例子没有没有使用MW三方的AOP Framework, 而是利用Java语言本n自带的动态代理功能来实现AOP. 

  让我们先回到AOP本nQAOP主要应用于日志记录,性能l计Q安全控?事务处理{方面。它的主要意囑ְ要将日志记录Q性能l计Q安全控制等{代码从商业逻辑代码中清楚的划分出来Q我们可以把q些行ؓ一个一个单独看作系l所要解决的问题Q就是所谓的面向问题的编E?不知AOP译作面向问题的编E是否欠?。通过对这些行为的分离Q我们希望可以将它们独立地配|到商业Ҏ中,而要改变q些行ؓ也不需要媄响到商业Ҏ代码?nbsp;

  假设pȝ׃pd的BusinessObject所完成业务逻辑功能Q系l要求在每一ơ业务逻辑处理时要做日志记录。这里我们略d体的业务逻辑代码?nbsp;

public interface BusinessInterface { 
 public void processBusiness(); 


public class BusinessObject implements BusinessInterface { 
 private Logger logger = Logger.getLogger(this.getClass().getName()); 
 public void processBusiness(){ 
  try { 
   logger.info("start to processing..."); 
   //business logic here. 
   System.out.println(“here is business logic”); 
   logger.info("end processing..."); 
  } catch (Exception e){ 
   logger.info("exception happends..."); 
   //exception handling 
  } 
 } 


  q里处理商业逻辑的代码和日志记录代码混合在一Pq给日后的维护带来一定的困难Qƈ且也会造成大量的代码重复。完全相同的log代码出现在pȝ的每一个BusinessObject中?nbsp;

按照AOP的思想Q我们应该把日志记录代码分离出来。要这些代码分d涉及C个问题,我们必须知道商业逻辑代码何时被调用,q样我们好插入日志记录代码。一般来说要截获一个方法,我们可以采用回调Ҏ或者动态代理。动态代理一般要更加灉|一些,目前多数的AOP Framework也大都采用了动态代理来实现。这里我们也采用动态代理作Z子?nbsp;

  JDK1.2以后提供了动态代理的支持Q?a target=_new>E序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理器Q然后通过java.lang.reflect.Proxy得到一个代?a target=_new>对象Q通过q个代理对象来执行商业方?在商业方法被调用的同Ӟ执行处理器会被自动调用?nbsp;

  有了JDK的这U支持,我们所要做的仅仅是提供一个日志处理器?nbsp;

public class LogHandler implements InvocationHandler { 

 private Logger logger Q?nbsp;Logger.getLogger(this.getClass().getName()); 
  private Object delegate; 
  public LogHandler(Object delegate){ 
   this.delegate = delegate; 
  } 

 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
  Object o = null; 
  try { 
   logger.info("method stats..." Q?nbsp;method); 
   o = method.invoke(delegate,args); 
   logger.info("method ends..." + method); 
  } catch (Exception e){ 
   logger.info("Exception happends..."); 
   //excetpion handling. 
  } 
  return o; 
 } 


  现在我们可以把BusinessObject里面的所有日志处理代码全部去掉了?nbsp;

public class BusinessObject implements BusinessInterface { 

 private Logger logger = Logger.getLogger(this.getClass().getName()); 
 public void processBusiness(){ 
  //business processing 
  System.out.println(“here is business logic”); 
 } 


  客户?/font>调用商业Ҏ的代码如下:

BusinessInterface businessImp = new BusinessObject(); 

InvocationHandler handler = new LogHandler(businessImp); 

BusinessInterface proxy = (BusinessInterface) Proxy.newProxyInstance( 
 businessImp.getClass().getClassLoader(), 
 businessImp.getClass().getInterfaces(), 
 handler); 

proxy.processBusiness(); 

  E序输出如下Q?nbsp;

INFO: method stats... 
here is business logic 
INFO: method ends... 

  x我们的第一ơ小试是完成了。可以看刎ͼ采用AOP之后Q日志记录和业务逻辑代码完全分开了,以后要改变日志记录的话只需要修Ҏ志记录处理器p了,?a target=_new>业务对象本nQBusinessObjectQ无需做Q何修攏Vƈ且这个日志记录不会造成重复代码了,所有的商业处理对象都可以重用这个日志处理器?nbsp;

  当然在实际应用中Q这个例子就昑־太粗p了。由于JDK的动态代理ƈ没有直接支持一ơ注册多个InvocationHandlerQ那么我们对业务处理Ҏ既要日志记录又要性能l计Ӟ需要自己做一些变通了。一般我们可以自己定义一个Handler接口Q然后维护一个队列存放所有Handler, 当InvocationHandler被触发的时候我们依ơ调用自qHandler。所q的是目前几乎所有的AOP Framework都对q方面提供了很好的支?q里推荐大家使用Spring? 来源Q赛q网论坛 中科永联高技术培训中心本着技术交、共享精,部分信息资料为网上收集,如果本页内容늊了您的版权,L刻通知我们Q我们将?个工作日内作出妥善处理,q向您致以诚挚的歉意?

JAVA之\ 2007-04-08 10:55 发表评论
]]>
模式与J2EE http://www.tkk7.com/xixidabao/archive/2007/04/08/109205.htmlJAVA之\JAVA之\Sun, 08 Apr 2007 02:42:00 GMThttp://www.tkk7.com/xixidabao/archive/2007/04/08/109205.html 模式与J2EE http://www.itisedu.com   2006-5-12 15:56:28   中科永联 [关键字]模式 J2EE


信息工程是以当前数据pȝ为基Q在一个企业或企业的主要部门,关于信息pȝ的规 划、分析、设计和构成的一整套怺兌的正规化、自动化的技术应用?

 

--- JAMES Martin 

    正如上面信息工程的创始hJames MartinZ息工E的概念所做定?a target=_new>c?/font>|模式(patterns)的创始h建筑师ChriSTopher Alexander?lt;模式语言Q?977?979>一书中Ҏ式的概念q行了如下描q?附注Q书名后面的q䆾代表在各个不同时期的作品Q下面Ş式同?Q?br>每一个模式描qC一个在我们周围不断重复发生的问题,以及该问题的解决Ҏ的核心。这P你就能一ơ又一ơ的使用该解x案而不必做重复力_。每个模式是׃部分l成的一个规则,q个规则描述特定环境、问题和解决Ҏ之间的关pR简单的_没有一个模式是独立的实体,每个模式都存在着怺支持Q但支持的程度不同:大的模式可以内嵌的模式Q同{层ơ的模式q列存在Q而小的模式被嵌入到大的模式之中?
--- Christopher Alexander  
    模式的概念在软g行业被采用以后,得到的广泛的发展Q现在已l存在许多种cd的模式应用,其中比较有名的箸作有Q?a target=_new>GoF(Erich GAmma、Richard Helm、Ralph Johnson和John VlissIDEs四hQ简UͼGang of Four[GoF])?lt;设计模式Q?995>QMartin Fowler?lt;分析模式Q?997>QFrank Buschmann{h?lt;体系l构模式Q?996?000>、Jim O.Coplien、Niel Harrison{h?lt;~程模式Q?995?996?998?999>和Deepak Alur{h?lt;J2EE核心模式Q?001>{,其中最具媄响的是GoF?lt;设计模式>一书,书中详细讨论了三U类型,?3U模式。好的设计源于工作中l验的积累,当设计用标准的模板以模式的方式q行交流Ӟ模式成了交和重用的强大机Ӟq且可以改善设计和开发Y件的方式。模式可以帮助我们在一个特定的环境里整理ƈ记录已知的可重现的问题及解决ҎQƈ且通过模式来与他h交流q些知识Q这些模式可以解军_不同环境中重复出现的问题。模式可以设计重复使用Q重复用已知的解决Ҏ可以~短设计和开发应用的周期Q有效的使用模式Q可以我们q离重复投资的怪圈。模式的关键在于单性和可重现性?br>    举一个模式应用的单示例。例如,在你的便携式电脑上运行一个进E中?a target=_new>对象Qƈ且这些对象需要和q行在另一q程中的别的对象通信Q也许这一q程q不在你的便携式电脑上,而在别的地方。你又不惌pȝ中的对象担心如何扑֯|上的其他对象或者执?a target=_new>q程q程调用。这Ӟ可以使用代理(Proxy模式Q详见GoF?lt;设计模式>一?模式来解册个问题,你能做的事就是ؓq个q程对象在你的本地过E中建立一个代理对象,该代理对象和q程对象h相同的接口。你的本地对象利用通常处理q程中的消息发送来和代理交谈。这时代理对象负责把消息传送给实在对象Q而不实在对象位于何处?br>    ׃下面要讲的Java 2q_的企业版(J2EE)应用模式中很多用C设计模式?a target=_new>重构(Refactoring)的概念,所以在此有必要再概要介l一下重构的概念。重构已l被证明可以L软g的腐朽和衰|Q关于重构方面的有名怽当然首推是Martin Fowler所写的<重构Q?999>一书了Q书中详l介l了重构的七大类型,?0余种具体的重构手法,同时也指出测试机制在重构中的重要性。书中Martin Fowler寚w构的概念q行了详l说明:
    重构是对软g内部l构的一U调_目地是在不改变[软g之可察行为]的前提下Q提高其可理解性,降低其修Ҏ本。重构是一U有U律的、经q训l的、有条不紊的E序整理ҎQ可以将整理q程中不心引入的错误的机率降到最低,本质上说Q重构就是在代码写好之后改进它的设计。重构之前,首先查自己是否有一套可靠的试机制Q这些测试必L我检验能力?/p>


--- Martin Fowler 

    建立于Java~程语言和Java技术基之上的J2EEq_是最适用于企业分布式环境的应用l构Q它被设计ؓ面向多层体系的结构。J2EE包含下面关键技术:Java服务器页?Java Service PageQJSP)?a target=_new>Servlet?a target=_new>Enterprise JavaBeans(EJB)lg?a target=_new>Java消息服务(Java Message ServiceQ?a target=_new>JMS)?a target=_new>JDBC和Java命名与目录接?Java Naming and DIrECtory InterfaceQJNDI)。由于J2EEq_?a target=_new>分层pȝQ所以我们将J2EE的层ơ模型化Q这个模型得我们将职责逻辑地分C同的层中Q共分了五个层次Q客户层、表C层、业务层、集成层和资源层。因为客户层和资源层q不是J2EEq_直接x的问题,所以后面介l的15个J2EE应用模式全部属于上面五层中的中间三层Q其中表C层模式包含与Servlet和JSP技术相关的模式、业务层模式包含与EJB技术有关的模式、集成层模式包含与JMS和JDBC有关的模式。具体模式可参看下面表格Q?/p>

表一Q表C层模式
模式?/strong> 单描q?/strong>
截取qo?Intercepting Filter) 促进h的预先处理和后处?/td>
前端控制?Front Controller) 提供h处理的集中控制器
视图助手(View Helper) 把与表示层格式化无关的逻辑装到助手组?/td>
复合视图(CompOSite View) 从原子的子组件创Z个聚集视?/td>
工作者服?Service To Worker) 合ƈ分发者组件、前端控制器和视囑֊手模?/td>
分发者视?Dispatcher View) 合ƈ分发者组件、前端控制器和视囑֊手模式,把许多动作推q到视图处理


表二Q业务层模式
模式?/strong> 单描q?/strong>
业务委托(Business Delegate) 把表C层和服务层分隔开Qƈ且提供服务的外观和代理接?/td>
值对?Value object) 通过减少|络对话Q以加速层之间的数据交?/td>
会话外观(Session Facade) 隐藏业务对象复性,集中?a target=_new>工作?/font>处理
复合实体(Composite Entity) 通过把参数相关的对象分组q单个实体beanQ表C计粗_度实体bean的最好经?/td>
值对象组装器(Value Object ASsembler) 把来自多个数据源的值对象组装成一个复合值对?/td>
值列表处理器(Value List Handler) 理查询执行、结果缓册Ӏ以及结果处?/td>
服务定位?Service Locator) 装业务服务查找和创建的复杂性,定位业务服务工厂


表三Q集成层模式
模式?/strong> 单描q?/strong>
数据讉K对象(Data Access Object) 抽象数据源,提供Ҏ据的透明讉K
服务Ȁ发器(Service Activator) 加速EJBlg的异步处?/td>

    ׃J2EE模式众多Q篇q有限,q里只概要介l其中的一U应用模?- 集成层的数据讉K对象(DAO)模式Q有兴趣的读者可以参看下面参考文献中的资料?br>数据讉K对象模式

 数据讉K对象模式

1、问?br>    Ҏ数据源不同,数据讉K也不同。根据存储的cd(关系数据?/font>?a target=_new>面向对象数据库等)和供应商不同Q持久性存?比如数据?的访问差别也很大。当业务lg(如会话bean)或表C组?如助手组?需要访问某数据源时Q它们可以用合适的API来获得连接性,以及操作该数据源。但是在q些lg中包含连接性和数据讉K代码会引入这些组件及数据源实C间的紧密耦合。组件中q类代码依赖性应用E序从某U数据源q移到其它种cȝ数据源将变得非常ȝ和困难,当数据源变化Ӟlg也需要改变,以便于能够处理新cd的数据源?/p>

2、解x?br>    使用数据讉K对象(DAO)来抽象和装所有对数据源的讉K。DAO理着与数据源的连接以便于索和存储数据QDAO实现了用来操作数据源的访问机制。依赖于DAO的业务组件ؓ?a target=_new>客户?/font>使用DAO提供了更单的接口QDAO完全向客L隐藏了数据源实现l节。由于当低层数据源实现变化时QDAO向客L提供的接口不会变化,所以该模式允许DAO调整C同的存储模式Q而不会媄响其客户端或业务lg。重要的是,DAO充当lg和数据源之间的适配器?/p>

3、实现策?br>    通过调整抽象工厂(Abstract Factory)模式和工厂方?Factory MethodQ这二个创徏型模式的实现详情可参看GoF?lt;设计模式>一?模式QDAO模式可以辑ֈ很高的灵zd?

当低层存储不会随着实现变化而变化时Q可以用工厂方法模式来实现该策略,以生应用程序需要的大量DAOQ如下面cd1所C?
当低层存储随着实现的变化而变化时Q策略可以通过使用抽象工厂模式而实现。抽象工厂可以基于工厂方法实现而创建,q可使用工厂Ҏ实现Q该{略提供一个DAO的抽象工厂对象,其中该对象可以构造多U类型的具体的DAO工厂Q每个工厂支持一U不同类型的持久性存储实现。一旦你获取某特定实现的具体DAO工厂Q你可以使用它来生成该实C所支持和实现的DAOQ如下面cd2所C?


 

4、应?br>    当数据访问代码被直接嵌入到有其他不相兌责的某类中时Q就会修改变的十分困难。这时可以采用分L据访问代码的解决ҎQ将数据讉K代码抽取C个新cMQƈ且把该新c逻辑或者物理地Ud到离数据源比较近的位|,q样可以增强模块性和可重用性,如下面图3所C。具体作法可以用提炼类(Extract ClassQ一U重构手法,l节可参看Martin?lt;重构>一?Ҏ创徏一个新c,q将原来cM把数据访问代码移动到q个新的数据讉K对象(DAO)c,使用q个新的DAO对象从控制器cM讉K数据?br>    CZQ持久性逻辑被嵌入到一个用新DAO对象理的持久性的某企业新DAO对象中,把持久性代码和该企业新DAO对象代码l合h会创q、紧密耦合的代码。当持久性代码是该企业新DAO对象的一部分Ӟ对该持久性存储的M改动都要求更改该新DAO对象的持久性代码。这U耦合对企业新DAO对象代码l护会带来负面的影响。下面图4用分L据访问对象方法对其进行重构改q后的结果?/p>

    ?5个J2EE模式中,每个模式都作用于设计模式和构架模式之间的某些斚w。每个模式不是孤立存在的Q需要其它模式的支持才能更加体现其含义和用处Qؓ了最大限度的用好模式Q还需要充分理解模式之间的关系?

 参考文?

pȝ分析员教E?--- |晓沛等?
设计模式Q可复用面向对象软g的元?--- 李英军等?
重构-改善既有代码的设?--- 侯捷{译
J2EE核心模式 --- 牛志奇等?
UML_a(W二? --- 徐家译



JAVA之\ 2007-04-08 10:42 发表评论
]]>
Hibernate二~存ȝhttp://www.tkk7.com/xixidabao/archive/2007/04/08/109196.htmlJAVA之\JAVA之\Sun, 08 Apr 2007 02:04:00 GMThttp://www.tkk7.com/xixidabao/archive/2007/04/08/109196.html

Hibernate二~存ȝ

2006-10-27 15:59 作者: AreYouOK 出处Q?JAVAEYE 责Q~辑Q?a title=向本~辑提问 target=_blank>方舟


       很多人对二~存都不太了解,或者是有错误的认识Q我一直想写一文章介l一下hibernate的二U缓存的Q今天终于忍不住了?

  我的l验主要来自hibernate2.1版本Q基本原理和3.0?.1是一LQ请原谅我的固不化?

  hibernate的session提供了一U缓存,每个sessionQ对同一个idq行两次loadQ不会发送两条sqll数据库Q但是session关闭的时候,一U缓存就失效了?br>
  二~存是SessionFactoryU别的全局~存Q它底下可以使用不同的缓存类库,比如ehcache、oscache{,需要设|hibernate.cache.provider_classQ我们这里用ehcacheQ在2.1中就?hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider如果使用查询~存Q加上hibernate.cache.use_query_cache=true

  ~存可以单的看成一个MapQ通过key在缓存里面找value?br>
  Class的缓?/strong>

  对于一条记录,也就是一个PO来说Q是ҎID来找的,~存的key是IDQvalue是POJO。无论listQloadq是iterateQ只要读Z个对象,都会填充~存。但是list不会使用~存Q而iterate会先取数据库select id出来Q然后一个id一个id的loadQ如果在~存里面有,׃~存取,没有的话去数据库load。假设是d~存Q需要设|:

Qcache usage="read-write"/Q?

  如果你用的二~存实现是ehcache的话Q需要配|ehcache.xml

Qcache name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true" /Q?

  其中eternal表示~存是不是永q不时QtimeToLiveSeconds是缓存中每个元素Q这里也是一个POJOQ的时旉Q如果eternal="false"Q超q指定的旉Q这个元素就被移C。timeToIdleSeconds是发呆时_是可选的。当往~存里面put的元素超q?00个时Q如果overflowToDisk="true"Q就会把~存中的部分数据保存在硬盘上的时文仉面?

  每个需要缓存的class都要q样配置。如果你没有配置Qhibernate会在启动的时候警告你Q然后用defaultCache的配|,q样多个class会共享一个配|?

  当某个ID通过hibernate修改Ӟhibernate会知道,于是U除~存?

  q样大家可能会想Q同L查询条gQ第一ơ先listQ第二次再iterateQ就可以使用到缓存了。实际上q是很难的,因ؓ你无法判断什么时候是W一ơ,而且每次查询的条仉常是不一LQ假如数据库里面?00条记录,id??00Q第一ơlist的时候出了前50个idQ第二次iterate的时候却查询?0?0号idQ那?0-50是从~存里面取的Q?1?0是从数据库取的,共发?+20条sql。所以我一直认为iterate没有什么用QL会有1+N的问题?

  Q题外话Q有说法说大型查询用list会把整个l果集装入内存,很慢Q而iterate只select id比较好,但是大型查询L要分|的,谁也不会真的把整个结果集装进来,假如一?0条的话,iterate共需要执?1条语句,list虽然选择若干字段Q比iterateW一条select id语句慢一些,但只有一条语句,不装入整个结果集hibernateq会Ҏ数据库方a做优化,比如使用mysql的limitQ整体看来应该还是list快。)

  如果惌对list或者iterate查询的结果缓存,p用到查询~存?br>
  查询~存

  首先需要配|hibernate.cache.use_query_cache=true

  如果用ehcacheQ配|ehcache.xmlQ注意hibernate3.0以后不是net.sf的包名了Q?br>
Qcache name="net.sf.hibernate.cache.StandardQueryCache"
maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600"
timeToLiveSeconds="7200" overflowToDisk="true"/Q?
Qcache name="net.sf.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/Q?

  然后

query.setCacheable(true);//ȀzL询缓?
query.setCacheRegion("myCacheRegion");//指定要用的cacheRegionQ可?

  W二行指定要使用的cacheRegion是myCacheRegionQ即你可以给每个查询~存做一个单独的配置Q用setCacheRegion来做q个指定Q需要在ehcache.xml里面配置它:

Qcache name="myCacheRegion" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" /Q?

  如果省略W二行,不设|cacheRegion的话Q那么会使用上面提到的标准查询缓存的配置Q也是Qnet.sf.hibernate.cache.StandardQueryCache

  对于查询~存来说Q缓存的key是根据hql生成的sqlQ再加上参数Q分늭信息Q可以通过日志输出看到Q不q它的输Z是很可读Q最好改一下它的代码)?

  比如hqlQ?

from Cat c where c.name like ?

  生成大致如下的sqlQ?

select * from cat c where c.name like ?

  参数?tiger%"Q那么查询缓存的key*大约*是这L字符Ԍ我是凭记忆写的,q不_Q不q看了也该明白了Q:

select * from cat c where c.name like ? , parameter:tiger%

  q样Q保证了同样的查询、同L参数{条件下h一Lkey?

  现在说说~存的valueQ如果是list方式的话Qvalue在这里ƈ不是整个l果集,而是查询出来的这一串ID。也是_不管是listҎq是iterateҎQ第一ơ查询的时候,它们的查询方式很它们qx的方式是一LQlist执行一条sqlQiterate执行1+N条,多出来的行ؓ是它们填充了~存。但是到同样条gW二ơ查询的时候,都和iterate的行Z样了Q根据缓存的keyȝ存里面查CvalueQvalue是一串idQ然后在到class的缓存里面去一个一个的load出来。这样做是ؓ了节U内存?

  可以看出来,查询~存需要打开相关cȝclass~存。list和iterateҎW一ơ执行的时候,都是既填充查询缓存又填充class~存的?
q里q有一个很Ҏ被忽视的重要问题Q即打开查询~存以后Q即使是listҎ也可能遇?+N的问题!相同条gW一ơlist的时候,因ؓ查询~存中找不到Q不class~存是否存在数据QL发送一条sql语句到数据库获取全部数据Q然后填充查询缓存和class~存。但是第二次执行的时候,问题来了,如果你的class~存的超时时间比较短Q现在class~存都超时了Q但是查询缓存还在,那么listҎ在获取id串以后,会一个一个去数据库loadQ因此,class~存的超时时间一定不能短于查询缓存设|的时旉Q如果还讄了发呆时间的话,保证class~存的发呆时间也大于查询的缓存的生存旉。这里还有其他情况,比如class~存被程序强制evict了,q种情况p自己注意了?br>
  另外Q如果hql查询包含select字句Q那么查询缓存里面的value是整个l果集了?br>
  当hibernate更新数据库的时候,它怎么知道更新哪些查询~存呢?

  hibernate在一个地方维护每个表的最后更新时_其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配|里面?

  当通过hibernate更新的时候,hibernate会知道这ơ更新媄响了哪些表。然后它更新q些表的最后更新时间。每个缓存都有一个生成时间和q个~存所查询的表Q当hibernate查询一个缓存是否存在的时候,如果~存存在Q它q要取出~存的生成时间和q个~存所查询的表Q然后去查找q些表的最后更新时_如果有一个表在生成时间后更新q了Q那么这个缓存是无效的?

  可以看出Q只要更新过一个表Q那么凡是涉及到q个表的查询~存失效了Q因此查询缓存的命中率可能会比较低?br>
Collection~存

  需要在hbm的collection里面讄Q?br>
Qcache usage="read-write"/Q?

  假如class是CatQcollection叫childrenQ那么ehcache里面配置

Qcache name="com.xxx.pojo.Cat.children"
maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
overflowToDisk="true" /Q?

  Collection的缓存和前面查询~存的list一P也是只保持一串idQ但它不会因个表更新q就失效Q一个collection~存仅在q个collection里面的元素有增删时才失效?

  q样有一个问题,如果你的collection是根据某个字D|序的Q当其中一个元素更C该字D|Q导致顺序改变时Qcollection~存里面的顺序没有做更新?br>
  ~存{略

  只读~存Qread-onlyQ:没有什么好说的

  ?写缓存(read-writeQ?E序可能要的更新数据

  不严格的?写缓存(nonstrict-read-writeQ:需要更新数据,但是两个事务更新同一条记录的可能性很,性能比读写缓存好
事务~存QtransactionalQ:~存支持事务Q发生异常的时候,~存也能够回滚,只支持jta环境Q这个我没有怎么研究q?br>
  d~存和不严格d~存在实C的区别在于,d~存更新~存的时候会把缓存里面的数据换成一个锁Q其他事务如果去取相应的~存数据Q发现被锁住了,然后q接取数据库查询?

  在hibernate2.1的ehcache实现中,如果锁住部分~存的事务发生了异常Q那么缓存会一直被锁住Q直?0U后时?

  不严D写缓存不锁定~存中的数据?使用二~存的前|条件?br>
  你的hibernateE序Ҏ据库有独占的写访问权Q其他的q程更新了数据库Qhibernate是不可能知道的。你操作数据库必需直接通过hibernateQ如果你调用存储q程Q或者自׃用jdbc更新数据库,hibernate也是不知道的。hibernate3.0的大扚w更新和删除是不更CU缓存的Q但是据?.1已经解决了这个问题?

  q个限制相当的棘手,有时候hibernate做批量更新、删除很慢,但是你却不能自己写jdbc来优化,很郁闷吧?

  SessionFactory也提供了U除~存的方法,你一定要自己写一些JDBC的话Q可以调用这些方法移除缓存,q些Ҏ是:

void evict(Class persistentClass)
Evict all entries from the second-level cache.
void evict(Class persistentClass, Serializable id)
Evict an entry from the second-level cache.
void evictCollection(String roleName)
Evict all entries from the second-level cache.
void evictCollection(String roleName, Serializable id)
Evict an entry from the second-level cache.
void evictQueries()
Evict any query result sets cached in the default query cache region.
void evictQueries(String cacheRegion)
Evict any query result sets cached in the named query cache region.

  不过我不q样做,因ؓq样很难l护。比如你现在用JDBC扚w更新了某个表Q有3个查询缓存会用到q个表,用evictQueries(String cacheRegion)U除?个查询缓存,然后用evict(Class persistentClass)U除了class~存Q看上去好像完整了。不q哪天你d了一个相x询缓存,可能会忘记更新这里的U除代码。如果你的jdbc代码到处都是Q在你添加一个查询缓存的时候,q知道其他什么地方也要做相应的改动吗Q?br>
  ȝQ?

  不要惛_然的以ؓ~存一定能提高性能Q仅仅在你能够驾驭它q且条g合适的情况下才是这L。hibernate的二U缓存限制还是比较多的,不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下ؕ用,可能会有1+N的问题。不当的使用q可能导致读数据?
如果受不了hibernate的诸多限Ӟ那么q是自己在应用程序的层面上做~存吧?

  在越高的层面上做~存Q效果就会越好。就好像管盘有缓存,数据库还是要实现自己的缓存,管数据库有~存Q咱们的应用E序q是要做~存。因为底层的~存它ƈ不知道高层要用这些数据干什么,只能做的比较通用Q而高层可以有针对性的实现~存Q所以在更高的别上做缓存,效果也要好些吧?br>

JAVA之\ 2007-04-08 10:04 发表评论
]]>
J2EE 全面?/title><link>http://www.tkk7.com/xixidabao/archive/2006/09/11/69038.html</link><dc:creator>JAVA之\</dc:creator><author>JAVA之\</author><pubDate>Mon, 11 Sep 2006 13:22:00 GMT</pubDate><guid>http://www.tkk7.com/xixidabao/archive/2006/09/11/69038.html</guid><description><![CDATA[ <table cellspacing="0" cellpadding="0" width="760" align="center" border="0"> <tbody> <tr> <td class="title" valign="center" align="middle" height="56"> <b> <font color="#ff0000" size="3">J2EE 全面?br /><!-- #EndEditable --></font> </b> </td> </tr> <tr> <td class="formtitle" align="middle" height="40"> <!-- #BeginEditable "2" -->作者:刘湛 (jeru@163.net) 武汉大学信息与计科学系学士 选自QMatrix-与Javap<!-- #EndEditable --></td> </tr> </tbody> </table> <table height="65" cellspacing="0" cellpadding="0" width="760" align="center" border="0"> <tbody> <tr> <td class="content" height="65"> <!-- #BeginEditable "3" --> <table class="content" width="77%" align="center" border="0"> <tbody> <tr> <td class="content" valign="top"> <span id="lpocmpo" class="myp11"> <font id="zoom"> </font> </span> <span id="iekjesv" class="p11b"> </span> <p> <strong>J2EE 全面?/strong> <br />本文从五个方面对J2EEq行了比较全面的介绍。从J2EE的概念说P到它的优势,到J2EE典型的四层模型,和它的框架结构,最后是J2EE十三U核心技术的一个简介。本文分门别cȝ对J2EE中的服务Q组Ӟ层次Q容器,API都做了比较详l的介绍Q相信看完此文,读者会对J2EE有一个更清晰的认识?</p> <p> <strong>一. J2EE的概?/strong> <br />目前QJava 2q_?个版本,它们是适用于小型设备和卡的Java 2q_Micro版(Java 2 Platform Micro EditionQJ2MEQ、适用于桌面系l的Java 2q_标准版(Java 2 Platform Standard EditionQJ2SEQ、适用于创建服务器应用E序和服务的Java2q_企业版(Java 2 Platform Enterprise Edition J2EEQ?br />J2EE是一U利用Java 2q_来简化企业解x案的开发、部|和理相关的复杂问题的体系l构。J2EE技术的基础是核心Javaq_或Java 2q_的标准版QJ2EE不仅巩固了标准版中的许多优点Q例?~写一ơ、随处运?的特性、方便存取数据库的JDBC API、CORBA技术以及能够在Internet应用中保护数据的安全模式{等Q同时还提供了对 EJBQEnterprise JavaBeansQ、Java Servlets API、JSPQJava Server PagesQ以及XML技术的全面支持。其最l目的就是成Z个能够企业开发者大q羃短投攑ָ场时间的<br />体系l构?br />J2EE体系l构提供中间层集成框架用来满x需太多费用而又需要高可用性、高可靠性以及可扩展性的应用的需求。通过提供l一的开发^収ͼJ2EE降低了开发多层应用的费用和复杂性,同时提供对现有应用程序集成强有力支持Q完全支持Enterprise JavaBeansQ有良好的向导支持打包和部v应用Q添加目录支持,增强了安全机Ӟ提高了性能?/p> <p> <strong>? J2EE的优?/strong> <br />J2EE为搭建具有可伸羃性、灵zL、易l护性的商务pȝ提供了良好的机制:<br />保留现存的IT资: ׃企业必须适应新的商业需求,利用已有的企业信息系l方面的投资Q而不是重新制定全盘方案就变得很重要。这P一个以渐进的(而不是激q的Q全盘否定的Q方式徏立在已有pȝ之上的服务器端^台机制是公司所需求的。J2EE架构可以充分利用用户原有的投资,如一些公怋用的BEA Tuxedo、IBM CICS, IBM Encina,、InpriseVisiBroker及Netscape Application Server。这之所以成为可能是因ؓJ2EE拥有q泛的业界支持和一些重要的'企业计算'领域供应商的参与。每一个供应商都对现有的客h供了不用废弃已有投资Q进入可UL的J2EE领域的升U途径。由于基于J2EEq_的品几乎能够在M操作pȝ和硬仉|上q行Q现有的操作pȝ和硬件也<br />能被保留使用?br />高效的开? J2EE允许公司把一些通用的、很J琐的服务端d交给中间件供应商d成。这样开发h员可以集中精力在如何创徏商业逻辑上,相应地羃短了开发时间。高U中间g供应商提供以下这些复杂的中间件服?<br />状态管理服?-- 让开发h员写更少的代码,不用兛_如何理状态,q样能够更快地完成程序开发?br />持箋性服?-- 让开发h员不用对数据讉K逻辑q行~码p~写应用E序Q能生成更轻巧,与数据库无关的应用程序,q种应用E序更易于开发与l护?br />分布式共享数据对象CACHE服务 -- 让开发h员编刉性能的系l,极大提高整体部v的׾~性?br />支持异构环境: J2EE能够开发部|在异构环境中的可移植程序。基于J2EE的应用程序不依赖M特定操作pȝ、中间g、硬件。因此设计合理的ZJ2EE的程序只需开发一ơ就可部|到各种q_。这在典型的异构企业计算环境中是十分关键的。J2EE标准也允许客戯购与J2EE兼容的第三方的现成的lgQ把他们部v到异构环境中Q节省了p己制订整个方案所需的费用?br />可׾~? 企业必须要选择一U服务器端^収ͼq种q_应能提供极佳的可伸羃性去满那些在他们系l上q行商业q作的大Ҏ客户。基于J2EEq_的应用程序可被部|到各种操作pȝ上。例如可被部|到高端UNIX与大型机pȝQ这U系l单机可支持64?56个处理器。(q是NT服务器所望尘莫及的)J2EE领域的供应商提供了更为广泛的负蝲q{略。能消除pȝ中的瓉Q允许多台服务器集成部v。这U部|可达数千个处理器,实现可高度׾~的pȝQ满x来商业应用的需要?br />E_的可用? 一个服务器端^台必能全天候运转以满公司客户、合作伙伴的需要。因为INTERNET是全球化的、无处不在的Q即使在夜间按计划停Z可能造成严重损失。若是意外停机,那会有灾难性后果。J2EE部v到可靠的操作环境中,他们支持长期的可用性。一些J2EE部v在WINDOWS环境中,客户也可选择健壮性能更好的操作系l如Sun Solaris、IBM OS/390。最健壮的操作系l可辑ֈ99.999%的可用性或每年只需5分钟停机旉。这是实时性很强商业系l理想的选择?/p> <p> <br /> <strong>? J2EE 的四层模?/strong> <br />J2EE使用多层的分布式应用模型Q应用逻辑按功能划分ؓlgQ各个应用组件根据他们所在的层分布在不同的机器上。事实上Qsun设计J2EE的初h是ؓ了解决两层模?client/server)的弊端,在传l模式中Q客L担当了过多的角色而显得臃肿,在这U模式中Q第一ơ部|的时候比较容易,但难于升U或改进Q可伸展性也不理惻I而且l常Z某种专有的协议――通常是某U数据库协议。它使得重用业务逻辑和界面逻辑非常困难。现在J2EE 的多层企业应用模型两层化模型中的不同层面切分成许多层。一个多层化应用能够Z同的每种服务提供一个独立的层,以下?J2EE 典型的四层结?<br />q行在客L机器上的客户层组?br />q行在J2EE服务器上的Web层组?br />q行在J2EE服务器上的业务逻辑层组?br />q行在EIS服务器上的企业信息系l?Enterprise information system)层Y?br />J2EE应用E序lg<br />J2EE应用E序是由lg构成?J2EElg是具有独立功能的软g单元Q它们通过相关的类和文件组装成J2EE应用E序Qƈ与其他组件交互。J2EE说明书中定义了以下的J2EElg:<br />应用客户端程序和applets是客户层lg.<br />Java Servlet和JavaServer Pages(JSP)是web层组?<br />Enterprise JavaBeans(EJB)是业务层lg.<br />客户层组?br />J2EE应用E序可以是基于web方式?也可以是Z传统方式?<br />web 层组件J2EE web层组件可以是JSP 面或Servlets.按照J2EE规范Q静态的HTML面和Applets不算是web层组件。web层可能包含某?JavaBean 对象来处理用戯入,q把输入发送给q行在业务层上的enterprise bean 来进行处理?/p> <p>业务层组?br />业务层代码的逻辑用来满银行Q零售,金融{特D商务领域的需?p行在业务层上的enterprise bean q行处理. 下图表明了一个enterprise bean 是如何从客户端程序接收数据,q行处理(如果必要的话), q发送到EIS 层储存的Q这个过E也可以逆向q行?br />有三U企业的bean: 会话(session) beans, 实体(entity) beans, ?消息驱动(message-driven) beans. 会话bean 表示与客LE序的时交? 当客LE序执行完后, 会话bean 和相x据就会消? 相反, 实体bean 表示数据库的表中一行永久的记录. 当客LE序中止或服务器关闭? ׃有潜在的服务保证实体bean 的数据得以保?消息驱动 bean l合了会话bean ?JMS的消息监听器的特? 允许一个业务层lg异步接收JMS 消息.</p> <p> <br />企业信息pȝ?br />企业信息pȝ层处理企业信息系lY件包括企业基pȝ例如企业资源计划 (ERP), 大型Z务处? 数据库系l?和其它的遗留信息pȝ. 例如QJ2EE 应用lg可能Z数据库连接需要访问企业信息系l?/p> <p> <br /> <strong>? J2EE 的结?/strong> <br />q种ZlgQ具有^台无x的J2EE l构使得J2EE E序的编写十分简单,因ؓ业务逻辑被封装成可复用的lgQƈ且J2EE 服务器以容器的Ş式ؓ所有的lgcd提供后台服务. 因ؓ你不用自己开发这U服? 所以你可以集中_֊解决手头的业务问?</p> <p> <br />容器和服?br />容器讄定制了J2EE服务器所提供得内在支持,包括安全Q事务管理,JNDI(Java Naming and Directory Interface)d,q程q接{服务,以下列出最重要的几U服务:<br />J2EE安全(Security)模型可以让你配置 web lg或enterprise bean ,q样只有被授权的用户才能讉Kpȝ资源. 每一客户属于一个特别的角色Q而每个角色只允许Ȁzȝ定的Ҏ。你应在enterprise bean的布|描qC声明角色和可被激zȝҎ。由于这U声明性的ҎQ你不必~写加强安全性的规则?br />J2EE 事务理QTransaction ManagementQ模型让你指定组成一个事务中所有方法间的关p,q样一个事务中的所有方法被当成一个单一的单? 当客LȀzM个enterprise bean中的ҎQ容器介入一理事务。因有容器管理事务,在enterprise bean中不必对事务的边界进行编码。要求控制分布式事务的代码会非常复杂。你只需在布|描q文件中声明enterprise bean的事务属性,而不用编写ƈ调试复杂的代码。容器将L文gqؓ你处理此enterprise bean的事务?br />JNDI d(JNDI Lookup)服务向企业内的多重名字和目录服务提供了一个统一的接?q样应用E序lg可以讉K名字和目录服?<br />J2EEq程q接QRemote Client ConnectivityQ模型管理客L和enterprise bean间的低层交互. 当一个enterprise bean创徏? 一个客L可以调用它的Ҏp它和客户端位于同一虚拟Z一?<br />生存周期理QLife Cycle ManagementQ模型管理enterprise bean的创建和U除,一个enterprise bean在其生存周期中将会历l几U状态。容器创建enterprise beanQƈ在可用实例池与活动状态中Ud他,而最l将其从容器中移除。即使可以调用enterprise bean的create及removeҎQ容器也会在后台执行这些Q务?/p> <p> <br />数据库连接池QDatabase Connection PoolingQ模型是一个有价值的资源。获取数据库q接是一耗时的工作,而且q接数非常有限。容器通过理q接池来~和q些问题?br />enterprise bean可从池中q速获取连接。在bean释放q接之可为其他bean使用?br />容器cd<br />J2EE应用lg可以安装部vC下几U容器中?<br />EJB 容器理所有J2EE 应用E序中企业bean 的执? enterprise bean 和它们的容器q行在J2EE 服务器上.<br />Web 容器理所有J2EE 应用E序中JSP面和Servletlg的执? Web lg和它们的容器q行在J2EE 服务器上.<br />应用E序客户端容器管理所有J2EE应用E序中应用程序客Llg的执? 应用E序客户端和它们的容器运行在J2EE 服务器上.<br />Applet 容器是运行在客户端机器上的web览器和 Java 插g的结?<br /><br /><strong>? J2EE的核心API与组?/strong><br />J2EEq_׃整套服务QServicesQ、应用程序接口(APIsQ和协议构成Q它对开发基于Web的多层应用提供了功能支持Q下面对J2EE中的13U技术规范进行简单的描述(限于幅Q这里只能进行简单的描述):<br />JDBC(Java Database Connectivity):<br />JDBC API问不同的数据库提供了一U统一的途径Q象ODBC一PJDBC对开发者屏蔽了一些细节问题,另外QJDCBҎ据库的访问也hq_无关性?br />JNDI(Java Name and Directory Interface):<br />JNDI API被用于执行名字和目录服务。它提供了一致的模型来存取和操作企业U的资源如DNS和LDAPQ本地文件系l,或应用服务器中的对象?br /><br />EJB(Enterprise JavaBean):<br />J2EE技术之所以赢得某体广泛重视的原因之一是EJB。它们提供了一个框架来开发和实施分布式商务逻辑Q由此很显著地简化了h可׾~性和高度复杂的企业应用的开发。EJB规范定义了EJBlg在何时如何与它们的容器进行交互作用。容器负责提供公用的服务Q例如目录服务、事务管理、安全性、资源缓冲池以及定w性。但q里值得注意的是QEJBq不是实现J2EE的唯一途径。正是由于J2EE的开放性,使得有的厂商能够以一U和EJBq的方式来辑ֈ同样的目的?br />RMI(Remote Method Invoke):<br />正如其名字所表示的那PRMI协议调用q程对象上方法。它使用了序列化方式在客L和服务器端传递数据。RMI是一U被EJB使用的更底层的协议?br />Java IDL/CORBA:<br />在Java IDL的支持下Q开发h员可以将Java和CORBA集成在一赗?他们可以创徏Java对象q之可在CORBA ORB中展开, 或者他们还可以创徏Javacdƈ作ؓ和其它ORB一起展开的CORBA对象的客戗后一U方法提供了另外一U途径Q通过它Java可以被用于将你的新的应用和旧的系l相集成?br />JSP(Java Server Pages):<br />JSP面由HTML代码和嵌入其中的Java代码所l成。服务器在页面被客户端所h以后对这些Java代码q行处理Q然后将生成的HTML面q回l客L的浏览器?br />Java Servlet:<br />Servlet是一U小型的JavaE序Q它扩展了Web服务器的功能。作ZU服务器端的应用Q当被请求时开始执行,q和CGI Perl脚本很相伹{Servlet提供的功能大多与JSPcMQ不q实现的方式不同。JSP通常是大多数HTML代码中嵌入少量的Java代码Q而servlets全部由Java写成q且生成HTML?br />XML(Extensible Markup Language):<br />XML是一U可以用来定义其它标记语a的语a。它被用来在不同的商务过E中׃n数据?br />XML的发展和Java是相互独立的Q但是,它和Javah的相同目标正是^台独立性。通过Java和XML的组合,您可以得C个完的hq_独立性的解决Ҏ?br />JMS(Java Message Service):<br />MS是用于和面向消息的中间g怺通信的应用程序接?API)。它既支持点对点的域Q有支持发布/订阅(publish/subscribe)cd的域Qƈ且提供对下列cd的支持:l认可的消息传?事务型消息的传递,一致性消息和h持久性的订阅者支持。JMSq提供了另一U方式来Ҏ的应用与旧的后台pȝ盔R成?br />JTA(Java Transaction Architecture):<br />JTA定义了一U标准的APIQ应用系l由此可以访问各U事务监控?br />JTS(Java Transaction Service):<br />JTS是CORBA OTS事务监控的基本的实现。JTS规定了事务管理器的实现方式。该事务理器是在高层支持Java Transaction API (JTA)规范Qƈ且在较底层实现OMG OTS specification的Java映像。JTS事务理器ؓ应用服务器、资源管理器、独立的应用以及通信资源理器提供了事务服务?br />JavaMail:<br />JavaMail是用于存取邮件服务器的APIQ它提供了一套邮件服务器的抽象类。不仅支持SMTP服务器,也支持IMAP服务器?br />JTA(JavaBeans Activation Framework):<br />JavaMail利用JAF来处理MIME~码的邮仉件。MIME的字节流可以被{换成Java对象</p> <p> <br />参考资料:<br />《Develop n-tier application using J2EE? Steven Gould<br />《The Business Benefits of EJB and J2EE Technologies over COM+ and Windows D<br />NA?br />《The J2EE Tutorial》chapter overview - Monica Pawlan</p> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <img src ="http://www.tkk7.com/xixidabao/aggbug/69038.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/xixidabao/" target="_blank">JAVA之\</a> 2006-09-11 21:22 <a href="http://www.tkk7.com/xixidabao/archive/2006/09/11/69038.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2EE宠物商店http://www.tkk7.com/xixidabao/archive/2006/09/11/69037.htmlJAVA之\JAVA之\Mon, 11 Sep 2006 13:17:00 GMThttp://www.tkk7.com/xixidabao/archive/2006/09/11/69037.html J2EE宠物商店 作者:?谷和?/font>   来源QCSDN
 

 J2EE 是Java技术在企业q算上的应用Q它包含多种q算标准Q如EJBlg架构、JDBC数据库运、JMS信息传递、Java Servlets/JSP{WeblgE序{,功能强大且内容博大精深。ؓ了让使用者可以有一个设计J2EE架构应用E序的模板,Sun做出一套系l名为“Java宠物商店QPet StoreQ”。这个网上宠物店的范例是针对已经熟悉JavaE序设计和J2EE概念人员的。这个系l是使用正规方式设计出来的,使得使用J2EE架构的h员有了一个参考的依据。这个范例一出来Q很快就被用来当成比较各家J2EE兼容产品的依据。Oracle的J2EE Application ServerQOracle 9iASQ、BEA WebLogic Server?a >IBM WebSphere都有相应的品。Java标准的精原本就是各家厂商合作制定技术标准,然后再根据这个标准来评选出最优品?br />
  Java Pet Store使用的架构设计就是所谓的MVC 设计模式。MVC是Model-View-Controller的简写,是设计模式的一U,源自Smalltalk。MVC模式则是对象分成三c,Model对象专门用来包装应用E序的状态,View用来负责屏幕上的展现QController则负责定义应用程序的各种动作和反应。Java宠物店系l利用MVC模式设计整个pȝ架构Q将各层的对象清楚地分开。Java宠物店的目的是展CZ个具有扩充性的企业q算架构Q就是采用三层(3-TiersQ式设计Q资料展现层在最外面Q中间是执行企业q算逻辑的中间层lgQ后端就是单U存放资料的关系型数据库。Java宠物店当初的用意也只是当成一个J2EE架构设计的模板,q没有特别针对加速执行效能作额外的设计?br />
pȝ构架与宠物商店简?/b>

  pȝ构架

  Pet Store|站pȝ采用松耦合的设计架构,可以和多个数据源、EISq行交互。这个例子共分成4个部分:

  1.Web购物站点Q?br />
  2.理部分,包括销售统计、手工接?拒绝订单Q?br />
  3.订单处理Q包括以?部分内容Q?br />
   ?通过JMS接受/处理订单消息Q?br />
   ?用Java Mail来通知客户Q?br />
   ?通过JMS发订单给供应商;

  ?l护订单数据库?br />
  4.供应商,此部分包括以下内容:

   ?通过JMS接受订单Q?br />
  ?zN货物给用户Q?br />
  ?提供一个基于Web的库存管理;

  ?l护库存数据库?br />
  宠物店网上商店功?br />
  通过览器可以访问此商店。客户通过览Q可以把货物攑օ购物车,创徏账户/d账户Q创单,然后通过信用卡支付?br />
  宠物商店l构

  宠物店的|站服务是从上而下的。最上层是WAF(Web Application Framework)来控制应用的屏幕跌{Q生视图,然后调用商业lg来完成商业处理(如图1所C)?br />


  ? Java Pet Store l构

  WAF提供了许多Web应用所需的服务,包括h的过滤和分发、模板视囄产生、一pd可重用的TaglibQ以及屏q流E控制等。应用组件封装了处理的逻辑Q它们代表了商业的数据,q且操作q些商业数据Q实体EJB代表了商业实体,如客戗地址、̎目。会话EJB提供了一些方法,如登陆一个用戗输Z个用戗管理购物R{。其它会话EJB提供了一些共同的ҎQ如产生唯一标示W。传l的JavaBeanlg变成了值对象,用来在EJBlg和应用间传递数据。XML文档cd用来处理订单信息?br />
  q个宠物店例子的WAF是对J2EE蓝图Web层规范的实现。一个Web层处理一般可以划分成四步Q如?所C):

  ?解释一个请求;

  ?执行一个商业逻辑处理Q?br />
  ?选择下一个视图;

  ?产生q个视图?br />


  ? WAF的Web层处?br />
  宠物店模块设?br />
  宠物店由一些独立模块组成:

  ?控制模块 它来分发h到各个业务处理逻辑、控制屏q蟩转、处理对应的lg及用P

  ?d和注?控制模块由WAF实现和扩展;

  ?购物车模?购物车跟t用戯物过E;

  ?d模块 需要用L录在某些面dQ?br />
  ?消息模块 从宠物店到等单中心用来异步传输订单;

  ?cd模块 Ҏ用户查询需求提供一个类别视图;

  ?客户模块 表示客户信息Q如地址、信用卡、联pL式等Q如?所C)?br />


  ? Java pet Store 模块设计

  在图3中,控制模块控制所有的交互和执?每个用户会话都有一个购物R对应?br />
  宠物店的lg

  1. EJBQ代表了商业数据和执行商业逻辑处理Q?br />
  2. JSP面Q?定义了整个应用的视图框架模板(template.jsp)和模板组成的各个JSP文gQ以及各U被引用的图形文Ӟ

  3. XML文gQ用来定义屏q、屏q蟩转控制、绑定URL到某个HTML Action、定制signOn以及J2EE部v的部|XML文gQ?br />
  4. Servletq虑? 用来校验用户安全的登陆和输出的编码;

  5. 异步信息发送组?传输使用XML装的订单到订单处理中心Q?br />
  6. 一个安装程?用来产生例子数据库?br />
分析宠物商店的应?/b>

下面按照MVC架构和层ơ化应用模型来分析这个应用?br />
模型—视䏀控制架?br />
1Q应用模型划分方?br />
分析一个实际应用可以有三种划分的方法:W一U划分方法ؓ模型—视䏀控ӞMVCQ架构。这U方法把应用分解成数据、显C和控制三个部分。第二种划分Ҏ把应用按照不同的角色划分成不同的层次Q分dL、Web层、EJBs层和底端的数据层或遗留系l层Q即J2EE应用的层ơ划分方法。第三种划分是传l的功能模块划分?br />
划分的目的是使复杂的问题清晰化、条理化。每一U划分虽然增加了额外的复杂性,但也有它的好处。MVC架构为应用组件提供一个灵zȝ、可重用的、易试的、可扩展的和清晰的设计角艌Ӏ多层设计实现技术的选择灉|Q同时具有可升和可扩展性。模块化的设计把pȝ分解成小的直接模块,可以q行单独分析、测试和理解?br />
现在企业U应用与以前相比Q要更多地支持用不同类型接口的多类型用P例如在线商店需要ؓWeb֮提供HMTL主页、ؓ无线֮提供XML主页、ؓpȝ理员提供JFC/Swing接口、ؓ供应商提供基于XML的Web服务{(见图4Q?br />


? Java Pet Store 支持的各U类型用户关pd

当开发一个支持单一cd客户端的应用Ӟ可以把数据访问逻辑、显C控刉辑和接口逻辑交织在一赗但对于支持多类型客L的企业系l来_q是很麻烦的。因此:

?对于每种cd的客L接口Q需开发不同的应用Q?br />
?每个应用的非界面代码是重复的Q在实现、测试和l护斚w需重复工作Q?br />
?复制工作本n是昂늚Q因为界面与非界面代码交l;

?重复工作不可避免Q而且是有~陷而缓慢的?br />
2.使用模型—视䏀控制架?br />
通过在J2EE应用中用模型—视䏀控制架构,把核心数据和数据讉K功能与用这些功能的昄控制逻辑分开Q如?所C。这U分d许多视图׃n同样的企业数据模型?br />


? MVC架构

MVC架构h于SmalltalkQ最初用来在传统的图形用L面模型中映射输入、处理和输出d。然而,它可以直接用来映多层企业应用中的相x念,具体概念介绍如下Q?br />
模型QModelQ代表企业数据和业务规则Q用来控制访问和数据更新。模型是接近现实世界的服务YӞ因此现实世界的徏模技术可以应用模型?br />
视图QViewQ代表模型的内容。它通过模型讉K企业数据q指定这些数据的昄。视图负责模型状态改变后呈现l用L数据也相应改变。可以通过推(PushQ模型实玎ͼ卌囑֜模型中注册获取更新指令,或者拉QPullQ模型,即由视图负责在需要获取最新数据的时候调用模型?br />
控制QControllerQ把与视图交互{化成模型执行的动作。在独立q行的GUI客户端,用户交互可能是按钮或菜单Q而在Web应用中是GET和POST HTTPh。模型执行的动作包括ȀzM务处理进E或改变模型状态。以用户交互和模型动作结果ؓ基础Q控刉过选择合适的视图完成相应功能?br />
MVC架构有如下优点:

?多视图用同一模型。模型与视图分离允许多视图用同一企业模型。因此,企业U应用模型组件容易实现、测试和l护?br />
?Ҏ支持新类型的客户端。支持一个新cd的客LQ只需写一个视囑֒控制Q然后把它连到现存的企业模型中?br />
分析Java Pet Store应用

视图

视图是用L面和应用E序的接口。在Java Pet Store中,视图在Web层实现。共有三U组件实现视图:JSP面、JSP自定义标记和JavaBean。视N分涉及到三方面内容:

1.屏幕

屏幕是一个页面显C的所有内宏V根据需要,在ScreenDefinitions.jsp中定义如下屏q:

																												
																														
NameQMAIN_SCREENQDEFAULT_SCREEN
    NameQCATEGORY_SCREEN
    NameQSEARCH_SCREEN
    NameQPRODUCT_SCREEN
    NameQPRODUCT_DETAILS_SCREEN
    NameQCART_SCREEN
    NameQCHECKOUT_SCREEN
    NameQPLACEORDER_SCREEN
    NameQCOMMIT_ORDER_SCREEN
    NameQSIGNIN_SCREEN
    NameQSIGNUP_SCREEN
																												
																										


2Q模?br />
因ؓ要整个|站的页面具有相同的特征Q如每个面都要有Logo、Banner{相同的元素Q所以采用模板定义页面的不同l成部分。本CZ中定义的模板元素有footer.jsp、banner.jsp和index.jsp{。ScreenDefinitions.jsp定义好的屏幕包括q些模板元素Q通过include指o包含到页面中

3Q视N择

视图的选择是通过控制来完成的。控制根据实际情况分析用hC囄IDQ运行模板把整个视图昄出来Q如?所C?br />


? 视图选择

模型

模型的状态是视图昄的数据来源,也是控制的具体对象。在J2EE中,描述模型的状态采用三UEJBQ无状态会话EJB、有状态会话EJB和实体EJB?br />
1Q辅助对?br />
有两U主要的辅助对象Q数据库讉K对象和值对象。对于实体EJB来说Q数据库讉K对象装了数据库讉K的方法,如AccountDAO{。对于所有EJB的属性|则都׃个值对象来装Q如ShoppingCartModel、AccountModel{?br />
2QEJBs

本示例用到的EJBs如图7所C?br />


? Java Pet Store使用到的EJBs

3Q模型状态到视图的绑?br />
一个模型对应多个视图,实现视图的绑定方法是QModelUpdateListener和ModelUpdateNotifier实现了一U注?监听模式Q通过调用监听器的performUpdateҎ来视图得到更新。例如:

																																		
																																				
public class AccountWebImpl extends AccountModel
implements ModelUpdateListener{
 private ModelManager mmQ?
 private Account acctEjbQ?
 public AccountWebImpl(ModelManager mm){
  super(nullQnullQnull}Q?
  this.mm=mmQ?
  mm.addListener(JNDINames.ACCOUNT_EJBHOMEQthis)Q?
 }
 public void performUpdate(){
  if(acctEjb==null)  {
   acctEjb=mm.getAccountEJB()Q?
  }
  try{
   if(acctEjb !=null)copy(acctEjb.getDetails())Q?
  }catch(RemoteException re){
   throw new GeneralFailureException(re)Q?
  }
 }
}
																																		
																																


控制

控制负责处理用户h、调用相应的模型、更新模型的状态、刷新视图以及返回用户合理的面。示例的所有控制对象如?所C?br />


? 控制对象?br />
1QRequestProcessor

RequestProcessor接收q处理用L所有请求,调用RequestToEventTranslator对象把请求{换成预定义的事gQ在事g处理完成后,q行视图更新?代码如下所C:

																																		
																																				
public class RequestProcessor{
     private ShoppingClientControllerWebImpl sccQ?
     private ModelManager mmQ?
     private ModelUpdateNotifier munQ?
     private RequestToEventTranslator eventTranslatorQ?
     private SecurityAdapter securityAdapterQ?
     public void init(...)  {
      mm = (ModelManager)session.getAttribute("modelManager")Q?
      mun = mmQ?
      SCC = new ShoppingClientControllerWebImpl(session)Q?
      eventTranslator= new RequestToEventTranslator(thisQmm)Q?
     }
     public void processRequest(HttpServletRequest req){
      checkForWebServerLogin(req)Q?
      EStoreEvent event = eventTranslator.processRequest(req)Q?
      if (event != null){
       Collection updatedModelList = scc.handleEvent(event)Q?
       mun.notifyListeners(updatedModelList)Q?
      }     
     }
    }
																																		
																																


2QShoppingClientControllerWebImpl

ShoppingClientContronerWebImpl是调用EJB层的ShoppingClientController代理对象Q代码如下所C:

																																		
																																				
public class ShoppingClientControllerWebImpl{
     private com....ejb.ShoppingClientController sccEjbQ?
     private HttpSession sessionQ?
     public ShoppingClientControllerWebImpl(HttpSession session){
      this.session = sessionQ?  
      ModelManager mm= (ModelManager)session.getAttribute("modelManager")Q?
      sccEjb = mm.getSCCEJB()Q?   
     }
     public synchronized AccountModel getAccount(){
      return sccEjb.getAccount().getDetails()Q?
     }    
     ......   
     public synchronized Collection handleEvent(EStoreEvent ese){
      return sccEjb.handleEvent(ese)Q?
     }
     public synchronized void remove()  {
      sccEjb.remove()Q?
     }
    }
																																		
																																


3QShoppingClientController

ShoppingClientController是有状态的会话EJBQ它为每个用户徏立一个单独的实例Q负责购物R和̎L生命周期Qƈ负责处理事g。同时它也控制状态机StateMachine的生命周期。代码参见赛q网http://linux.ccidnet.com的期刊浏?003q第6期?br />
4QStateMachine

StateMachine实现核心的业务逻辑Q它负责改变模型的状态,包括处理每个业务事g的方法。代码参见赛q网http://linux.ccidnet.com的期刊浏?003q第6期?br />
  

  J2EE|站的开发方法,xInternet的开发方法。Internet开发的发展可以划分Z个阶D:W一阶段是将业务逻辑和表现逻辑完全集成在一P采用HTML、JSP和Servlets技术开发;W二阶段是将业务逻辑和表现逻辑分开Q采用HTML、JSP、Servlets、JavaBeans Compoments和Custom Tags技术开发;W三个阶D|MVC设计模式QJ2EE的开发方法)。今天,MVC设计模式已成为Internet开发发展的L。无论是通过W一阶段开发的应用Q还是通过W二阶段开发的应用Q都会面临着开发h员的分工、应用的可维护性和可扩展性及可测量性的问题。ؓ此,我们在设计阶D关心的重点是系l结构的复杂E度、代码之间的耦合度、代码的易维护性、应用框架的可重用性、EJBlg的可重用性和易测试性,以及不同技能开发h员的分工{。用U观全局的眼光来看,在Internetpȝ开始设计的时候,p考虑开发、运行、维护阶D늚问题

 



JAVA之\ 2006-09-11 21:17 发表评论
]]>
利用J2EE模式构徏|站http://www.tkk7.com/xixidabao/archive/2006/06/18/53638.htmlJAVA之\JAVA之\Sun, 18 Jun 2006 13:26:00 GMThttp://www.tkk7.com/xixidabao/archive/2006/06/18/53638.html 利用J2EE模式构徏|站 作者:李志
 

一、前a

    本文以一个教学网站的思\ZQ探讨利用J2EE技术和WebSphere产品构徏|站的模式和Ҏ?/p>

二、设计网站系l?/a>

    我们的样例是一个教学网站系l,它的软g包括WebSphere Application Server应用服务器Y件V4.0、WSAD开发工具和DB2数据库(非商业用途)Q硬件ؓIBM xSeries服务器。在本文中,主要探讨MVC的开发模型和常用的J2EE模式Q关于网站徏讄其他l节qq不提了?/p>

Q一Q系l用例图

    分析|站的系l目标后Q我们首先具体化pȝ功能QŞ成一张用例图Q定义一pd的可重构lgQ以指导随后的开发工作?/p>

 ? Use Case picture
? Use Case picture

 

Q二Q组件化设计

    在构造网站系l时Q我们把每层的系l想象成拥有多个"?的装|,开发h员可以向槽中插入lg以扩大其能力Q也可以通过l承或其他机制具体化lgpȝ。这些组件可以是开发h员ؓ该应用系l开发的Q也可以是以前开发好的复用组件。在q种分层体系l构中,每个应用pȝ都表CZؓ一个单独的pȝ。每个系l都采用lg构造。每个组件系l又可以通过其他下层lgpȝ构造。重构h员采用一l与特定应用pȝ领域和业务有关的lg或顶层中的组件系l来构造每个应用系l?/p>

    l合J2EEQ让我们首先了解J2EE体系中的lg构成情况Q如?所C?/p>

?  J2EElg打包{略
? J2EElg打包{略

 

    在上图中可以看出Q不同的lg归档C同的文g包中Q这样就保证了一个组件的"插拔"不会影响到其它的lg。根据应用系l组件的功能Q我们可以把它们分ؓ动态组件和静态组件。静态的lg包含|页文gQ主要用于放|教学资料和参考文章。动态组件则包括各种功能模块Q如论坛pȝ、模拟测验系l等?/p>

    应用pȝlg之下是于特定业务有关的组件。在q里Q我们可以添加非Java~写的一些程序,用于处理特定内容下的操作Q比如模拟测验系l中的出题模块。当Ӟ要考虑C层组件调用的正面接口问题。对于这层组Ӟ我们能够随时替换Q只要其提供的数据符合上U正面的要求?/p>

    以上两lg之下是J2EE应用服务器和操作pȝQ整体如?所C?/p>

? 计算机组成原理网站系l组件架构图
? 计算机组成原理网站系l组件架构图

 

Q三Q利用J2EE模式开发组件系l?/p>

    下面着重介l开发过E中使用的J2EE模式Q这些模式都是通用cd的?/p>

    本系l采用MVC开发模型,即Model-View-Controller。Model是指应用E序的数据,以及对这些数据的操作QView是指用户界面QController负责用户界面和程序数据之间的同步。这U模型的好处在于分离不同功能的代码,便于以后的维护,q有利于在项目小l内按照组成员各自的擅长进行分工,有利于三个部分ƈ行开发、加快项目进度?/p>

    Z使各开发h员协调一_为其他组件提供一致和标准的正面,增强pȝ的可l护性和可复用性,我们q泛采用了SUN公司提出的基于MVC的设计模式?/p>

    ?是用h册模块的UML图,我们结合这个模块具体阐q各模式的特点和在本pȝ中的实际应用?/p>

? 表示层模? src=
? 表示层模?

 

    明确了所采用的体pd模式Q下面具体设计类的属性和ҎQ通过设计完善的接口和l承、重载等Ҏq行重构。模块的UML的类图表C如下:

? 模块的UML的类? src=
? 模块的UML的类?

 

l合上图Q让我们看看q个模块中都q用了哪些模式?/p>

1. 表示层模?/b>

    pȝ的表C层集中了MVC模式中的View与Controller。该pȝ用JSP代表ViewQ用Servlet代表Controller。在Controllerq一模块中,又采用了视图助手、分发者与值对象模式,以增强系l的模块化,提高l护性?/p>

Q?Q前端控制器

控制器通常表现为Servlet形式Q其UML表示如下Q?/p>

? 前端控制? src=
? 前端控制?

 

    ҎModel-View-Controller的开发思想Q用控制器作ؓ处理h的最初联pȝ。该控制器管理着h的处理,包括调用安全服务Q比如验证和授权、委托业务处理、管理合适的视图选择、处理错误,以及理内容创徏逻辑的选择。也可以把前端控制器看成一个触发器Q由它来启动程?/p>

    下面是功能代码的h。其中出现的RegisterHelper、Command{类Q接下来会有详细介绍?/p>

   public void performTask(javax.servlet.http.HttpServletRequest request,
		javax.servlet.http.HttpServletResponse response)
		throws javax.servlet.ServletException, java.io.IOException 
   {
   	   RegisterHelper rh=new RegisterHelper(request,response);//启动注册视图助手
   	   Command command=rh.getCommand();//p囑֊手中获得q初始化Command
   	   CustomerBean cb=rh.getCustomerBean();//p囑֊手中获得q初始化值对?
   	   request.setAttribute("customerbean",cb);
   	   String dispatcher=rh.getDispatcher();//p囑֊手中获得q初始化分发?
	   request.setAttribute("type",rh.getType());//讄上下文属?
   	   try {
   	    command.execute((Helper)rh);//执行业务代码
   	   } catch(javax.ejb.DuplicateKeyException de) {
		request.setAttribute("errorbean",new ErrorBean("对不P已经有h注册了该用户?"));//注册重名处理
		dispatch(request,response,dispatcher);//分发q移交控制权
		return;
   	   } catch(Exception e) {
   		request.setAttribute("errorbean",new ErrorBean("对不P数据库出?"));//出错处理
		dispatch(request,response,dispatcher);
		return;
   	}
   	   dispatch(request,response,dispatcher);
    
   }
   

    优点Q通过集中化决{点和控Ӟ控制器有助于减少嵌入在JSP中Java代码QScriptletQ的数量Q保持View功能的纯z性。它的位|如?中Controller所C?/p>

Q?Q视囑֊?/p>

    表示层更改经常发生,而且当业务数据访问逻辑和表C格式化逻辑被؜杂时Q表C层更改很难开发和l护。这使系l灵zL更差,更缺乏可用性,而且对变化的适应性更弱?/p>

? 视图助手
? 视图助手

 

    视图包含格式化代码,把其处理责Q委托l其助手cR助手也存储该视囄中间数据Q如表单、URL参数{,q且充当业务数据适配器?/p>

下面是功能代码的h?/p>

public class RegisterHelper implements Helper {

	static String dispatcher = "RegisterDispatcher";
	private CustomerBean customer = null;
	private String type = null;
	
	public RegisterHelper(
		javax.servlet.http.HttpServletRequest request,
		javax.servlet.http.HttpServletResponse response) {
		setType(request);
		setCustomerBean(request);		
	}

	/**
	 * 定义面cd:HTML or XML
	 */
	public void setType(javax.servlet.http.HttpServletRequest request) {
		type = request.getParameter("type");
	}

	/**
	 * 获取Command
	 */
	public Command getCommand() {
		RegisterCommand rc = new RegisterCommand();
		return rc;
	}

	/**
	 * 向值对象中填充数据
	 */
	public void setCustomerBean(javax.servlet.http.HttpServletRequest request) {
		customer = new CustomerBean();
		customer.setUsername(request.getParameter("username"));
		customer.setPassword(request.getParameter("password"));
		customer.setEmail(request.getParameter("email"));
		customer.setTruename(request.getParameter("truename"));
		customer.setId(request.getParameter("id"));
		customer.setService(this.setService(request));
	}
	/**
	 * 获取值对?
	 */

	public CustomerBean getCustomerBean() {
		return this.customer;
	}

	/**
	 * 获取分发?
	 */
	public String getDispatcher() {
		return this.dispatcher;
	}

	/**
	 * 获取cd
	 */
	public String getType() {
		return type;
	}
}

    优点Q在助手中而不是在视图中封装业务逻辑会增强应用程序的模块化,q且更有利于lg重用。助手有大量的责任,包括攉视图和控刉要的数据Q以及存储中间模型。它的位|如?中Helper所C?/p>

Q?QCommand模式

    Command中包含纯业务代码Q如注册、登陆、检验等。在样例模块中,它的职责是将注册信息传递给Entity Bean?/p>

? Command
? Command

 

功能代码如下所C:

      public void execute(Helper helper) throws Exception 
   {
      RegisterHelper rh = (RegisterHelper) helper;//获取视图助手
		CustomerBean cb = rh.getCustomerBean();//从视囑֊手中获取值对?
		ServiceLocator sl = ServiceLocator.getInstance();//初始化服务定位器
		CustomersHome ch = (CustomersHome) sl.getHome(ServiceLocator.Services.CUSTOMERS);//从服务定位器中获取Entity Bean本地接口
		try {	
			Customers customers = ch.create(cb);//注册信息导入数据库
		} catch(javax.ejb.DuplicateKeyException e) {
			throw new javax.ejb.DuplicateKeyException();
		} catch(Exception e) {
			throw e;
		}
	
   }
   

Q?Q分发者模?/p>

    如果表C化逻辑和业务逻辑混合在视图中Q会使系l可重用性和灉|性变差,而且一半还会更改操作难以实施。分发者负责视囄理和DQ选择下一个视图,q且提供分发资源控制的机制。分发者可以提供静态的分发Q也能提供更高的动态分发机制?/p>

    在我们的目中,׃涉及到PC用户和移动手机用L讉KQ我们需要针对不同的用户q回不同的结果页面,因此分发者的存在非常有必要。分发者表CؓServlet形式Q它承接Controller的处理结果,q判断用LcdQ把正确的视图返回给用户。它的位|如?中Dispatcher所C?/p>

? 分发? src=
? 分发?

 

功能代码如下所C:

		public void performTask(
		javax.servlet.http.HttpServletRequest request,
		javax.servlet.http.HttpServletResponse response)
		throws javax.servlet.ServletException, java.io.IOException {
		String type=(String)request.getAttribute("type");//获取面cd
		isError=(request.getAttribute("errorbean")!=null)?true:false;//判断是否出错
		String file=selectType(type,isError,response);//Ҏ面cd和是否出错确定显C页?
		getServletConfig().getServletContext().getRequestDispatcher(file).forward(request,response);//重定向到昄面
	}
	
	public String selectType(String str,boolean isError,javax.servlet.http.HttpServletResponse response) {
		if (str.equals("html")) {//HTMLcd的页?
			if (isError) {//成功
				System.out.println("Some error happens!");
				return "register_error.jsp";
			} else {//出错
				return "register_ok.jsp";
			}
		} else {//WML手机面
			if (isError) {//成功
				System.out.println("Some error happens!");
				return "wml/register_error.jsp";
			} else {//出错				
				response.setContentType("text/vnd.wap.wml;charSet=gb2312");
				return "wml/register_ok.jsp";
			}
		}
	}
	

Q?Q复合视?/p>

    复杂的Web面可以展示来自多个数据源的内容Q用多个包含单昄面的子视图。同Ӟh不同技能的多个开发h员可以参与这些Web面的开发和l护?/p>

    因此Q我们采用有多个原子视图l成的复合视图。模版中每个lg是动态结合在一LQƈ且页面的布局是独立于内容q行理的。在我们的项目中Q采用了<jsp:include page="***" flush="true">嵌入面QD栏和标示独立于各个页面,使用戯够及时地看到M变动Qƈ使系l更改的代h降低到最?/p>

2. 业务层模?/b>

Q?Q值对?/p>

    J2EE应用E序把服务器端业务组件实CؓSession Bean和Entity Bean。业务组件的一些方法可以向客户端返回数据。通常Q客L需要多ơ调用业务对象的get/setҎ直到获得所有的属性倹{由于EJB的调用采用RMI-IIOP方式通过|络q行Q这样做大大延缓了业务层的处理速度Q降低了效率?/p>

    Z解决q一问题Q我们用值对象封装业务数据。相应的Ҏ调用是设|和索值对象。当客户端向企业beanh业务数据Ӟ该企业bean可以构造值对象,用属性值来填充Qƈ且按照值把它传递给客户端,q也W合EJB端粗_度调用的需要?/p>

    值对象是可串行化的JavaBean对象。值对象类也可以提供接收所有必ȝ属性以创徏该值对象的构造器。通常Q值对象中的成员被定义为私有的Q而其Get/SetҎ则是公有的?/p>

?0值对? src=
?0值对?

 

如图10所C,作ؓCZ的CutomerBean中包含了对应Entity Bean所需的属性及其访问方法?/p>

Q?Q服务定位器

    J2EE客户端与EJBlgq行交互Q这些组件提供业务服务和持久性能力。ؓ了与它们交互Q客L必须定位Q或UCؓ查找Q该服务lgQ或创徏一个新的组件。比如,EJB客户端必d位EJB的本地对象,然后客户端用该本地对象来查找某对象Q或者创建或删除一个或多个EJB?/p>

    q样Q对于所有需要访问JNDI理的服务对象的客户端而言Q都需要进行定位工作。在需要查找服务的客户端中Q会D不必要的代码重复现象。同Ӟ创徏最初JNDI环境和在EJB本地对象上执行查N会占用大量的资源。如果多个客L反复地请求相同的bean本地对象Q这U重复现象会严重影响应用E序性能?/p>

    我们使用服务定位器对象来抽取所有的JNDI应用Qƈ且隐蔽最初环境创建、EJB本地对象查找和EJB对象重创建的复杂性。多个客L可以重新使用服务定位器对象来降低代码的复杂性,提供单控制点Qƈ且通过提供~冲机制来提高性能?/p>

    该模式降低了来自于客L依赖性的客户端复杂性,q且需要执行查扑֒创徏q程Q这些都是非常消耗资源的。ؓ了消除这些问题,该模式提供了把所有依赖性和|络l节抽取到服务定位器的一U机制。它的位|如?1中ServiceLocator所C?/p>

?1 服务定位? src=
?1 服务定位?

 

功能代码如下所C:

public class ServiceLocator 
{
   	private static ServiceLocator me;
	InitialContext context = null;
   /**
    * 初始化上下文
    */
   public ServiceLocator() 
   {
		try {
			context = new InitialContext();
		} catch (NamingException e) {
			e.printStackTrace();
		}    
   }
	public class Services {
		//为EJB讑֮h序号
		final public static int CUSTOMERS=0;
		final public static int PARTNERS=1;
		final public static int ADMINISTRATORS=2;
		final public static int PERMITS=3;
		final public static int PAPERBROKER=4;
		final public static int CHECK=5;
	}
	final static Class CUSTOMERS_CLASS=CustomersHome.class;
	final static String CUSTOMERS_NAME="CustomersHome";
	final static Class PARTNERS_CLASS=PartnersHome.class;
	final static String PARTNERS_NAME="PartnersHome";
	final static Class ADMINISTRATORS_CLASS=AdministratorsHome.class;
	final static String ADMINISTRATORS_NAME="AdministratorsHome";
	final static Class PERMITS_CLASS=PermitsHome.class;
	final static String PERMITS_NAME="PermitsHome";
	final static Class PAPERBROKER_CLASS=PaperBrokerHome.class;
	final static String PAPERBROKER_NAME="PaperBrokerHome";
	final static Class CHECK_CLASS=CheckHome.class;
	final static String CHECK_NAME="CheckHome";
	public static ServiceLocator getInstance() {//单线E处理以节省资源
		if (me == null)
			me = new ServiceLocator();
		return me;
	}   
	static private Class getServiceClass(int service) {
		switch(service) {
			case Services.CUSTOMERS:
				return CUSTOMERS_CLASS;
			case Services.PARTNERS:
				return PARTNERS_CLASS;
			case Services.ADMINISTRATORS:
				return ADMINISTRATORS_CLASS;
			case Services.PERMITS:
				return PERMITS_CLASS;
			case Services.PAPERBROKER:
				return PAPERBROKER_CLASS;
			case Services.CHECK:
				return CHECK_CLASS;
		}
		return null;
	}
	static private String getServiceName(int service) {
		switch(service) {
			case Services.CUSTOMERS:
				return CUSTOMERS_NAME;
			case Services.PARTNERS:
				return PARTNERS_NAME;
			case Services.ADMINISTRATORS:
				return ADMINISTRATORS_NAME;
			case Services.PERMITS:
				return PERMITS_NAME;
			case Services.PAPERBROKER:
				return PAPERBROKER_NAME;
			case Services.CHECK:
				return CHECK_NAME;
		}
		return null;
	}
   /**
    * q回EJB本地接口
    */
   public EJBHome getHome(int s) 
   {
    	EJBHome home = null;
		try {
			Object objref = context.lookup(getServiceName(s));
			home = (EJBHome) PortableRemoteObject.narrow(objref, getServiceClass(s));

		} catch (NamingException e) {
			e.printStackTrace();
		}
		return home;
   }
}

~点Q如果增加新的EJBQ需要修Ҏ务定位器的代码?/p>

    以上q些模式都是可以通用的,在实际应用中q用q些模式Q不仅加快了开发进度,而且开发h员各司其职,避免了代码的混ؕQ取得了比较好的效果?/p>

三、ȝ

    本文记述了根据J2EE模式和MVC开发模型,利用IBM公司的WebSphere应用服务器来l织|站的心得和体会。大家的目cd也许会有不同Q但开发的模式M有相通之处。善于根据实际情况选择开发模式,可以提高开发效率和代码质量Q但也不要一xq模式不放Q量体裁衣才能游刃有余?/p>



JAVA之\ 2006-06-18 21:26 发表评论
]]>
ZJ2EE的电子商务网站实例解?/title><link>http://www.tkk7.com/xixidabao/archive/2006/05/26/48358.html</link><dc:creator>JAVA之\</dc:creator><author>JAVA之\</author><pubDate>Fri, 26 May 2006 08:21:00 GMT</pubDate><guid>http://www.tkk7.com/xixidabao/archive/2006/05/26/48358.html</guid><description><![CDATA[ <b>摘要Q?/b>本文以实例来详细分析q用J2EE技术架构来搭徏企业U电子商务网站的全过E,q对关键部g的实C及相x术进行具体剖析,同时l合W者经验,提出很多有h值的思\和方法?br /><br />  <b>一Q?前言Q?/b><br /><br />  q年来,随着互联|业务的q猛发展Q企业间、企业与消费者间实现电子商务已经成ؓ可能Q徏立企业的电子商务^C仅可以拓宽企业的营销渠道Q而且Ҏ升企业品牌Ş象等斚w有重要的战略意义?br /><br />  本文以目前国内最大服务交易^台如易网Qhttp://www.routease.com/Qؓ例,来深入剖析一个电子商务交易^台搭建的全过E?br /><br />  《准备篇?br /><br />  一个项目的实施首先定目目标、项目需求与开发环境(为方便理解,如易网作ؓ目来描qͼ。本主要讨三个斚wQ?<br /><br />  一.实施目标<br /><br />  如易|的创办目标Q徏设ؓ国内最大的服务cM易^台和在线工作q_。由于本以技术讲解ؓ主,如要了解更多的背景资料,可以讉KQhttp://www.routease.com/AboutUs.htm ?br /><br />  ?实施需?br /><br />  目标军_需求,定制清晰明确的项目需求是整个目成|的关键。可以用Rose工具来徏立项目对象实体图Q这里就不再赘述了,以下几个重要对象做一些描qͼQ可以对照http://www.routease.com/来浏览下面内容)Q?br /><br />  TotradeEntity:交易实体对象。该对象为核心对象,标识交易的服务对象。比如翻译服务,开锁服务等?<br /><br />  ServiceRequirementQ服务需求对象。该对象标识用户需求。比如需要电脑维修的信息{?br /><br />  SHOP:店铺对象。该对象Z企业或者个人开的网店,一个店铺对应多个交易实体?br /><br />  USER:用户对象。该对象标识从事|站的合法注册用P它保留用户信息?br /><br />  Account:帐户对象。该对象标识用户的帐户信息?br /><br />  Message:消息对象。该对象标识用户之间交流的信息?br /><br />  CreditQ信誉对象。该对象标识用户交易的信誉等U信息,Z易提供有力参考?br /><br />  ?开?q行环境<br /><br />  Z以上需求分析,本站采用J2EE/Structs应用架构Q服务器L采用WIN2003 SERVER+APACHE2.0.54+TOMCAT 5.5.4的系l环境,开发环境:Eclipse+JDK1.5Q数据库DAO采用的著名的ORM工具TopLink9.0.4.5。以下对相应开发技术及其工具做一个简要介l:<br /><br />  1Q?Structs技?br /><br />  Web应用的开发经历了一个由P2PQPage to PageQ到MVC(model view controller)的发展过E。早期的Web应用对用戯求的处理和响应均是在面上完成的Q如?-1所C,x的JSP1.0。这LWeb架构最大的好处是开发效率较高,然后q几q随着互联|的q猛发展Q网站功能日益增强,而这UP2P的网站架构(因ؓ其业务规则代码与面代码混ؓ一团,不利于维护)已经不再适应大规模应用的发展要求Q取而代之的是基于MVC的Web架构。MVC的核心思想是将应用分ؓ模型、视囑֒控制器三部分。模型是指应用程序的数据Q以及对q些数据的操作;视图是指用户界面Qcontroller负责用户界面和程序数据之间的同步Q也是完成两个方向的动作:a.在根据用L?view)的操作完成对E序数据(model)的更斎ͼb.程序数据(modelQ的改变及时反应到用L面(viewQ上。通过MVC的Web架构,可以弱化各个部分的耦合关系Qƈ业务逻辑处理与页面以及数据分d来,q样当其中一个模块的代码发生改变Ӟq不影响其他模块的正常运行,所以基于MVC的Web架构更适应于大规模软g应用开发的潮流?<br /><br /><table width="90%" align="center" border="0"><tbody><tr><td><div align="center"><img style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="/imagelist/06/21/62bdhtjmdg27.gif" border="1" /><br />?<br /><img style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="/imagelist/06/21/ji519258055o.gif" border="1" /><br />?</div></td></tr></tbody></table><br />  目前ZMVC的开发框架主要有Structs、Spring{。本站选用其中的Structs作ؓ开发框Ӟ采用Structs应用框架开发应用程序,开发h员从J琐的代码编制中解放出来Q取而代之的是配|一些含有对应关pȝXML文gQ这样当应用环境发生变化Ӟ不需重新~译E序卛_q行Qƈ且得应用更加灵zR高?而且重用度高?br /><br />  从开发角度,Struts主要有如下的功能Q?br /><br />  ·包含一个controller servletQ能用Lh发送到相应的Action对象。通过Web.xml文g来配|其相关参数?br /><br />  ·tag库,q且在controller servlet中提供关联支持,帮助开发h员创Z互式表单应用?br /><br />  ·通过配置Structs-config.xml文gQ将Action对象与用戯求以及请求结果页面关联v来?br /><br />  如需更多了解Structs的相关信息,请其官方|站Qhttp://jakarta.apache.org/struts <br /><br />  2QTopLink技?br /><br />  q去Q对模型数据的存取访问往往是直接是应用通过ODBCq样的数据库接口讉K数据库。但是这样处理ƈ不符合OOP的精,而且应用开发h员必ȝ悉后台数据库的模型构造,q就加大开发的隑ֺ。ؓ此,ORMQObject Relational MappingQ技术应q而生.ORM技术实际是一个对象持久化的框Ӟ其核心思想是徏立了Java对象与后台数据库之间的映关pR这样对q些Java对象的访问实际就是对后台数据库的讉KQ从而屏蔽了数据库访问的l节Q开发h员甚臛_以在不了解后台数据库的情况下q行开发工作。此外,Toplink在数据缓存优化上也有很好的表现。本目采用著名的ORM工具Toplinkq行开发?br /><br /><br /><strong>《实施篇?/strong><br /><br />  本篇主要介绍该^台的具体实现q程。根据Y件工E的相关理论Q结合笔者多q的开发经验,|站开发一般尊循以下六步骤Q?br /><br />  1Q?攉、整理网站需求?br /><br />  2Q?Ҏ|站需求,构想|页的交互情景(即USE CASEQ?q设计出|站的原形(PrototypeQ?br /><br />  3Q?设计出实例化对象以及后台数据库结构?br /><br />  4Q?采用ORM工具Q徏立实例化对象与后台数据库之间的映关pR?br /><br />  5Q?Ҏ|站交互需求,定制后台ActionQ以处理用户动作?br /><br />  6Q?修改|站原ŞQPrototypeQؓ动态页面(JSP文gQ?Action处理l果嵌入到动态页面中q回l客L?br /><br />  在这六个步骤中,W一步实际已l在《准备篇》里已经l出了,下面重点讲解后面几个步骤?br /><br />  1Q?|站原ŞQPrototypeQ?br /><br />  |站原Ş是对一个网站功能的面U描qͼ即看到网站原形就好比看到一个真实的|站一P只是|站原Şq没有嵌入动态代码,而且面之间也缺乏关联而已?br /><br />  |站原Ş的开发ؓU静态页面的开发,制作|站原Ş的关键在于将|站功能需求{化ؓ人机界面?br /><br />  如易|的|站原Ş制作下蝲地址Q?a target="_blank">http://www.routease.com/download/ruyinew924.rar</a><br /><br />  2Q?OOP设计与后台数据库设计<br /><br />  借助强大的ORM开发工P可以OOP与数据库的设计同时进行(卛_以同时实施上面步骤的3Q?步)Q这也是ORM工具最大特炏V本目采用Oracle公司的Toplink作ؓORM开发工兗以下简要介lToplink开发过E?br /><br />  1Q?打开Toplink的Mapping WorkbenchlgQ然后新Z个Mapping 工程?br /><br />  2Q?配置工程的属性,卛_"选项"面板上设|工E\径以及Java对象源代码的路径?br /><br />  3Q?配置数据库登陆参敎ͼ包括应用讉K数据库的URL、用户名、密码等?br /><br />  完成以上三步Q就可以Ҏ应用的需求来开发JavacR在Mapping Workbench里新Z个描q符Q实际就是有一个Javac),Ҏ需求来d属性,q自动生成Set/GetҎ。一旦完成Javacȝ开发后Q选择"自动映射到数据库"的选项Q即可实现数据库表的自动创徏。(Toplink的最大优势就是在定制好JavacM后可以自动生成数据库的表l构Q?br /><br />  鉴于国内Toplink斚w的资料较,q里介绍一下Toplink生成的工E文件RouteaseMappingProject,该工E文件在web服务器启动的时候装载,可以理解为客L序对数据库访问的接口E序Q他有三cL法:<br /><br />  ·构造函?br /><br />  主要是调用oracle.toplink.sessions.Project的addDescriptorҎQ其作用是将数据库和Java对象之间的映关pd入到Project 中。代码示范如下:<br /><br /><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>public RouteaseMappingProject() {<br />addDescriptor(buildAccountDescriptor());<br />addDescriptor(buildPhoneDescriptor());<br />…?<br />}</td></tr></tbody></table><br />  ·applyLoginҎ<br /><br />  它处理客L序登陆数据,q|一些存取数据库的参敎ͼ比如~冲池等。代码示范ؓQ?br /><br /><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>public void applyLogin() {<br /> //配置数据库访问参?br /> DatabaseLogin login = new DatabaseLogin();<br /> login.usePlatform(new oracle.toplink.oraclespecific.Oracle9Platform());<br /> login.setDriverClassName("oracle.jdbc.driver.OracleDriver");  login.setConnectionString(ApplicationConfiguration.get(ConfigurationConstants.DB_CON_STR));  login.setUserName(ApplicationConfiguration.get(ConfigurationConstants.DB_USER));   login.setPassword(ApplicationConfiguration.get(ConfigurationConstants.DB_ENCRYPTED_PASSWORD));<br /> // 讄数据库参?br /> login.setUsesNativeSequencing(true);<br /> login.setSequencePreallocationSize(1);<br /> login.setShouldBindAllParameters(false);<br /> login.setShouldCacheAllStatements(false);<br /> login.setUsesByteArrayBinding(true);<br /> login.setUsesStringBinding(false);<br /> if (login.shouldUseByteArrayBinding()) { // Can only be used with binding.<br />  login.setUsesStreamsForBinding(false);<br /> }<br /> login.setShouldForceFieldNamesToUpperCase(false);<br /> login.setShouldOptimizeDataConversion(true);<br /> login.setShouldTrimStrings(true);<br /> login.setUsesBatchWriting(false);<br /> if (login.shouldUseBatchWriting()) { // Can only be used with batch writing.<br />  login.setUsesJDBCBatchWriting(true);<br /> }<br /> login.setUsesExternalConnectionPooling(false);<br /> login.setUsesExternalTransactionController(false);<br /> setLogin(login);<br />}</td></tr></tbody></table><br />  ·建立映射关系<br /><br />  Toplink通过cM于builXXXDescriptorҎ来徏立Java对象与数据库表字D之间的对应关系Q示范代码如下:<br /><br /><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>public Descriptor buildAccountDescriptor() {<br /> Descriptor descriptor = new Descriptor();<br /> descriptor.descriptorIsAggregate();<br /> descriptor.setJavaClass(com.routease.db.vo.user.Account.class);<br /> descriptor.setAlias("Account");<br /> // Mappings.<br /> //建立Account 对象的deposit属性与数据库表的DEPOSIT字段的对应关p?br /> DirectToFieldMapping depositMapping = new DirectToFieldMapping();<br /> depositMapping.setAttributeName("deposit");<br /> depositMapping.setFieldName("DEPOSIT");<br /> descriptor.addMapping(depositMapping);<br /> ?br /> return descriptor;<br />}</td></tr></tbody></table><br /><br /><br /> 3Q?定制后台Action<br /><br />  ҎMVC的精,View和Model设计好之后应该是开发重点{Ud控制器的开发上。控制器是根据用戯行响应的处理模块Q比如用户通过首页的搜索条Ҏ务信息进行检索,q时Qweb服务中的SearchToTradeEntityActionQ对应SearchToTradeEntityAction.java文gQ会对用戯一动作q行处理。以下对q一Actionq行详细分析Q?br /><br /><table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td>package com.routease.action.totradeentity;<br />import java.util.Collection;<br />import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpServletResponse;<br />import org.apache.commons.beanutils.PropertyUtils;<br />import org.apache.commons.lang.StringUtils;<br />import org.apache.struts.action.ActionForm;<br />import org.apache.struts.action.ActionForward;<br />import org.apache.struts.action.ActionMapping;<br />import com.routease.action.PagingAction;<br />import com.routease.action.helper.UserHelper;<br />import com.routease.db.dao.DataSource;<br />import com.routease.db.dao.totradeentity.SearchingCriteria;<br />import com.routease.db.dao.totradeentity.ToTradeEntityDAO;<br />import com.routease.db.util.Constants;<br />import com.routease.db.util.Page;<br />public class SearchToTradeEntityAction extends PagingAction {<br /> public SearchToTradeEntityAction() <br /> {<br />  super();<br /> }<br /> // executeWithDataSourceҎAction默认执行的方?br /> public ActionForward executeWithDataSource(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response, DataSource ds) throws Exception {<br />  //首先接受用户提交的表单数?br />  String objective = (String) PropertyUtils.getSimpleProperty(actionForm, "objective");<br />  String keyWords = (String) PropertyUtils.getSimpleProperty(actionForm, "keyWords");<br />  String keyWordsRange = (String) PropertyUtils.getSimpleProperty(actionForm, "keyWordsRange");<br />  if (StringUtils.isEmpty(keyWordsRange)) {<br />   keyWordsRange = SearchingCriteria.KEY_WORDS_RANGE_NAME;<br />  }<br />  String industryLevel1 = (String) PropertyUtils.getSimpleProperty(actionForm, "industryLevel1");<br />  String industryLevel2 = (String) PropertyUtils.getSimpleProperty(actionForm, "industryLevel2");<br />  String startingPrice = (String) PropertyUtils.getSimpleProperty(actionForm, "startingPrice");<br />  String endingPrice = (String) PropertyUtils.getSimpleProperty(actionForm, "endingPrice");<br />  String city = (String) PropertyUtils.getSimpleProperty(actionForm, "city");<br />  String province = (String) PropertyUtils.getSimpleProperty(actionForm, "province");<br />  String startNoStr = (String) PropertyUtils.getSimpleProperty(actionForm, "startNumber");<br />  String lengthStr = (String) PropertyUtils.getSimpleProperty(actionForm, "length");<br />  if (StringUtils.isEmpty(startNoStr)) {<br />   startNoStr = "1";<br />  }<br />  //Ҏ用户提交的数据,创徏查询表达式对象SC<br />  int startNumber = Integer.parseInt(startNoStr);<br />  int length = UserHelper.getPagingLength(ds, request);<br />  ToTradeEntityDAO serviceDAO = new ToTradeEntityDAO(ds);<br />  SearchingCriteria sc = new SearchingCriteria();<br />  sc.setCity(city);<br />  sc.setProvince(province);<br />  sc.setEndingPrice(endingPrice);<br />  sc.setIndustryLevel1(industryLevel1);<br />  sc.setIndustryLevel2(industryLevel2);<br />  sc.setKeyWords(keyWords);<br />  sc.setKeyWordsRange(keyWordsRange);<br />  sc.setObjective(objective);<br />  sc.setStartingPrice(startingPrice);<br />  if (Constants.IS_TEST) {<br />   System.out.println("start of page:" + startNumber);<br />  }<br />  //提交查询对象SC,q获得查询结果集Q将其结果集攑օRequest对象中,便于q回<br />  Page result = serviceDAO.searchToTradeEntities(sc, startNumber, length);<br />  Collection industries = serviceDAO.findIndustryDistribution(sc);<br />  result.setSizePerPage(length);<br />  request.setAttribute(Constants.TO_TRADE_ENTITY, result);<br />  request.setAttribute("MY_INDUSTRIES",industries);<br />  request.setAttribute("MY_PAGE", result);<br />  //业务逻辑处理完毕之后Q返回成功页?br />  return actionMapping.findForward("SUCCESS_PAGE");<br /> }<br />}</td></tr></tbody></table><br />  SearchToTradeEntityAction是一个典型的ActionQ由前面注解不难看出Q一般Action分ؓ三部分:<br /><br />  a. 接受用户表单数据<br /><br />  b. 处理用户表单数据<br /><br />  c. q回处理l果及页?br /><br />  4Q?修改面为JSP文g<br /><br />  凡是涉及C用户状态相关的面均应攚wؓ动态页面(JSP文gQ,攚w是在前面静态文件的基础上进行的Q用服务器端q回的数据(存放在Request对象里)替换静态文本,׃q部分相Ҏ术性不强,所以不再详l赘qC?br /><br />  通过前面四部分的介绍Q基本概qC如易|技术实施的主要q程Q在下面的一章里介绍|站技术中的几个重要技巧?br /><br /><br /><b>《完l篇?/b><br /><br />  本篇主要介绍|站实施q程中的几个重要技巧和思\Q最后还介l网站维护方面的内容?br /><br />  一. 加快|站速度<br /><br />  量以静态html文gZQ由于静态文件不需要WEB服务器解析而直接返回给客户端,所以速度更快?br /><br />  对网站实时性不强的动态文件可以采用后台定期刷新的机制来{化ؓ静态文件或者js文gQ如易网首页中的"推荐服务"栏目实际是采用q种机制,但是对实时性要求较强的交易环节是不适合用这U方式的?br /><br />  另外一U加快网站速度的方法就是将频繁讉K数据库的信息攑֜内存中,在web服务器启动的时候加载进来,q种以ؓI间换时间的思\也值得借鉴?br /><br />  二. 服务器监管理流E?br /><br />  一般企业服务器都是采用独立服务器Q需要专人维护,但是q样成本较高Q有必要开发一套后台监控程序来对系l资源,数据/E序备䆾做监,用技术手D|降低成本?br /><br />  如易|后台监控程序实现思\是:分两个线E,一个进E监服务器的内存、磁盘资源以及数据库、Web服务{相兛_用的状态,一旦发现有异常Q将以Email或短信的形式通知pȝ理员;另外一个进E主要对数据q行周期性的备䆾Qƈ备份通过ftp上传x定备用服务器?br /><br />  本系l管理程序在|站q行期间起到重要的安全保障作用,而且也基本不需要h工干预,减少了h力成本,值得中小企业借鉴?br /><br />  三. 自助营销q_<br /><br />  对企业电子商务^収ͼ营销ؓ重要。通过不同路径攉营销数据库,q定期给用户发送企业品信息,q一切过E采用程序的方式实现Q方便,省事?br /><br />  最后,要介l一下网站维护的事宜。网站一旦运营v来,必须保证?*24时的全天候正常运行。所以,|站后期的维护极为重要。根据笔者经验,主要需要做好以下几个方面:<br /><br />  1Q?定期做好数据备䆾和程序备份?br /><br />  2Q?做好|站安全防护工作Q对重要文g和目录设|访问权限,架设防火墙,关闭不用的端口。定期更Ҏ务器的密码,防止黑客入R?<br /><br />  3Q?ME序U的修改必须l过试环境的验证之后才能发布到生环境Q要有套严格的发布流E?br /><br />  做好以上三个斚wQ网站的正常q行基本可以保证?br /><br />  <b>l束语:</b><br /><br />  本文重点介绍了网站实施过E中的技术框架和实现ҎQƈl合实例分析了其中运用到的相x术。实践证明,q套思\建立h的网站架构稳定高效,h很高的应用h倹{?br /><br /><img src ="http://www.tkk7.com/xixidabao/aggbug/48358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/xixidabao/" target="_blank">JAVA之\</a> 2006-05-26 16:21 <a href="http://www.tkk7.com/xixidabao/archive/2006/05/26/48358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://tzfzs.com" target="_blank">һѸ</a>| <a href="http://www678678.com" target="_blank">˳ձ߹ۿ</a>| <a href="http://www132126.com" target="_blank">Ƶ</a>| <a href="http://8222se.com" target="_blank">޹ۺ߾Ʒ</a>| <a href="http://juytv.com" target="_blank">˳ӰԺ77777</a>| <a href="http://342030.com" target="_blank">ƬվŮ</a>| <a href="http://3hc88.com" target="_blank">þҹɫƷAV </a>| <a href="http://www-kj5799.com" target="_blank">޾Ʒѹۿ</a>| <a href="http://1314a.com" target="_blank">ĻƵ</a>| <a href="http://yeyaweiban.com" target="_blank">ɫַ</a>| <a href="http://sdkjkj.com" target="_blank">鶹һѲվ</a>| <a href="http://tccqdy.com" target="_blank">2020þþƷۺһ</a>| <a href="http://mangaou.com" target="_blank">޾ƷѶ</a>| <a href="http://zzzttt669.com" target="_blank">޴߶רһ</a>| <a href="http://an930.com" target="_blank">jizzjizzƵȫ</a>| <a href="http://xbooktxt.com" target="_blank">Ѿþþþþ</a>| <a href="http://44od.com" target="_blank">޳AVƬ</a>| <a href="http://liuxilife.com" target="_blank">1024Ѹùۿվ</a>| <a href="http://longcais.com" target="_blank">պĻ</a>| <a href="http://yy1514.com" target="_blank">޹˾þۺҰ</a>| <a href="http://www456788.com" target="_blank">Ļ߳ѿ</a>| <a href="http://xwy2.com" target="_blank">þþŷղAV</a>| <a href="http://microston.com" target="_blank">޶߹ۿ </a>| <a href="http://pengkaimjg.com" target="_blank">ɫ͵͵ɫݺ99</a>| <a href="http://sds54.com" target="_blank">˾Ʒ</a>| <a href="http://spxingyiquan.com" target="_blank">һëƬԿ60Ѳ</a>| <a href="http://www-135888.com" target="_blank">þþƷƷ޾Ʒ</a>| <a href="http://0359puju.com" target="_blank">þþþav</a>| <a href="http://zhiwajic.com" target="_blank">avר߹ۿ</a>| <a href="http://qsqse1.com" target="_blank">պޱ̬</a>| <a href="http://hqwgg.com" target="_blank">57paoƵ</a>| <a href="http://3fsf.com" target="_blank">ƷƬ߻</a>| <a href="http://gdbobo.com" target="_blank">޾ƷҾþþþþ</a>| <a href="http://gift1town.com" target="_blank">պѸƵ</a>| <a href="http://qqc46.com" target="_blank">պ߹ۿƵ</a>| <a href="http://flowsns.com" target="_blank">ŷ߹ۿ</a>| <a href="http://69xjk.com" target="_blank">Ƭ߹ۿ</a>| <a href="http://555yyyy.com" target="_blank">պ伤Ƶ߲</a>| <a href="http://hkschooltv.com" target="_blank">þ޾ƷƷ</a>| <a href="http://ygpx6.com" target="_blank">Իavҹҹˬ</a>| <a href="http://shrongshan.com" target="_blank">avƬ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>