0

我目前正在考虑 Java Swing WebStart 应用程序(胖客户端)和在 Tomcat 上运行的一些远程服务之间的远程处理/序列化的一些设计细节。我想使用 http 兼容的传输与服务器通信,因为我已经在使用 Spring,我认为 Spring 的 HTTP Remoting 是一个不错的选择。但我对这里的其他选择持开放态度。我的设计问题最好用一些小例子来说明

客户端将调用远程端的一些服务。示例服务接口:

public interface ServiceInterface extends Serialiazable {
    // Get immutable reference data
    public List<Building> getBuildings();
    public List<Office> getOffices();

    // Create, read and update Employee objects
    public insertEmployee(Employee employee);
    public Employee getEmployee();
    public void updateEmployee(Employee employee);
}

Building 和 Office 是不可变的引用数据对象,例如

public Building implements Serializable {
    String name;
    public Building(String name) { this.name = name; }
    public String getName() { return name; }
}

public Office implements Serializable {
    Building building;
    int maxEmployees;
    public Office(Building building, int maxEmployess) {
        this.building = building;
        this.maxEmployees = maxEmployees;
    }
    public Building getBuilding() { return building; }
    punlic int getMaxEmployees() { retrun maxEmployees; }
}

可用的建筑物和办公室在运行时不会改变,并且应该由客户端预先设置以具有可供选择列表、过滤条件...我希望客户端上的每个特定建筑物和办公室只有一个实例和一个实例在服务器端。在服务器端这不是一个大问题,但在我看来,当我在 getBuildings() 之后调用 getOffices() 时,问题就从这里开始了。getOffices() 返回的 Buildings 共享相同的 Buildings 实例(如果它们分配了相同的 Buildings),但 getOffices() 返回的 Buildings(在 Office 对象中引用)与 getBuildings() 返回的 Buildings 实例不同。

这可以通过使用一些 getReferenceDate() 方法在同一个调用中返回两个信息来解决,但是如果我有员工引用办公室,问题就会开始。

我正在考虑一些自定义序列化(readObject,writeObject)只传输主键,而不是从某个保存引用数据对象的类中获取对象的实例。但这是解决这个问题的最佳方案吗?我假设这个问题不是一个罕见的问题,但在谷歌上没有找到任何东西。有更好的解决方案吗?如果没有,实现它的最佳方法是什么?

4

2 回答 2

1

如果您要序列化,您可能需要实现 readResolve 以保证您不会创建额外的实例:

来自 Serializable 的 javadoc:

当从流中读取实例时需要指定替换的类应该使用精确的签名实现这个特殊方法。

ANY-ACCESS-MODIFIER 对象 readResolve() 抛出 ObjectStreamException;

我似乎记得在枚举前的日子里读过这种方法来处理必须保证是单数的对象的序列化,比如类型安全的枚举。

我还强烈建议您在序列化类中包含手动 serialVersionUID,以便您可以手动控制应用程序何时决定您的类表示无法反序列化的不兼容版本。

然而,在更基本的层面上,我会质疑整个方法 - 而不是试图通过网络保证对象身份,这听起来至少是一场并发噩梦,为什么不只是传递原始数据和你的逻辑是否通过 id 来确定身份,就像我们在我祖父时代所做的那样?您的后端有一个构建对象,它从前端获取一个,通过 ID 进行比较(如果您更改了前端的对象,则必须将对象提交到中央数据存储并确定更改的内容,这可能是与多个客户端的同步问题,但无论如何你都会遇到这个问题)。

通过 Spring-httpclient 远程传递数据非常简单,比 RMI 低级一些。

于 2009-02-03T16:27:19.790 回答
0

首先,我建议您使用RMI进行远程处理,它可以通过 HTTP (IIRC) 代理。其次,如果你序列化ServiceInterface,我相信序列化机制将维护它在远程JVM中反序列化时的相对引用。

于 2009-02-03T16:12:52.613 回答