webx—CommandDispatcher分发服务



webx—CommandDispatcher分发服务

一、简介

 

Command pattern是一套基于Spring Framework ,以Use Case为中心的框架。它糅合了几种经典的JavaEE设计模式,使应用开发者在实现Use Case时,能够更专注于商业逻辑本身。

 

结构图:

 

 

 

 

 

 

整个业务层都是用Spring框架来配置的。Spring是一种轻量的IoC的框架,使用Spring能够最大程度上保证业务逻辑不被污染

 

表现层调用业务逻辑层的流程图:

 

 

二、具体流程

 

1. 客户端

 

如何调用一个业务逻辑呢?对于业务逻辑的调用者(通常是表现层),完全不用关心这个业务逻辑是如何实现的。对客户端而言,它只能看到command dispatcher,如下图:
对需要调用业务操作的Web层组件,其内聚了一个CommandDispatcher,通过该dispatcher来完成业务的委派,但是这个commandDispatcher就是一个Bean,它存在于Spring容器之中(可以参考web层的模块ioc)。缺点在于web层被command所侵入,并且与业务实现在一定程度上发生了耦合。

 

 

步骤:

 

a)创建一个Command,填上业务逻辑所需要的参数。
b)将Command对象传递给CommandDispatcher,这样就完成了业务逻辑的调用。
c)如果需要,可以取得业务逻辑的返回结果。

 

 

 

  1. // Step 1. 装配一个command,
  2. //         command名称为”userCommand”,”userCommand”中有许多有关user的子命令,
  3. //         而”registerUser”是其中的一个子命令。(子命令参数是可选的)
  4. Command command = new CommandSupport(“userCommand”, ”registerUser”);
  5. commandName.getParameters().put(“name”, ”michael”);
  6. commandName.getParameters().put(“password”, ”helloworld”);
  7. commandName.getParameters().put(“email”, ”michael@hello.world”);
  8. // Step 2. 调用业务逻辑
  9. Result result = getDispatcher().execute(command);
  10. // Step 3. 处理返回结果
  11. if (result.isSuccess()) {
  12.     User user = (User) result.getModels().get(“user”);
  13.     // 通常这类操作会返回数据库所创建的sequence ID。
  14.     int id = user.getId();
  15.     …
  16. } else {
  17.     ResultCode errorCode = result.getResultCode();
  18.     if (errorCode == UserResultCode.USER_ALREADY_EXISTS) {
  19.         …
  20.     }
  21.     …
  22. }

 

// Step 1. 装配一个command,
//         command名称为"userCommand","userCommand"中有许多有关user的子命令,
//         而"registerUser"是其中的一个子命令。(子命令参数是可选的)
Command command = new CommandSupport("userCommand", "registerUser");

commandName.getParameters().put("name", "michael");
commandName.getParameters().put("password", "helloworld");
commandName.getParameters().put("email", "michael@hello.world");

// Step 2. 调用业务逻辑
Result result = getDispatcher().execute(command);

// Step 3. 处理返回结果
if (result.isSuccess()) {
    User user = (User) result.getModels().get("user");

    // 通常这类操作会返回数据库所创建的sequence ID。
    int id = user.getId();

    ...
} else {
    ResultCode errorCode = result.getResultCode();

    if (errorCode == UserResultCode.USER_ALREADY_EXISTS) {
        ...
    }

    ...
}


2. 服务端

 

 

服务端,它也不需要了解客户端的情况。服务端要做的,无非是从系统接收command的请求,然后执行相应的业务逻辑而已。

 

步骤:

 

a)创建ApplicationObject(即AO)。
实现ApplicationObject接口,但建议从ApplicationObjectSupport继承

 

 

 

  1. public class LoginAO extends ApplicationObjectSupport {
  2. }

 


public class LoginAO extends ApplicationObjectSupport {
}

 

 

 

b)执行

 

类似于WebX中的action,AO可以根据command中的event参数来自动调用相应的方法,例如 new CommandSupport(“loginAO”, “login”),那么,只要实现下面的方法即可

 

 

 

  1. public Result doLogin() {
  2.     Account user   = userManager.login(userId, password);
  3.     Result  result = new ResultSupport();
  4.     if (user == null) {
  5.         result.setSuccess(false);
  6.         result.setResultCode(
  7.                 LoginResultCode.INVALID_USER_OR_PASSWORD);
  8.     } else {
  9.         result.setDefaultModel(“user”, user);
  10.     }
  11.     return result;
  12. }

 

public Result doLogin() {
    Account user   = userManager.login(userId, password);
    Result  result = new ResultSupport();

    if (user == null) {
        result.setSuccess(false);
        result.setResultCode(
                LoginResultCode.INVALID_USER_OR_PASSWORD);
    } else {
        result.setDefaultModel("user", user);
    }

    return result;
}

如果没有提供event参数,或未匹配event,那么默认的doPerform()方法将被执行

 

 

3. CommandDispatcher 实现

 

CommandDispatcher是一个“分发器”。它的功能就是根据command的名字找到相应的业务逻辑对象,并执行之。每一个业务逻辑对象对应一个或一组相关的use case。例如:在用户管理系统中,用户的创建、删除、修改等操作可以看作一个use case,因而我们可以写一个业务逻辑对象——“UserManagementAO”——来处理这个use case。“AO”是“ApplicationObject”的缩写,每一个AO必须实现ApplicationObject接口。

 

CommandDispatcher有多种实现,以适应多种需要:

 

 

 

 

序号 CommandDispatcher的实现 说明
1. Stateless Session Bean

(CommandDispatcherBean)

 

使用Stateless Session Bean来分发Command。该实现允许进行分布式的商业逻辑调用。
2. Message-driven Bean

(CommandDispatcherClient)

通过Message-driven Bean来分发Command,通过JMS来发送Command请求。该实现允许进行异步的商业逻辑调用。
3. Plain Javabean

(CommandDispatcherLogic)

通过普通的Javabean来分发Command。这个实现非常适合在非EJB的环境下调用商业逻辑。
4. NOOP

(CommandDispatcherNoop)

不做任何事情的分发器。这个实现非常适合在程序的开发阶段,用来调试程序。或者当商业逻辑还未开发完成时,调用者可以利用该分发器来“调用”商业逻辑,以便调用者的代码可以被顺利地开发。
5. Selector

(CommandDispatcherSelector)

该分发器可根据Command的内容来自动先择合适的其它CommandDispatcher。这样,我们就可以更方便地控制CommandDispatcher的行为。例如,在调用者完全不知情的情况下,将某个Command的处理转变为利用Message-driven bean来异步处理。

 

 

 

 

 

尽管有这么多种CommandDispatcher的实现,但是表现层完全不用了解这些细节。所有的CommandDispatcher都是通过spring来配置的

 

 

 

4. 小结

 

Command Pattern是基于request-response的模式。客户端创建command,服务端响应command并返回结果给客户端 —— 类似WEB层的模式。而客户端和服务端是通过command dispatcher来连接的。
这种模式有什么好处呢?
最大的好处,就是客户端和服务端完全分离。无论是Web-tier还是Biz-tier都不用了解command分发的细节 —— 这些细节对代码是透明的。
其次,所有的CommandDispatcher都是通过spring来配置的,因此也很容易创建新的CommandDispatcher模式。目前已经支持同步、异步等操作。
那么,这种模式有什么缺点呢?任何设计模式都有适用的场合,也有不利的一面。Command Pattern也不例外。
这种模式最大的缺点是,没有一种统一的方法,可以知道业务逻辑层所需要的参数个数、类型,同样也很难知道返回值的数量和类型。这样会增加客户端/服务端程序员交流的成本。

http://blog.csdn.net/itomge/article/details/18041829