使用远程服务进行Java序列化和实例共享

时间:2009-02-03 16:04:22

标签: java serialization remoting

我目前正在考虑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返回的建筑物共用建筑物的同一个实例(如果他们有分配相同的大楼),但()()由getOffices返回的建筑物(在Office对象的引用)是不一样的情况下,通过getBuildings返回的建筑物。

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

我在考虑一些自定义序列化(readObject,writeObject)只传输主键,而不是从包含引用数据对象的某个类获取对象的实例。但这是解决这个问题的最佳方法吗?我认为这个问题不是一个不常见的问题,但在Google上没有找到任何问题。有更好的解决方案吗?如果没有,实施它的最佳方式是什么?

2 个答案:

答案 0 :(得分:1)

如果您要序列化,您可能需要实现readResolve以保证您不创建其他实例:

来自Serializable的javadoc:

  

需要指定的类   当它的一个实例是替换时   从流中读取应该实现   这个特殊的方法与确切   签名。

     

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

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

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

然而,在更基础的层面上,我会质疑整个方法 - 而不是试图保证网络上的对象身份,这听起来至少是并发的噩梦,为什么不通过原始周围的数据并让你的逻辑通过id确定身份,我们在爷爷的日子里这样做了吗?你的后端有一个构建对象,它从前端得到一个,通过ID进行比较(如果你改变了前端的对象,你必须将你的对象提交到你的中央数据存储区并确定改变了什么,这可能是是多个客户端的同步问题,但无论如何你都有这个问题)。

通过Spring-httpclient远程传递数据既简单又简单,比RMI低一点。

答案 1 :(得分:0)

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