服务命令调用模式 

Jdon Framework 1.4新功能介绍

  Jdon Framework(以下简称JF)1.4版本在简化和优化两个方向有进一步提高,其中最主要的功能是提供了一种 服务命令调用模式的实现,也就是说,可以象在C/S结构下, 一个菜单按钮功能直接激活其功能方法一样。

多层结构优缺点

  多层结构的好处是带来了良好的可维护性,可拓展性,但是也带来开发的复杂性,有时我们为实现一个小功能,需要做如下步骤:

  1. 创建Domain Model;
  2. 创建界面模型,如struts的ActionForm;
  3. 创建Struts的Action,作为界面控制器;
  4. 配置界面流程struts-config.xml
  5. 创建Domain Model的Service接口
  6. 创建Domain Model的持久化DAO

  对于复杂功能,上述过程是必须的,这样可以达到很好的分层解耦作用。但是,有时一个小功能,或者是Domain Model的特殊功能,只是在Service增加了一个小方法,是否还要整个流程都走一遍呢?

  使用JF就不必了,JF提供基于URL调用参数的服务命令调用模式,就象当初我们在C/S结构中,一个菜单按钮功能直接激活其功能方法一样。

服务命令调用模式

  JF提供的服务命令调用模式有几种实现方式,可根据功能复杂程度灵活选择,并且提供最简单直接的缺省实现。

  我们先看看JF提供的服务命令调用模式是什么样?如下图:

  当浏览器客户端调用某个Struts的Action,如serviceAction.do时,跟随的参数action或method值如果为xxxxx,那么通过JF,就可以直接调用对应Service接口的方法名为xxxxx的方法,如果xxxxx是abcde;那么就调用service的abcde方法。

  这种直接将客户端命令和后台业务层服务直接对应的关系可以大大简化我们很多小功能开发,从而达到类似Ruby on Rails那样的快速开发。

  更大的好处是:我们几乎可以象Ruby on Rails(ROR)那样实现快速开发,而不必陷入另外一个语言陷阱。

域驱动开发框架

  • 核心思想:
    面向域模型Domain Model编程,尽可能减少层次之间混乱调用,化多层编码为多层配置,提供多层编码中各层的缺省实现
  • 前提:
    不能丧失多层结构,否则返回Delphi/VB时代;保证多层之间的松耦合。

  Java发展十年依赖,开始有人抱怨使用Java开发Web网站系统,类似大炮轰蚊子。“Ruby on Rails 是Web系统主打选择”对Java世界提出冲击和挑战。但是使用另外一种语言有其他陷阱。

  对Java世界提出:吸取DDD框架(ROR)优点,真正简化Java企业系统开发,不能打着简化反简化,不能因为Ioc/AOP导致复杂化。

  比较一下Jdon框架实现DDD框架的两个目标:

  目标一

  DDD框架目标: 界面(边界)对象=域对象=持久化的实体(bo)。
  Jdon框架:要求Model和Struts的ActionForm一致。

  目标二:

Domain layer就直接面对表现层,Domain layer中的Object成为无遮挡Object,这样目的减少分叉混乱调用,如图:

  图中左边是传统的J2EE系统,表现层和业务层之间混乱调用,造成修改一个Service接口都要小心翼翼,生怕有别的表现层来调用它,而且很难搞清楚庞大系统是如何调用的,如果采取图中右边方法,去除控制层,如去除Struts的Action,表现层和Domain Model(领域层)业务层可以以Model为线索,实现清晰的前后调用路线,这样系统就易于维护了。

  Jdon框架是通过服务调用命令模式直接去除了Contorller Layer,Domain Model 通过Service直接面对表现层可见第一节的图,只要前台浏览器客户端调用参数写上Service的方法名称,就无需额外编程,直接调用某个服务的对应方法。

  而且,Service和Domain Model通过jdonframework.xml紧密结合:如下配置

<model key="userId" class ="com.jdon.framework.test.model.UserTest">
  <actionForm name="userActionForm"/>
  <handler>
    <service ref="testService">
      <getMethod name="getUser" />
      <createMethod name="createUser" />
      <updateMethod name="updateUser" />
      <deleteMethod name="deleteUser" />
    </service>
  </handler>
</model>

 

配置缺省实现

  下面我们提供三种不同的实现方式,根据功能复杂程度进行选用,注本章节功能在JF1.4版本后可使用:

  实现服务调用命令模式的效果,可以通过简单的配置就可以达到,主要分下面几个步骤:

  假设调用url形式如:/aaa.do?method=xxxxx 或者 /aaa.do?action=xxxxx

  第一步:配置struts-config.xml如下:

<action path="/aaa" type="com.jdon.strutsutil.com.jdon.strutsutil.ServiceMethodAction" name="aForm" scope="request"validate="false">

<forward name="xxxxx" path="/xxx.jsp"/>

</action>

  这个配置主要使用JF的一个现成Action子类:com.jdon.strutsutil.ServiceMethodAction,其中forward配置中的name值必须是调用参数的值xxxxx,这样,调用Service处理后,可返回对应的Jsp页面。

  第二步:配置JF的配置文件jdonframework.xml,告诉系统,你所要调用的Service接口是哪个类。如下:

  

<model key="primary key of your model" class ="your model class">
   <actionForm name="aForm"/>
     <handler>
       <service ref="testService" /> <!--指定对应的接口Service名称-->
     </handler>
</model>

<pojoService name="testService"     
         class="com.jdon.framework.test.service.TestServicePOJOImp"/>

 

  第三步,最后就是你自己要编码实现Service接口和子类,接口中必须有和调用参数值xxxxx相同的方法名,方法参数是com.jdon.controller.events.EventModel;在EventModel中可封装你的传输参数,方法返回类型可返回值,缺省是空,如下:

 

public interface TestService{
   ……
   void xxxxx(EventModel em);
   ……
}


  至此全部完成,这样,你的Service接口方法,可以直接在URL参数中直接调用,方便快捷。无需再编写控制层任何Action,把精力放在业务Service层,也不再为是在控制层实现还是业务层实现进行烦恼的选择,将控制层压缩只留一个配置文件在那里。

 

JF的CRUD流程

  JF的CRUD(新增修改删除和查询)是在服务命令调用模式基础上对CRUD的简化和模板化,从而使得程序员可以在极短时间内开发出一个原型系统。

  我们已经看到,在CRUD流程中,最后需要保存新增或修改结果时,提交给ModelSaveAction的参数action值非常重要, action参数来决定整个流程是新增保存还是修改保存或者是删除,action的参数值是固定的,有三个create、edit或delete,这是JF固定的,必须是这三个字符中一个。那么,参数除了这三个以外,是否可以是其他值呢?

  有时,我们向后台提交保存结果可能不是新增、编辑或删除这么简单,可能是两者性质的删除,在我们的Service中有两个delete方法,那么如何使得前台提交到这两个delete方法呢?一个使用JF的CRUD方式,另外一个或更多的方式如何?

  很简单,直接使用服务命令调用模式即可,例如向ModelSaveAction提交时,action值为deleteAll;那么只要你的Service接口中deleteAll方法即可;

测试

  从网址:/jdonframework/app.htm#simple下载struts+jdon+jdbc案例,在浏览器URL键入: http://localhost:8080/testWeb/serviceAction.do?method=xxxxx,然后观察控制输出!!!!!!! hello, this is not error, you are calling the service with parameter xxxxx !!!!!!!

  运行过程: testWeb/serviceAction.do?method=xxxxx 激活struts-config.xml中如下配置:

<action path="/serviceAction" type="com.jdon.strutsutil.ServiceMethodAction"
name="userActionForm" scope="request" validate="false">
    <forward name="xxxxx" path="/result.jsp"/>
</action>

然后激活业务层com.jdon.framework.test.service.TestServicePOJOImp的xxxxx方法

public void xxxxx(EventModel em){
    logger.error("!!!!!!! hello, this is not error, you are calling the service with parameter
             xxxxx !!!!!!!");
}


更多资料:

一个关于命令模式的问题

J2EE中几种业务代理模式的实现和比较

设计模式之Command

Ruby on Rails/Naked Objects指引下的域驱动开发

发布讨论