65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 GWT 和 LinkSet 的远程动态命令模式

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2011年1月19日

LGPL3

2分钟阅读

viewsIcon

17031

downloadIcon

258

Command 模式是一个非常有用的解决方案,但在分布式环境中会引起一些问题。

引言

正如在之前的文章中所述,LinkSet 是一个小型库,旨在帮助程序员摆脱声明监听器接口的麻烦。它利用了 Java 5 的特性,并且被设计成可以替代传统的“监听器接口 + 匿名类”的解决方案。以前,它有事件总线支持,现在它支持远程动态 Command 模式。

引言

Command 模式是一个非常有用的解决方案,但在分布式环境中会引起一些问题。当以传统方式实现并通过网络传输时,几乎所有服务器代码也都需要驻留在客户端。当客户端使用与服务器端不同的技术(如 JavaScript 或 Adobe Flex)时,这通常是不可取的,甚至是不可能实现的。

解决方案

最明显的方法是将命令代码与执行代码分开,以便命令仅携带命令名称和可以轻松通过网络传输的数据。然而,这种解决方案带来了在服务器端轻松分发命令的另一个问题。有一个解决方案可以解决这个问题,但是类型安全导致它变得过于复杂。我发现放弃类型安全会使它更容易、更简单。

使用 LinkSet 作为动态命令分发器,配合 GWT 应用

只有两个类使魔法发生。第一个是 CommandExecutor 类,它负责将命令绑定到方法,第二个是 Eexecutor 注解,用于标记方法。

CommandExecutor 类只有一个公共构造函数,它接受对包含执行命令的方法的对象的引用,并且只有一个公共方法 execute,它导致真正的命令执行发生。

以下代码是使用 LinkSet Command 模式支持的 GWT RPC 服务的示例。

命令接口

如果你希望你的客户端是类型安全的,则需要这个接口。

public interface Command<ReturnType extends Serializable> extends Serializable{
}

服务接口

@RemoteServiceRelativePath("rpcservice")
public interface RPCService extends RemoteService {
    public <R extends Serializable> R execute(
      final Command<R> command) throws Throwable;
}

异步服务接口

public interface RPCServiceAsync {
    public <ReturnType extends Serializable> void execute(
            Command<ReturnType> command, AsyncCallback<ReturnType> callback);
}

Servlet 类

这是 LinkSet 实际使用的地方

public class RPCServiceServlet extends RemoteServiceServlet 
             implements RPCService {
        
    // Create an axecutor - the parameter is lamos always "this".
    private final CommandExecutor executor = new CommandExecutor(this); 
    
    @SuppressWarnings("unchecked")
    public <ReturnType extends Serializable> ReturnType execute(
            final Command<ReturnType> command) throws Throwable {

        // call executor and cast a return type.
        return (ReturnType) this.executor.execute(command);
    }
    // Boilerplate  code ends here - the rest is Your application's logic.
    
    // The method is annotated with it's parameter's class (a command's class).
    @Executor(cmdClass = InvalidateSession.class)
    public Null invalidateSession(final InvalidateSession cmd) {

        getThreadLocalRequest().getSession().invalidate();
            // LinkSet cannot exetuce void methods.
            // Use Null class or Object class as return type and return null.
        return null; 
    }

    @Executor(cmdClass = ListUsers.class)
    public ArrayList<User> listDomains(final ListUsers cmd) {

        final ArrayList<User> result = new ArrayList<User>();
        …
        return result;
    }
}

当一个 CommandExecutor 对象被创建时

CommandExecutor executor = new CommandExecutor(this);

它会扫描其参数的类,查找带注解的方法

@Executor(cmdClass = ListUsers.class)
public ArrayList listDomains(final ListUsers cmd) {

并创建一个命令类和方法之间的映射。

execute 方法被调用时

this.executor.execute(command);

它会调用分配给其参数类型的适当方法(通过反射)。

值得注意的是,LinkSet 不依赖于任何外部库,并且它不强制命令继承任何特定类或实现任何特定接口,因此它对应用程序的客户端是完全不可见的。它不仅可以与 GWT 一起使用,还可以与 Adobe Flex、EJB、RMI 和其他框架一起使用。

摘要

LinkSet 是一个对 Java 的轻量级动态方法的试验。如果你喜欢它,请享受使用它...并在 github.com/lbownik/linkset 上报告错误。

 

© . All rights reserved.