??xml version="1.0" encoding="utf-8" standalone="yes"?>中文字幕亚洲不卡在线亚瑟,亚洲风情亚Aⅴ在线发布,亚洲AV无码专区在线播放中文 http://www.tkk7.com/cgogg/category/23084.htmlTake Easyzh-cnWed, 20 Jun 2007 14:52:44 GMTWed, 20 Jun 2007 14:52:44 GMT60AppFuse学习W记-视图?/title><link>http://www.tkk7.com/cgogg/articles/124989.html</link><dc:creator>chenguo</dc:creator><author>chenguo</author><pubDate>Mon, 18 Jun 2007 10:11:00 GMT</pubDate><guid>http://www.tkk7.com/cgogg/articles/124989.html</guid><wfw:comment>http://www.tkk7.com/cgogg/comments/124989.html</wfw:comment><comments>http://www.tkk7.com/cgogg/articles/124989.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/cgogg/comments/commentRss/124989.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/cgogg/services/trackbacks/124989.html</trackback:ping><description><![CDATA[<p>1. E序描述<br>    视图层主要由JSP|页构成Q此外还包括Resource Bundle资源文g及ActionForm Bean、Validation{,q些lg提供对国际化、接收用戯入的表单数据、表单验证和错误处理{的支持?br>    与User的视囑ֱ有关的文件有Q?br>    userList.jspQ用户列表页面,用于h理权限的用户对其他用户的管理?br>    userForm.jspQ用户信息页面,用于对用户信息的增、删、改<br>    UserForm.javaQ与用户信息表单对应的ActionForm Bean<br>    validation.xmlQ对用户信息表单q行验证的配|文?br>    Resource Bundle资源文gQ中文的是ApplicationResource_Zh_cn.properties<br>    default.jspQ用于复合网늚sitemesh文g<br>    JavaScript、CSS文g</p> <p>2. JSP面<br>    与用L关的JSP面包括用户列表和用户信息。head及foot{通用信息攄在head.jsp、foot.jsp中,因此userList.jsp及userForm.jsp只包含与业务相关的标{。下面介l主要的标签功能Q?br>    <logic:messagesPresent>Q判断指定的消息是否存在。若指定message属性ؓtrueQ则从request范围? 索属性key为Globals.MESSAGE_KEY的ActionMessages对象。若不指定属性,则默认检索属性key? Globals.ERROR_KEY的ActionMessages对象。在本系l中一个检索Success消息Q一个检索Error消息?br>    <fmt:message>QJSTL标签。用于输出Resource Bundle中的一条消息?br>    <bean:struts>Q用于检索Struts框架内在的对象,如ActionFormBean、ActionForward? ActionMapping。在q里用于在JSP面上定义一个ActionForward 变量以方便其它地方的引用。forward为struts-config.xml中定义的global-forward?br>    <c:set>QJSTL标签。用于定义一个变量,以方便其它地方的引用?br>    <c:out>QJSTL标签。用于在面上显CZ个EL表达式的|如显C?lt;c:set>定义的变量。EL是JSTL采用的简单的表达式语aQ该语言提供一个访问和操作应用E序数据的简单方式?br>    <c:if><c:when><c:forEach><c:choose>QJSTL标签。用于处理条件的标记Q根据特定的逻辑条g来控制输出网内容,或者@环遍历集合中的所有元素?br>    <display>QDisplay Tag的标{,用于昄控制层返回的List。可以方便的定制表格是否分页、对列排序、导出数据等?br>    <html:form>Q用来定义HTML表单。Struts的HTML标签可以和标准的HTML元素完成相同的功能,Struts框架能够把表单中的数据自动映到相应的ActionForm Bean中?br>    <html:text><html:password><html:hidden>Q在表单上生成相应的HTML元素?br>    <html:submit><html:cancel>Q在表单上生成提交按钮和取消按钮。当用户按下按钮Ӟ生一个提交事 件或取消事gQ由ActioncL莗本pȝ?lt;html:submit><html:cancel>的属性相同(均ؓ methodQ,用户按下提交按钮或取消按钮后执行哪个Ҏ由lookupMethods.properties军_?br>    <html-el:multibox>Q在表单上生成HTML的CheckBox标签。html-el使用了JSTL扩展Q可以用EL表达式?br>    <html:messages><html:errors>Q用于在|页中输出消息?lt;html:errors>? 于输出错误消息,本系l中用于昄表单中字D的错误信息,<html:messages>昄全局的消息?br>    自定义标{:<br>    在你最初运行ant newӞAppFuse׃Ҏ你键入的目名自动生成一个标{文Ӟ在userForm.jsp中你会看到这个标{?br>    <YOURAPPNAME:label>Q它用于昄表单输入域前的提C文本,Ҏ本添加了一些特别的样式Q如在必填项前自动加"*"L?br>    <YOURAPPNAME:country>QuserForm中有讄国家一,该标{于显C国家的下拉列表?br>    <YOURAPPNAME:constants>Q用于在面上显C常量类org.appfuse.Constants中的帔R的倹{?/p> <p>3. ActionForm Bean<br>    ActionForm Bean是Struts提供的表单数据传输对象,用于在视囑ֱ和控制层之间传递HTML表单数据。控制层可以从ActionForm Bean中读取用戯入的表单数据Q也可以把来自模型层的数据存攑ֈActionForm Bean中,然后把它q回l视图?br>    User表单的ActionForm Bean为UserForm。UserForml承BaseForm。BaseForm是ActionForm的子cd象,扩展了三个通用ҎQ? toString()、equals(Object o) 和hashCode()。ƈ定义了一个验证,用于允许用户在点?删除"?取消"按钮时表单无验证?br>    UserForm中定义了与用户信息表单中的字D对应的属性?/p> <p>4. Validator验证框架<br>    Validator验证框架负责数据验证Q采用基于XML的配|文件来配置验证规则。其相关的文件有Q?br>    validation.xmlQ针对具体的Struts表单QؓActionForm配置所需的验证规则?br>    validator-rules.xmlQ框架自带文Ӟ包含了一l通用的验证规则?br>    validator-rules-custom.xmlQ自定义验证规则。本pȝ中定义了验证两个指定的输入域值是否相{的规则。用于验证密码和认密码 是否相等。其实将q个ҎE微修改一下,?#8220;=”变ؓ“<?gt;”可以验证一个域不能大于/于另外一个域Q非常的实用?br>    Resource BundleQ定义验证失败时昄的提C文本。Resource Bundle 中以errors为前~的Keyl大部分用于Validator的错误提C?br>    下面是在validation.xml 中配|的userForm验证规则<br>      <form name="userForm"><br>              <field property="username"<br>                     depends="required"></p> <p>                  <arg0 key="userForm.username"/><br>              </field><br>    ……………………………<br>    </form><br>    该配|通过depends="required"定义了userForm的username字段即用户名是必填项?br>    <arg0 key="userForm.username"/>声明了该字段所对应的文本在Resource Bundle中的Key。Validator会在Resource Bundle中寻找errors.required对应的文本:'{0}' 为必填项Q将userForm.username对应的文本带入{0}。如用户没有填写该项QValidator会提C?#8220;'用户? 为必填项”的消息?br>    validation.xml中用正则表辑ּ定义了一些简单的全局的规则,如电话号码的格式{?br>    默认情况下,Validator框架在Web服务器端执行表单验证。validator-rules.xml里已l定义了客户端JavaScript的生成规则,可以在JSP|页中生成JavaScript脚本。需要进行客L验证Ӟ在JSP中包含:<br>    <html:javascript formName="userForm" cdata="false"<br>      dynamicJavascript="true" staticJavascript="false"/><br>    <script type="text/javascript"<br>      src="<c:url value="/scripts/validator.jsp"/>"></script><br>    q在<html:form>中定义onsubmit事gQ?br>    onsubmit="return validateUserForm(this)"<br>    在userForm表单的提交和取消按钮中包含了onclick="bCancel=false"事g。bCancel是Validator定义的是否进行验证的变量。当用户点击删除或取消按钮时Q表单无验证,此时bCancel= true?/p><img src ="http://www.tkk7.com/cgogg/aggbug/124989.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/cgogg/" target="_blank">chenguo</a> 2007-06-18 18:11 <a href="http://www.tkk7.com/cgogg/articles/124989.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse学习W记-控制?/title><link>http://www.tkk7.com/cgogg/articles/124990.html</link><dc:creator>chenguo</dc:creator><author>chenguo</author><pubDate>Mon, 18 Jun 2007 10:11:00 GMT</pubDate><guid>http://www.tkk7.com/cgogg/articles/124990.html</guid><wfw:comment>http://www.tkk7.com/cgogg/comments/124990.html</wfw:comment><comments>http://www.tkk7.com/cgogg/articles/124990.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/cgogg/comments/commentRss/124990.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/cgogg/services/trackbacks/124990.html</trackback:ping><description><![CDATA[<p>1. 我们先详l介l一?strong>Struts的控制器</strong>的工作流E?br>    首先Q控制器QActionServletQ进行初始化工作Q读取配|文件struts-config.xmlQؓ不同的Struts模块初始化相应的 ModuleConfig对象。相应地有ControlConfig集合、FormBeanConfig集合、ForwardConfig集合? MessageResourcesConfig集合{?br>    AppFuse中设计了一个承ActionServlet 的子c:LoginServlet做ؓ控制器,对ActionServlet的功能进行了扩展。主要的功能是对本系l用到的一些组件进行初始化工作Q如用户w䆾的安全校验url、密码加密规则等?br>    控制器接收到HTTPhQƈ从ActionConfig中找出对应于该请求的Action子类Q如果没有对应的ActionQ控制器直接请求{发给JSP或者静态页面。否则控制器请求分发至具体Actionc进行处理?br>    在控制器调用具体Action的方法之前,相应的ActionForm对象利用HTTPh中的参数来填充自己。此外,若所操作的ActionForm c配|了validateQ系l会调用validatelg来检查请求参数的合法性,q且q回一个包含所有错误信息的ActionErrors对象。如? 执行成功QActionForm自动这些参C息以FormBean的方式保存在Servlet Context中,q样它们可以被其它Action对象或者JSP调用?br>    执行完成Action中的Ҏ之后Q返回一个ActionForward对象Q控制器通过该ActionForward对象来进行{发工作?/p> <p>    AppFuse实现的最主要的功能是对用L理。下面就以对用户的管理来说明一下AppFuse控制器的实现?/p> <p>    与用户信息表单数据相关的FormBean是UserForm。UserForm用来存放用户的基本信息?br>    UserForm的控制器是org.appfuse.webapp.action.UserAction。UserActionl承? BaseAction。BaseAction也是pȝ中几乎所有Actioncȝ父类Q它l承自Struts提供的DispatchActionQƈ提供 了控制层通用的方法?/p> <p>2. <strong>Action</strong><br>Action是用戯求和业务逻辑之间的桥梁,每个Action充当客户的一业务代理。主要完成以下Q务:<br>    1. 接收用户h?br>    2. Ҏ用户hQ调用合适的模型lg来执行相应的业务逻辑?br>    3. 获取业务逻辑执行l果<br>    4. Ҏ当前状态以及业务逻辑执行l果Q选择合适的视图lgq回l用戗?/p> <p>3. <strong>DispatchAction</strong><br>    org.apache.struts.actions.DispatchAction是org.apache.struts.action.Action的子cR?br>    Action的execute()Ҏ是调用模型的业务ҎQ完成用戯求的业务逻辑Q然后根据执行结果把h转发l其它合适的Weblg。通常Q在一个ActioncM只能完成一U业务操作(通过execute()ҎQ?br>    DispatchAction允许用户完成一个业务逻辑所需要的q箋动作和相兛_作集中于一个ActioncM。无覆盖execute()ҎQ而是可以创徏一些实现实际业务操作的ҎQ用户通过methodh参数指定所需要用的Ҏ?/p> <p>4. <strong>BaseAction</strong><br>    BaseAction中实Cpȝ中Action子类需要用到的通用ҎQ主要有Q?br>    1. public Object getBean(String name):通过dSpring的applicationContext-service.xml配置文g来创建实例从而实?#8220;依赖注入”的方法?br>    2. public ActionMessages getMessages(HttpServletRequest request)Q初始化Struts的ActionMessagesQƈq回?br>    3. protected Object convert(Object o) QPOJO与FormBean之间的{换方法?br>    4. execute()Q置换了原始的execute()Ҏ。作用是Ҏh的urlL相关的业务方法(没有methodh参数Ӟ。例如请求的面是editUser.html,则执行edit()Ҏ?br>    5. protected ActionForm getActionForm(ActionMapping mapping, HttpServletRequest request)Q在mapping范围内得C个Action FormBean?br>    6. protected User getUser(HttpSession session) Q从Session中拿到当前登录用户信息?br>    7. protected void updateFormBean(ActionMapping mapping, HttpServletRequest request, ActionForm form)Q在指定的范围内更新当前Action 所对应的Form Bean对象?br>    8. protected void removeFormBean(ActionMapping mapping, HttpServletRequest request)Q去除无用的Form Bean?nbsp;</p> <p>5. <strong>UserAction</strong><br>    UserAction是用h据管理的控制器,提供了对用户数据的添加、修攏V删除、查询等操作的控Ӟ其包含的业务Ҏ有:<br>    1. add()Q进入添加用户页面?br>    2. cancel()Q当用户在表单中点击“取消”按钮Ӟ执行该方法。如果用h通过用户列表q入该表单,卛_前用于拥有管理其它用L权限Q返回到用户列表Q否则返回到主页面?br>    3. delete()Q根据请求的用户ID调用业务层的removeUser ()Ҏ删除相应的记录,q回到用户列表?br>    4. edit()Q首先校验用戯求的URL是否为editProfile.htmlQ若是,表示当前d用户要查看自q信息Q此时请求\径中不应? 含有用户IDQ用户ID从Session中取得)或用于标识请求是通过用户列表的from参数Q如果含有这两个参数Q发?#8220;无权?#8221;的错误信息。若不是Q? 表示当前用户是通过用户列表q行h。根据请求的用户ID调用业务层的getUser ()Ҏ取得相应的记录。更新相应的FormBean?br>    5. save()Q当需要要d或修改用户信息时Q执行该Ҏ。首先校验请求参C是否?#8220;encryptPass”qgؓ“true”Q若是,表示? 码需要加密,随即密码加密。然后调用业务层的getRole ()Ҏ提交的用户权限持久化。调用业务层的saveUser ()ҎQ保存用户信息。如果用L辑的是自q信息Q更新Session中的当前d用户信息。如果用户在d旉择?#8220;C?#8221;Q更C存的 Cookie。如果用L辑的是其它用L信息Q根据version判断是新L据还是修Ҏ据,在ActionMessages中存储不同的消息Q返? 到添?修改用户信息面。若是新L据,调用sendNewUserEmail()l新用户发送一Email?br>    6. search()Q具有管理权限的用户q入用户列表时执行该Ҏ。调用业务层的getUsers ()ҎQ取得包含所有用户信息的List。返回到用户列表面?br>    7. unspecified()Q如果请求的url没有包含method参数Q通过BaseAction的execute()Ҏ也找不到指定的方法时Q执行该Ҏ。在该方法中转到search()Ҏ?br>    以上是很多Action需要用到的基本的方法?br>    8. sendNewUserEmail()Q根据FormBean中的内容l用户发送一Email?br>    9. checkForCookieLogin()Q如果用h通过CookiedQ用户在d旉择?#8220;C?#8221;Q,发出一个消息警告用户不能修改密码?br></p><img src ="http://www.tkk7.com/cgogg/aggbug/124990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/cgogg/" target="_blank">chenguo</a> 2007-06-18 18:11 <a href="http://www.tkk7.com/cgogg/articles/124990.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AppFuse学习W记-模型?/title><link>http://www.tkk7.com/cgogg/articles/124988.html</link><dc:creator>chenguo</dc:creator><author>chenguo</author><pubDate>Mon, 18 Jun 2007 10:09:00 GMT</pubDate><guid>http://www.tkk7.com/cgogg/articles/124988.html</guid><wfw:comment>http://www.tkk7.com/cgogg/comments/124988.html</wfw:comment><comments>http://www.tkk7.com/cgogg/articles/124988.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/cgogg/comments/commentRss/124988.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/cgogg/services/trackbacks/124988.html</trackback:ping><description><![CDATA[<p>3.3 模型层结?br>    Model层ؓ整个pȝ的核心部分,完成应用的业务逻辑及与数据库的通信。AppFuse中将Model分ؓ两层Q持久层和业务层。采用SpringQHibernate框架实现Q这里以对用户User数据的操作ؓ例详l阐q其实现方式?/p> <p>    Ҏ久化数据的访问基于DAOQData Access ObjectQ模式实现。DAO模式提供了访问关pd数据库系l所需的所有接口操作的接口。DAO模式底层数据访问操作与高层业务逻辑分离开Q对上层提供面向对象的数据访问接口?/p> <p>    Model层与User相关的类有:<br>    POJOQ?br>    UserQ管理员表的业务对象?br>    业务层:<br>    UserManagerQ业务层接口Qؓ控制层所调用?br>    UserManagerImplQ业务层接口的实玎ͼ调用持久层接口?br>    持久层:<br>    UserDAOQ持久层接口Qؓ业务层实现所调用?br>    UserDAOHibernateQ持久层接口的实现?br>    XML配置文gQ?br>    applicationContext-service.xmlQ业务层接口的配|文件?br>    applicationContext-hibernate.xmlQ持久层接口的配|文件?/p> <p>3.3.2 Spring的IoC<br>    IocQInversion of ControlQ即反{控制。Ioc模式即Dependency Injection模式是依赖注的意思,也就是将依赖先剥,然后在适当时候再注射q入?br>    Spring的轻量的bean容器Z务对象(business objectsQ、DAO对象和资源(如:JDBC数据源或者Hibernate SessionFactorie{)对象提供了IoCcd的装配能力。Spring使用一个xml格式的应用配|文件ؓ开发者提供了一U通过解析定制的属 性文件来手动理单实例对象或者工厂对象的选择性。由于Spring非入R性做Z个重要的目标Q因此可以由Spring配置理的bean对象均不需 要依赖Spring自有的接口和cd可以通过它们的bean属性完成配|?br>    实C来讲Spring采取了配|文件的形式来实C赖的注射Qƈ且支持Type2 IOCQSetter InjectionQ以及Type3 IOCQConstructor InjectionQ?<br>    在Model层,使用Spring提供的Setter Injection(type2)注入方式。以UserZQ下面是其用法?br>    在applicationContext- hibernate.xml中定?br>    <bean id="userDAO" class="org.appfuse.dao.hibernate.UserDAOHibernate"><br>        <property name="sessionFactory"><ref local="sessionFactory"/></property><br>    </bean><br>    在UserManagercM有一句: <br>    public void setUserDAO(UserDAO dao);<br>    q就是一个DAO Object讄ҎQ注器Q。UserDAO被调用Q和持久层通信。以q种方式创徏UserDAO的实例,同样辑ֈ了由UserManager创徏UserDao的目的。避免了直接实例化UserDAO的实现而业务层和持久层紧密耦合?br> </p> <p>    在控制层调用业务层方法时Q用服务定位器q回lSpring contextQSpring的BeanFactory提供了getBeanҎ。BeanFactory是一个通用的FactoryQ它使对象能够按名称获取Qƈ且能理对象之间的关pR?br>    在applicationContext-service.xml中配|?br>    <bean id="userManager" parent="txProxyTemplate"><br>        <property name="target"><br>            <bean class="org.appfuse.service.impl.UserManagerImpl"><br>                <property name="userDAO"><ref bean="userDAO"/></property><br>            </bean><br>        </property><br>    </bean><br>    在控制层BaseAction定义通用ҎQ?<br>    private static ApplicationContext ctx = null;<br>    public Object getBean(String name) {<br>        if (ctx == null) {<br>            ctx = WebApplicationContextUtils<br>                    .getRequiredWebApplicationContext(servlet.getServletContext());<br>        }<br>        return ctx.getBean(name);<br>    }<br>    在UserAction中创建UserManager的实例:<br>        UserManager mgr = (UserManager) getBean("userManager");<br>    q样Q通过BeanFactory的getBeanҎQ以及xml配置文gQ避免了在UserActioncM直接实例化UserManagerQ消除了控制层与业务层及业务层与持久层之间的耦合Q实C依赖的注?br>    ApplicationContext 是BeanFactory的子接口Qؓ下列东西提供支持Q?<br>        信息查找Q支持着国际?<br>        事g机制Q允许发布应用对象以及可选的注册以接收到事g <br>        可移植的文g和资源访?</p> <p>3.3.3 Spring的事务管?br>    在数据持久层的杰A献,可能是Spring最为闪亮的优点?br>    Spring提供了通过容器的集U式参数化事务机Ӟ实现事务的外部管理。容器管理的参数化事务ؓE序开发提供了相当的灵zL,同时因ؓ事务委托给容器 q行理Q应用逻辑中无需再编写事务代码,大大节省了代码量Q特别是针对需要同时操作多个事务资源的应用Q,从而提高了生率?br>    AppFuse在applicationContext-service.xml文g中进行了对事务的配置<br>    <bean id="txProxyTemplate" abstract="true"<br>        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><br>        <property name="transactionManager"><ref bean="transactionManager"/></property><br>        <property name="transactionAttributes"><br>            <props><br>                <prop key="save*">PROPAGATION_REQUIRED</prop><br>                <prop key="remove*">PROPAGATION_REQUIRED</prop><br>                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop><br>            </props><br>        </property><br>    </bean><br>    q里定义了一个名为txProxyTemplate的TransactionProxyFactoryBean服务。它对包含实际数据逻辑的持久层对象q? 行了事务的封装。在q里Q通过transactionAttributes属性,我们指定了事务的理{略Q即所有的名称以save和remove开? 的方法纳入事务管理范围。如果此Ҏ中抛出异常,则Spring当前事务回滚,如果Ҏ正常l束Q则提交事务?br>    而对所有其它方法则以只ȝ事务处理机制q行处理。设为只d事务Q可以持久层尝试对数据操作q行优化Q如对于只读事务Hibernate不执行flush操作Q而某些数据库q接池和JDBC 驱动也对只读型操作进行了特别优化?br>    如果有其他的Ҏ需要进行写数据库操作,可以在相应的Manager配置中声明。如在UserManager中,添加了属?br>        <property name="transactionAttributes"><br>            <props><br>                <prop key="save*">PROPAGATION_REQUIRED</prop><br>                <prop key="remove*">PROPAGATION_REQUIRED</prop><br>                <prop key="*LoginCookie">PROPAGATION_REQUIRED</prop><br>                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop><br>            </props><br>        </property><br>    q样Q以LoginCookiel尾的方法也可以写数据库了?br>    Spring可以Q意Java Class U_事务理Q而无需对其q行M修改Q因此我们的cd能完全不知道它正在被q行事务理?/p> <p><br>3.3.3 SpringQHibernate操作持久?br>    Spring对Hibernate有很好的支持?br>    Hibernate中通过SessionFactory创徏和维护Session。Spring对SessionFactory的配|进行了整合Q无需? 通过Hibernate.cfg.xml对SessionFactoryq行讑֮。SessionFactory节点的mappingResources 属性包含了映射文g的\径,list节点下可配置多个映射文g。hibernateProperties节点则容U了所有的属性配|。可以对应传l的 Hibernate.cfg.xml文gl构对这里的SessionFactory配置q行解读?br>    下面是HibernateSessionFactory ?HibernateTransactionManager的配|:<br>    在applicationContext-hibernate.xml中:<br>    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"><br>        <property name="dataSource"><ref bean="dataSource"/></property><br>        <property name="mappingResources"><br>            <list><br>                <value>com/mycompany/model/User.hbm.xml</value><br>                ……………………………<br>            </list><br>        </property></p> <p>        <property name="hibernateProperties"><br>        <props><br>            <prop key="hibernate.dialect">@HIBERNATE-DIALECT@</prop><br>            <!--prop key="hibernate.show_sql">true</prop--><br>            <!--prop key="hibernate.hbm2ddl.auto">update</prop--><br>        </props><br>        </property><br>    </bean></p> <p>    Spring 提供了一? HibernateTransactionManagerQ采用面向Hibernate的TransactionManager实现Q? org.springframework.orm.hibernate.HibernateTransactionManager。他用线E捆l了一? Hibernate SessionQ用它来支持transactions?br>    <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"><br>        <property name="sessionFactory"><ref local="sessionFactory"/></property><br>    </bean></p> <p>    sessionFactory Bean引用了HibernateSessionFactoryQ而transactionManager Bean引用了HibernateTransactionManage?transactionManager Bean中有个sessionFactory属性?HibernateTransactionManager有个sessionFactory setter ?getterҎQ用来在Spring启动的时候实?#8220;依赖注入” Qdependency injectionQ的? 在sessionFactory 属性里引用sessionFactory Bean。这两个对象在Spring容器初始化后pl装了v来了?br>  <br>    User使用一个TransactionProxyFactoryBeanQ它定义了一个setTransactionManager()。能很方便的? 理申明的事物q有Service Object。TransactionProxyFactoryBean q有个setter. q会被Business service objectQUserManagerQ引用, UserManager定义了业务层Qƈ且它q有个属性,由setUserDAO()引用?/p> <p>    pȝ持久层中所有的c都l承自Spring提供的HibernateDaoSupportc,HibernateSupport实现? HibernateTemplate和SessionFactory实例的关联。HibernateTemplate对Hibernate Session操作q行了封装,提供了一个简单的方式实现了Hibernate-based DAO对象。借助HibernateTemplate我们可以q每次数据操作必须首先获得Session实例、启动事务、提?回滚事务以及烦杂? try/catch/finally的繁琐操作。一个简单的Hibernate讉KҎ完全解决了些麻? 无论是在多个DAO接口q是在多方事务的情况下,Spring使得多种DAO对象无缝地协同工作?br>    对于单的单步的动作,象find, load, saveOrUpdate或者delete的调用,HibernateTemplate提供更ؓ便利的选择以代替象一行的回调的执行。此? HibernateDaoSupportcL供了setSessionFactoryҎ来接受一个SessionFactoryQ同时提供了 getSessionFactory和getHibernateTemplateҎ供其l承cM用。将q些l合hQ允许对于典型的需求给Z非常? 的DAO实现Q如获得所有用LҎQ?br>    public List getUsers(User user) {<br>        return getHibernateTemplate().find("from User u order by upper(u.username)");<br>    }<br></p> <br><img src ="http://www.tkk7.com/cgogg/aggbug/124988.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/cgogg/" target="_blank">chenguo</a> 2007-06-18 18:09 <a href="http://www.tkk7.com/cgogg/articles/124988.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>领域服务与业务服务职责的讨论http://www.tkk7.com/cgogg/articles/123850.htmlchenguochenguoWed, 13 Jun 2007 05:28:00 GMThttp://www.tkk7.com/cgogg/articles/123850.htmlhttp://www.tkk7.com/cgogg/comments/123850.htmlhttp://www.tkk7.com/cgogg/articles/123850.html#Feedback0http://www.tkk7.com/cgogg/comments/commentRss/123850.htmlhttp://www.tkk7.com/cgogg/services/trackbacks/123850.html
? 我们来回忆一下,通常我们针对读写xml、资金{账等代码攑֜service中,可以看出Q该层包括了两种含义Q一U是与业务无关的Q一U是与业务紧? 兌的。领域驱动设计将q两层含义进一步划分,《Domain-Driven Design》中的例子那P如果银行应用可以我们的交易转化q输出电子表格文Ӟ那么q种输出应该是应用服务。而负责处理资金{帐的借贷关系Q应? 属于领域层,它包括了基本的业务逻辑Q而技术层上的服务则根本没有Q何业务含义。由此得知,传l设计中的Servicel箋划分Q得到应用服务与领域? 务。领域层和应用层的服务是怺合作Q由应用Service指挥领域对象来解决问题?br>
如此划分Q可以各层的结构和职责更加清晰Q技术与业务q一步分R?br>
以上是我个h的理解,有不对之处还h正?br>
另仔l阅?a >实战DDD(Domain-Driven Design领域驱动设计)Q? 在该文中说到Q?#8220;在JiveJdon3中,com.jdon.jivejdon.service.ForumService和Forum实体模型及其值对 象ForumState共同完成领域模型Q其中ForumService属于应用服务层;而后两者属于领域层Q其他服? ForumMessageService、AccountService和UploadService{都是此cL质?#8221;在JiveJdon3中ƈ没有? 领域与应用Serviceq行明确的划分,而是由ForumService来完成。JJ3的代码我没有看过Q只是从q段文字q这样判断的Q有不对之处q请 包含。请问,JJ3中是否对Serviceq行了划分?如果没有那么您是怎样考虑的呢Q?

bangqQ? 非常有道理,Evans DDD中的Service和我们传l的Service实不一P它主要划分ؓ应用层服务和领域层服务以及基l构层服务?br>
在我的JJ3案例中,我没有进行这U严格的分层分类Q是以Web服务中的Service和操作Operations概念来区分的Q?br>
需要对外开攄、供客户端调用的我命名ؓ服务Q当然这个服务里也可能会区分为应用服务和领域服务Q不对外开放,供业务层内部使用的普通operations׃为普通组件来看待?br>
个h目前感觉Q应用服务和领域服务区分需要非常敏感,而且目前没有看到大大的好处?br>
有时Q快速?方便性确实必L意,当然q个度是根据当事h的水q定的?br>
无论如何Q我们更应该来关注领域对象:也就是实体和值对象,当然Q领域对象ƈ不是无行为的对象Q可以封装一些业务规则,不是单的setter或getter行ؓ?br>
不知你是如何惻I

版主Q? 应用服务与领域服务的区分实非常敏感且难以撑控,在较为复杂的应用中,应用服务与领域服务ƈ不一定能够完全实现分R这需要不断地重构来完善,但ƈ不一定能够完?个h观点)?br>
我认同领域对象不应只是简单的setter或getterQ可以封装一些业务规则。但前题是这些规则一定是它本w的职责才是Q否则模型就会遭到破?面向对象的精要处)?

版主Q? 引用两段文字来说明问题:
“OO~程的技术是一门代理的艺术。职责划分明,把接口定义好Q把实现交给另外的类来做。首先把变化的部分和不变的部?划分出来。不变的部分Q就成了框架。变化的部分Q就是程序员自己做?”

? 域对象是可以有行力的Q在Rod Johnson的《without EJB》第10章《持久化》中有一D|字:“领域对象包含的逻辑Q这里称之ؓ“domain logic”Q这些domain logic应该最化的依赖于DAOQ而我们讨论的那些需要持久化操作参与的事务性逻辑Q这里称之ؓ“workflow methods”Q这?#8220;workflow methods”应该攑֜“business facade”Q而不应该攑֜domain object里面。可重用度很高的操作可能是domain logicQ应该放在domain object里面Q比较难重用的控刉辑ҎQ特别是可跨多个domain object的操作则攑֜business facade object里面?#8221;

虽然领域对象是可以有行ؓ能力的,但除领域对象之外一定是要业务对象的。业务对象应该操控多个领域对象的协作。ƈ不是所有的逻辑都塞到领域对象中?

bangqQ? >但前题是q些规则一定是它本w的职责才是Q否则模型就会遭到破?面向对象的精要处)?
所以,例如各种条g的查询,q些条g的筛选功能也应该属于规则Q过L们将数据{选留l数据库SQL语句完成Q现在DDD认ؓ{选应该在内存中完成,SQL文本也是一U规则?br>
>除领域对象之外一定是要业务对象的
引用Rod 的话Ҏ引v误解Q前面我们讨Q我们的模型分领域对象和服务Q领域对象又分实体和值对象。那么Rodq个业务对象又是什么呢Q如果是服务Q我们一般不会将服务UCؓ对象Q服务是一U组件模型,要么是服务,要么是操作operations

>Service层和Function层的关系应该是胃和小肠的关系一?br>q是很Ş象比喻,现在实没有q方面框ӞService层和Function层分,从现在来看,好像更多q是分析领域的事情,必须由徏模h员来指定哪些服务是应用还是领域?



chenguo 2007-06-13 13:28 发表评论
]]>
J2EE分层架构解析http://www.tkk7.com/cgogg/articles/123842.htmlchenguochenguoWed, 13 Jun 2007 05:07:00 GMThttp://www.tkk7.com/cgogg/articles/123842.htmlhttp://www.tkk7.com/cgogg/comments/123842.htmlhttp://www.tkk7.com/cgogg/articles/123842.html#Feedback0http://www.tkk7.com/cgogg/comments/commentRss/123842.htmlhttp://www.tkk7.com/cgogg/services/trackbacks/123842.html了,具体分几层,q是一个值得决策的问题。我最熟悉的《责任驱动设计》和《领域驱
动设计》都推荐用四层,而且两者的d度相当高Q我受这两本书的影响也最大,所?br>很自然我的框架也分四层?br>
    哪四层?表现层、应用层、领域层和技术层?br>
    览器、PHP和数据库是比较容易区分出来的物理上的三个层次。然而这只是物理
分层Q跟逻辑分层q是有区别的。目前Ajax非常行Q而且很多应用也确实需要Ajax?br>提供富交互功能,所以支持Ajax是相当自然的一件事。在物理层面上,Ajax属于览?br>层。实际上我对在浏览器端维护一个领域模型ƈ不感兴趣Q原因是难以在两者间保持?br>步,也无谓地增加了复杂性。我完全可以直接在Action里处理,然后直接用PHP内置?br>JSONpd函数直接输出数据供客LJavaScriptq行eval调用。用JavaScript Helper
来生成AjaxQ目前我q没试过Q具体是否支持,q要到时看情况而定。另外在资源定位
斚wQ我觉得REST的思想不错Q不q目前还不是很熟悉RESTQ所以这一块打暂时先?br>一放,到时再重构以适应REST?br>
    回到PHPq一物理层面上来。上面所说的四层架构Q就是在PHPq一物理层次?br>
    先说表现层。PHP对表现层的支持非常灵z非常方便,因ؓPHP最初就是用来做表现
层的。关于页面的l织Q我的方法是把一个HTML面分成两类元素Q一cL布局Q另一
cL模板。跟现有的一些框架不一L是,我的模板没有再细分ؓ其它元素Q如slot?br>cR因为没必要。一个布局对应一个有HTML输出的ActionQ同时一个布局q对应多个模
ѝ注意,布局跟Action是一一对应的,但模板不同,模板是完全灵zȝQ在某个时?br>它可以嵌入某个布局Q在另一个时候可以嵌入另一个布局。这样一来,模板成了完?br>可以复用的单元,而且l过我的处理Q每个模板可以在树结构上从树叶一直往上移到树
根,以在多个Action、多个Module乃至多个App间的布局里共享。如果你熟悉JavaScript
的对象绑定,你就很容易理解一个对象做为另一个对象的某个属性这一q程跟我的模?br>对应布局q一q程非常怼Q都是动态绑定的?br>
    表现层由Action调用Q而Action则处于应用层Q多个Actionl成一个ModuleQ多?br>Modulel成一个ApplicationQ这一点参考自symfonyQ实际上在没有接触过symfony?br>我就惛_q这U组l方式)。这里有一个取舍问题,是是把一个Action当成一个文?br>处理Q还是多个Action集中C个文件来处理。symfonyQZend Framework采取的是一?br>文g多个Action的方式。我之前采用的是一个文件一个Action的方式,后来xq种?br>式有一个缺点:难以在多个Action间共享某些计,如Admin Module下的多个ActionQ?br>它们都需要检查客L是否有有效的会话信息以确保用户已l登录。在一个文件一?br>Action的情况下Q这些重复代码必然会在多个Action间复Ӟ除非你把q部分代码抽?br>出来攑ֈ某个地方Q但问题是应该放在哪个地方?我想不到好的地方Q你不可能把它们
攑ֈ抽象的Action父类Q因些逻辑只是属于某个模块的,不是所有的Action子类?br>有的Q,所以我打算采用一个文件多个Action的方法,q把q些重复代码抽象成一个预
处理Ҏ和后处理ҎQ当调用某个模块的ActionӞ预先执行q些代码。在q些代码
里,自然是校验和计算Q如果通不q,直接lResponse对象发redirect消息Q让客户?br>重定向到某个地方?br>
    除了调用表现层,Actionq有哪些职责Q实际上QAction的职责ƈ不多Q但它仍?br>pȝ的核心所在,因ؓ你的Action必须捕获所有的用例。可能一个用例有多个Action?br>与,也可能一个用例只有一个ActionQ这取决于你的用例分析。这是OOA阶段的Q务,
q里不多Ԍ一个优U的分析h员必能~写高质量的用例Q可以参考W.C的《编写有
效用例》一书)。捕获了用例后,Action有两个Q务:一Q选取某个领域服务Q让?br>领域服务处理某个逻辑事务Q二Q选取某个应用服务Q让该服务完成应用相关的dQ?br>如发送EmailQ把领域对象~存qCache源,把领域对象保存到Session数据源,{等?br>q里的关键,是区分领域服务和应用服务Q否则很隑ց出正的设计。关于服务层Q我
推荐阅读三本书籍Q一是《领域驱动设计》,q本书有一节详细地论qC服务层的?br>计以及领域服务和应用服务的区分;二是《企业应用架构模式》,q本书有两个地方?br>qC服务层,讲得比较l致Q三是《J2EE核心模式》,里头?#8220;业务服务”模式是?br>域服务的_描述Q简z易懂?br>
    应用服务操作技术层对象Q那么领域服务操作什么对象?领域服务操作领域模型?br>关于领域模型Q有非常多的书有详细的讲qͼ前面提到的三本书都有详细的讲qͼ除此
外还有《UML与模式应用》,《UML面向对象建模与设计》等书,都有寚w域模型的l致
讲述。理解领域模型ƈq用领域模型是一U非帔R要的技能,因ؓ只有分析q提炼出?br>适的领域模型Q设计才不会偏离需求。需要注意的是,我个人对领域模型复杂化ƈ没有
好感Q因样一来映到数据源将非常ȝ。我崇尚让领域模型跟数据库的E-R模型
一一对应Q这样一来无论理解还是修改,都非常简单。另外一个可能媄响设计的东西?br>值对象。目前对q些比较l节斚w的东西的处理Q我q暂时没有深入考虑Q等设计到那
时再说?br>
    需要注意的是,领域服务不能剥夺本应属于领域模型的一部分业务逻辑Q否则就?br>淆了领域服务与领域模型的区别。比如一个领域模型:用户Q它有一个规格检查:q龄
是否辑ֈ要求Q这个规格检查就不应该放到领域服务里Q而应该直接加在领域模型上Q?br>q也是非常自然的处理Ҏ。此外,cM查询用户是否存在q样的Q务,应该组l到
一个领域服务里Q由Action调用该服务。领域服务ƈ不知道是谁调用它Q这W合分层?br>基本原则Q即上层对象可以调用它下层的对象Q以及更下层的对象,但下层对象不能调
用上层对象,如果实需要,臛_也要用观察者模式来解开耦合Q以让领域服务能更好
地在多个Action间重用?br>
    领域层是由开发h员组l的Q框架对领域层基本没有做限制Q开发者可以进行Q?br>的发挥,前面我只是提ZU我认ؓ比较合适的l织Ҏ。下一将讲述框架内最重要
的组成部分——技术层Q以及技术层里的重中之重——持久层?


chenguo 2007-06-13 13:07 发表评论
]]>
վ֩ģ壺 ƷƵ׽Ƶ| ݺݺݰƵ| Ůҹ24ʽƵ | AAѹۿ1000Ӱ| Ƶ߹ۿ| 99þ99þѾƷС˵| þþþþþAv| Ƶ㶮| ˳ɼ߲| ëƬѹۿƵ| ޹Ʒ۲ӰԺ| ޳aavҰĦ| Ƶһѹۿ| þ޾Ʒ벥| þþƷѿ| þŮcc98cm| ĻmvֻѸ| avר߹ۿ| ѹŮˬˮƵ| 99ƵƷƵ76| AVר޾Ʒ| Ļ| ޹ŮƷþþ| ޹ƷۺϾþһ| յӰ߲Ѱ| 99Ļ| ŮѹۿƬ| Ʒվ| պƷһAVۿ| avŷǮ| freeƵ| ƵС˵ͼƬ| һ| Ʒ69XXXƵ| Ʒ޳AV߹ۿ| װ׹Ƶ| ۲Ƶwwwѿ| ҹ޾Ʒ| þù˾Ʒ| þþƷëƬѹۿ| ƷרWEB|