如何跨不同的JVM保留对象标识

ldioqlga  于 2022-09-18  发布在  Spring
关注(0)|答案(3)|浏览(166)

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

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

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

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

现在,当我们通过http-emoting(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"
    }
}

问题是,尽管从逻辑的Angular 来看,搜索对象是相同的,但由于序列化,搜索对象是不同的。

问题是,是否有一些技术可以支持或模拟跨VM的对象标识。

clj7thdc

clj7thdc1#

你说得对--对象同一性不同于逻辑上的相等。

  • 对象标识与==进行比较
  • 逻辑相等与.equals(..)进行比较

因此,覆盖equals()方法,一切都会好起来的。记住也要基于相同的字段覆盖hashCode()。使用您的IDE为您生成这两个方法。

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

piah890a

piah890a2#

IMHO试图在多个VM之间保持对象标识等价性是一个失败的提议。就我所知,语言规范不需要VM来支持这一点,所以如果您真的想要可移植的话,在哪里可以做到这一点是有限的。

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

yyyllmsg

yyyllmsg3#

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

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

如果我需要在应用程序服务器中执行某个操作,那么我会将User对象作为参数发送。如果VM为用户加载了相同的会话ID,那么它将使用存储在VM中的对象来知道分配的角色。否则,应用程序将能够更改用户中的角色,并且它将不安全。

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

秘密是这样的:会话ID是通过散列用户名、登录日期和在所有服务器之间共享的秘密密码创建的。

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

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

相关问题