如何在不同 JVM 之间保留对象身份

发布于 2024-09-04 20:22:42 字数 1116 浏览 10 评论 0原文

具体来说,让我用 Spring http-remoting 示例来说明这个问题。

假设我们有一个简单接口的实现:

public SearchServiceImpl implements SearchService {
    public SearchJdo processSearch(SearchJdo search) {
        search.name = "a funky name";
        return search;
    }
}

SearchJdo 本身就是一个简单的 POJO。

现在,当我们通过 http-remoting 从客户端调用该方法时(Spring 调用远程对象的机制,很像使用序列化的 EJB),我们会得到:

public class HTTPClient {
    public static void main(final String[] arguments) {
        final ApplicationContext context = new ClassPathXmlApplicationContext(
            "spring-http-client-config.xml");
        final SearchService searchService =
            (SearchService) context.getBean("searchService");

        SearchJdo search = new SearchJdo();
        search.name = "myName"; 
        // this method actually returns the same object it gets as an argument
        SearchJdo search2 = searchService.processSearch(search);
        System.out.println(search == search2); // prints "false"
    }
}

问题是搜索对象不同,因为序列化,尽管从逻辑角度来看它们是相同的。

问题是是否有某种技术可以支持或模拟跨虚拟机的对象身份。

To be specific let me illustrate the question with Spring http-remoting example.

Suppose we have such implementation of a simple interface:

public SearchServiceImpl implements SearchService {
    public SearchJdo processSearch(SearchJdo search) {
        search.name = "a funky name";
        return search;
    }
}

SearchJdo is itself a simple POJO.

Now when we call the method from a client through http-remoting (Spring's mechanism of calling remote objects much like EJB that uses serialization) we'll get:

public class HTTPClient {
    public static void main(final String[] arguments) {
        final ApplicationContext context = new ClassPathXmlApplicationContext(
            "spring-http-client-config.xml");
        final SearchService searchService =
            (SearchService) context.getBean("searchService");

        SearchJdo search = new SearchJdo();
        search.name = "myName"; 
        // this method actually returns the same object it gets as an argument
        SearchJdo search2 = searchService.processSearch(search);
        System.out.println(search == search2); // prints "false"
    }
}

The problem is that the search objects are different because of serializaton although from logical prospective they are the same.

The question is whether there are some technique that allows to support or emulate object identity across VMs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你说过了——对象同一性不同于逻辑相等。

  • 对象身份与 == 进行比较
  • 逻辑相等性与 .equals(..) 进行比较

因此重写 equals() 方法,所有内容都将是美好的。请记住也要根据相同的字段覆盖hashCode()。使用您的 IDE 为您生成这 2 个方法。

Teracotta VM 集群 允许在 VM 之间共享对象,但这不适合您的情况。)

You said it - object identity is different from logical equality.

  • object identity is compared with ==
  • logical equality is compared with .equals(..)

So override the equals() method and all will be fine. Remember to override hashCode() based on the same field(s) as well. Use your IDE to generate these 2 methods for you.

(Teracotta VM clustering allows sharing objects between VMs, but that doesn't fit your case.)

硪扪都還晓 2024-09-11 20:22:42

恕我直言,试图在虚拟机之间保持对象身份平等是一个失败的提议。
据我所知,语言规范不需要虚拟机来支持它,因此如果您真正想要可移植,您可以实现的地方将受到限制。

我可以问一下为什么你不直接使用你自己提供的唯一 ID 吗? Java GUID 虽然昂贵,但是是可序列化的。

IMHO attempting to preserve object identity equality across VMs is a losing proposition.
To the best of my knowledge the language specification does not require a VM to support that, so you would be limited in where you can pull off if you truly want to be portable.

May I ask why you don't just use some unique ID that you supply yourself? Java GUIDs, while expensive, are serializable.

╄→承喏 2024-09-11 20:22:42

我这样做过一次,但我不太确定这是否是正确的方法:

每个用户都有一个用户名、会话 ID、角色和附加到用户对象的登录日期。每次我登录虚拟机时,系统都会将一个 User 对象加载到内存中;我还将用户对象返回给应用程序。

如果我需要在应用程序服务器中执行操作,那么我将发送用户对象作为参数。如果虚拟机让用户加载相同的会话 ID,那么它将使用存储在虚拟机中的对象来了解分配的角色。否则,应用程序将能够更改用户的角色,这将是不安全的。

如果应用程序必须更改应用程序服务器,则会将用户对象发送到新服务器,而新服务器将无法在其记录中找到该用户。

秘密如下:会话 ID 是通过对用户名、登录日期和所有服务器共享的秘密密码进行哈希处理而创建的。

一旦新服务器发现会话ID是一致的,那么它就会从数据库加载角色作为可靠的信息源。

抱歉,如果我之前无法写这篇文章,但希望它对某人有所帮助。

I did this once, but I'm not quite sure if this is a right approach:

Every user had a username, session id, roles, and a login date attached to a user object. Every time I logged into a VM the system would load a User object into memory; I would also return the user object to the application.

If I needed to execute an action within the application server, then I would send the user object as an argument. If the VM had the User loaded with the same session ID then it would use the object stored in the VM to know the assigned roles. Otherwise, the application would then be capable of changing the roles in the user and it wouldn't be secure.

If the application had to change the application server, then it sends the user object to the new server and the new server wouldn't be able to find the user within its records.

HERE IS THE SECRET: The session ID is created hashing the username, the login date and a secret password shared among all of the servers.

Once the new server finds that the session ID is coherent, then it would load the roles from the database as a reliable source of information.

Sorry if I couldn't write this before, but hope it helps for someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文