操作系统: Windows 7
JDK: 1.8.0_05
我正在学习一些简单的RMI教程,包括Oracle的“计算”示例(Compute)。启动我的服务器不需要代码库,对类似问题的回答是“代码库是可选的”然而,我的服务器无法注册远程对象,除非它的接口位于某个代码库中。
我确保我的计算接口是可用的Web服务器上运行localhost,启动注册表服务器像这样:
set CLASSPATH=
rmiregistry -J-Djava.rmi.server.codebase="http://localhost:80/"
一切正常:
Exporting stub
Locating registry
Binding stub
ComputeEngine bound
但是如果我从Web服务器的路径中删除Compute.class,我会得到一个ClassNotFoundExcema:
Exporting stub
Locating registry
Binding stub
java.rmi.ServerException: RemoteException occurred ...:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: edu.uweo.java2.rmi.compute.server.Compute
我可以从Web服务器日志中看到有人试图下载Compute.class:
GET '/edu/uweo/java2/rmi/compute/server/Compute.class'
我还尝试在不指定代码库的情况下启动注册表服务器:
set CLASSPATH=
rmiregistry
当我这样做时,没有人试图联系我的web服务器(这并不让我感到惊讶),但我仍然得到ClassNotFoundException。
我的代码来自Oracle的教程,附带了两个额外的打印诊断:
try
{
String name = "Compute";
ComputeEngine engine = new ComputeEngine();
System.out.println( "Exporting stub" );
Compute stub =
(Compute)UnicastRemoteObject.exportObject( engine, 0 );
System.out.println( "Locating registry " );
Registry registry = LocateRegistry.getRegistry();
System.out.println( "Binding stub" );
registry.rebind( name, stub );
System.out.println( "ComputeEngine bound" );
}
谁能告诉我我错过了什么?
谢谢。
它以这种方式工作的原因是RMI注册表本身是使用RMI实现的。因此,当您在一个应用程序中调用
bind
时,rmiregistry
进程中的Registry
的实际实现将收到一个存根对象,该存根对象实现所有Remote
接口,就像所有RMI调用将引用传递给远程对象一样。
因此,
rmiregistry
进程需要访问您绑定的对象实现的所有远程接口,但正如您已经发现的,它的实际内容是无关的,因为注册表永远不会调用它上面的任何方法。它所做的只是将远程存根交给查找
的调用者,在这种情况下,存根被序列化并传输到远程调用者的JVM,在JVM中创建等效存根,再次实现存根(以及原始对象)实现的所有远程接口。
因此,
rmiregistry
进程中的接口(如果您将其作为独立进程启动)所发生的一切就是,通过让存根相应地实现远程对象所实现的远程接口,记录有关远程接口的信息,并将其传递给执行查找的所有其他远程应用程序。
原则上,通过不使用RMI和记录实现的接口而不需要它们的类文件,可以以不同的方式实现整个注册表,但是,这将是一项巨大的工作,因为在简单使用RMI时,您必须实现免费获得的所有东西。
但是请注意,如果您只有一台服务器,那么您可以通过让服务器本身在自己的JVM中创建注册表来简化一切。然后,您不需要启动另一个进程,也不需要考虑它的类路径/代码库。
你是正确的,你不需要使用代码库功能。然而,这意味着您的远程接口、它所依赖的类以及存根(如果您正在使用)必须对客户端和注册表的类路径都可用。您得到的异常表明注册表的CLASSPATH上没有这些类。
本文向大家介绍为什么我们需要微服务容器?相关面试题,主要包含被问及为什么我们需要微服务容器?时的应答技巧和注意事项,需要的朋友参考一下 要管理基于微服务的应用程序,容器是最简单的选择。它帮助用户单独部署和开发。您还可以使用Docker将微服务封装到容器的镜像中。没有任何额外的依赖或工作,微服务可以使用这些元素。
null
使用oAuth 2.0,在“授权代码”授权授予中,我首先调用“/授权”,获取代码,然后在对“/令牌”的调用中使用该代码来获取访问令牌。 我的问题:为什么这是流?我想这是出于安全原因,但我想不出来。为什么实现是这样的,而不是在第一次调用(“/authorize”)后立即获取访问令牌? 为什么我们需要这个代码?
问题内容: 我的应用程序中有一个弹出模式服务,名为。它只是在上翻转了一些布尔值,从而导致2条指令正确显示/隐藏。这是显示新模态时调用的函数 如您所见,我显示不透明的背景,然后设置了一个名为的变量,该变量随后通过DI传递到我的指令中。但是后来我注意到我的模态没有出现在适当的时候,而是在变量设置为true 之后出现在NEXT摘要循环中。然后,我必须添加作业周围的内容才能使其正常工作。但是,我认为仅当我
以我的拙见,关于“什么是单子”这个著名问题的答案,尤其是投票最多的答案,试图解释什么是单子,而没有明确解释为什么单子是真正必要的。它们能被解释为一个问题的解决方案吗?
问题内容: 我正在尝试学习Go Web编程,这是一个简单的Web服务器:它可以打印出被调用的时间。 刷新页面时,我得到: 问题:为什么是1、3、5倍而不是1,2,3 …?该函数的调用顺序是什么? 问题答案: 这是因为每个传入请求都被路由到您的处理函数,并且浏览器在后台进行了多次调用,尤其是。 并且由于您的Web服务器没有发送回有效的网站图标,因此当您在浏览器中刷新页面时,它将再次请求它。 在Chr