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





4.00/5 (1投票)
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 上报告错误。