2

我将在下面简要概述我的目标,以防万一有更好的替代方法来实现我想要的。 这个问题与我需要的非常相似,但并不完全是我需要的。我的问题...

我有一个界面:

public interface Command<T> extends Serializable {}

..加上一个实现:

public class EchoCommand implements Command<String> {
    private final String stringToEcho;

    public EchoCommand(String stringToEcho) {
        this.stringToEcho = stringToEcho;
    }

    public String getStringToEcho() {
        return stringToEcho;
    }
}

如果我创建另一个接口:

public interface AuthorizedCommand {
    String getAuthorizedUser();
}

..有没有办法在不知道子类类型的情况下在运行时在 EchoCommand 上实现 AuthorizedCommand 接口?

public <C extends Command<T>,T> C authorize(C command) {
    // can this be done so the returned Command is also an
    // instance of AuthorizedCommand?
    return (C) theDecoratedCommand;
}

为什么...我使用 Netty 为自己构建了一个非常简单的基于命令的概念验证客户端/服务器框架。在客户端和服务器之间共享的命令与命令处理程序之间存在一对一的关系。处理程序仅在服务器上,它们实现起来非常简单。这是界面。

public interface CommandHandler<C extends Command<T>,T> {
    public T execute(C command);
}

在客户端,事情也非常简单。在客户端保持简单是我决定尝试基于命令的 API 的主要原因。客户端发送命令并返回 Future。很明显,调用是异步的,而且客户端没有处理诸如将调用包装在SwingWorker. 为什么要针对异步调用(网络上的任何内容)构建同步 API 只是为了将同步调用包装在异步辅助方法中?我为此使用番石榴。

public <T> ListenableFuture<T> dispatch(Command<T> command)

现在我想添加身份验证和授权。我不想强迫我的命令处理程序了解授权,但在某些情况下,我希望他们能够询问有关正在为哪个用户执行命令的某些内容。主要是我希望能够lastModifiedBy对某些数据具有属性。

我正在考虑使用 Apache Shiro,所以显而易见的答案似乎是使用它们SubjectAwareExecutor来获取授权信息ThreadLocal,但是我的处理程序需要了解 Shiro,或者我需要通过找到某种映射命令的方式来抽象它Shiro 中的认证/授权信息。

由于每个命令都已经携带状态并通过我的整个管道传递,如果我可以装饰已授权的命令以便它们实现 AuthorizedCommand 接口,事情就会简单得多。然后我的命令处理程序可以使用已装饰的信息,但它是完全可选的。

if(command instanceof AuthorizedCommand) {
    // We can interrogate the command for the extra meta data
    // we're interested in.
}

这样,我还可以独立于我的应用程序的核心业务逻辑开发与身份验证/授权相关的所有内容。它还会(我认为)让我将会话信息与 Netty 相关联,Channel或者ChannelGroup我认为这对 NIO 框架更有意义,对吧?我认为 Netty 4 甚至可能允许在一个Channel听起来很适合跟踪会话信息之类的东西上设置类型属性(不过我还没有研究过)。

我想要完成的主要事情是能够非常快速地构建应用程序的原型。我想从客户端调度程序开始,它是命令类型到命令处理程序的简单映射,完全忽略了事物的网络和安全方面。一旦我对我的原型感到满意,我将换入基于 Netty 的调度程序(使用 Guice),然后,在开发周期的后期,我将添加 Shiro。

我非常感谢任何评论或建设性的批评。如果我解释的内容有意义并且在普通的旧 Java 中是不可能的,我会考虑在另一种 JVM 语言中构建该特定功能。也许是斯卡拉?

4

1 回答 1

0

你可以尝试做这样的事情:

Java:在运行时扩展类

在运行时,您的代码将扩展要实例化的 Command 类并实现 AuthorizedCommand 接口。这将使该类成为 AuthorizedCommand 的实例,同时保留原始的 Command 类结构。

需要注意的一件事是,您将无法使用“final”关键字扩展任何类。

于 2013-06-18T12:56:53.757 回答