⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch04.html

📁 java2高级编程
💻 HTML
📖 第 1 页 / 共 5 页
字号:
-iiop</EM> option to generate the stub and the classes necessary for RMI-IIOP. </LI></UL><P CLASS="Body"><A NAME="pgfId-1087654"></A><EM CLASS="Bold">IIOP Server. </EM>The <A NAME="marker-1087652"></A><A NAME="marker-1087653"></A>RMI-IIOP protocol is implemented as a JNDI plug-in, so as before, you need to create an <EM CLASS="CODE">InitialContext</EM>: </P><PRE CLASS="CODE"><A NAME="pgfId-1087655"></A>Hashtable env = new Hashtable();</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087656"></A>env.put(&quot;java.naming.factory.initial&quot;, &quot;com.sun.jndi.cosnaming.&quot; +                                       &quot;CNCtxFactory&quot;);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087657"></A>env.put(&quot;java.naming.provider.url&quot;,&quot;iiop://localhost:1091&quot;);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087658"></A>Context ic = new InitialContext(env);</PRE><P CLASS="Body"><A NAME="pgfId-1087659"></A>The naming factory should look familiar because it is the same CORBA naming service used in CORBA Naming Service (page 60). The main difference is the addition of a URL value specifying the naming service to which to connect. The naming service used here is the <EM CLASS="CODE">tnameserv</EM> program started on port 1091. </P><PRE CLASS="CODE"><A NAME="pgfId-1087660"></A>tnameserv -ORBInitialPort 1091</PRE><P CLASS="Body"><A NAME="pgfId-1087661"></A>The other main change to the server side is to replace calls to <EM CLASS="CODE">Naming.rebind</EM> to use the JNDI <A NAME="marker-1087662"></A><EM CLASS="CODE">rebind</EM><A NAME="marker-1087663"></A> method in the <EM CLASS="CODE">InitialContext</EM> instance. For example: </P><DIV><H6 CLASS="D"><A NAME="pgfId-1087664"></A><EM CLASS="Bold">Old RMI lookup code: </EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087665"></A>SellerHome shome= new SellerHome(&quot;seller&quot;); </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087666"></A>Naming.rebind(&quot;seller&quot;, shome);</PRE></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087667"></A><EM CLASS="Bold">New RMI code: </EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087668"></A>Hashtable env = new Hashtable();</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087669"></A>env.put(&quot;java.naming.factory.initial&quot;,&quot;com.sun.jndi.cosnaming.CNCtxFactory&quot;);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087670"></A>env.put(&quot;java.naming.provider.url&quot;, &quot;iiop://localhost:1091&quot;);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087671"></A>Context ic = new InitialContext(env);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087672"></A>SellerHome shome= new SellerHome(&quot;seller&quot;);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087673"></A>ic.rebind(&quot;seller&quot;, shome);</PRE><P CLASS="Body"><A NAME="pgfId-1087675"></A><EM CLASS="Bold">IIOP Client. </EM><A NAME="marker-1087674"></A>On the client side, the RMI lookup is changed to use an instance of the <EM CLASS="CODE">InitialContext</EM> in place of RMI <EM CLASS="CODE">Naming.lookup</EM>. The returned object is mapped to the requested object by using the <EM CLASS="CODE">narrow</EM> method of the <EM CLASS="CODE">javax.rmi.PortableRemoteObject</EM> class. <EM CLASS="CODE">PortableRemoteObject</EM> replaces <EM CLASS="CODE">UnicastRemoteObject</EM> that was previously available in the RMI server code. </P></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087676"></A><EM CLASS="Bold">Old RMI code: </EM></H6><PRE CLASS="CODE-caption"><A NAME="pgfId-1087678"></A>//API Ref: <A NAME="21536"></A>static Remote lookup(String rminame)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087680"></A><A NAME="marker-1087679"></A>SellerHome shome = (SellerHome)Naming.lookup(&quot;rmi://appserver:1090/seller&quot;);</PRE></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087681"></A><EM CLASS="Bold">New RMI code: </EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087682"></A>Hashtable env = new Hashtable();</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087683"></A>env.put(&quot;java.naming.factory.initial&quot;, &quot;com.sun.jndi.cosnaming.CNCtxFactory&quot;);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087684"></A>env.put(&quot;java.naming.provider.url&quot;, iiop://localhost:1091&quot;);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087685"></A>Context ic = new InitialContext(env);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087686"></A>SellerHome shome = </PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087688"></A>//API Ref: <A NAME="89158"></A>static object narrow(Object narrowFrom, Class narrowTo</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087689"></A>     <A NAME="marker-1087690"></A><A NAME="javax.rmi.PortableRemoteObject class"></A><A NAME="PortableRemoteObject class"></A><A NAME="narrow method"></A>(SellerHome)PortableRemoteObject.narrow(ic.lookup(&quot;seller&quot;), SellerHome)</PRE><P CLASS="Body"><A NAME="pgfId-1087696"></A>The <EM CLASS="CODE">PortableRemoteObject</EM><A NAME="marker-1087694"></A> replaces <EM CLASS="CODE">UnicastRemoteObject</EM><A NAME="marker-1087695"></A> previously available in the RMI server code. The RMI code would either extend <EM CLASS="CODE">UnicastRemoteObject</EM> or call the <EM CLASS="CODE">exportObject</EM><A NAME="marker-1087697"></A> method from the <EM CLASS="CODE">UnicastRemoteObject</EM> class. The <EM CLASS="CODE">PortableRemoteObject</EM> also contains an equivalent <EM CLASS="CODE">exportObject</EM><A NAME="marker-1087698"></A> method. In the current implementation, it is best to explicitly remove unused objects by calling <EM CLASS="CODE">PortableRemoteObject.unexportObject</EM><A NAME="marker-1087699"></A>.</P></DIV></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087700"></A>Improving Lookup Performance</H5><P CLASS="Body"><A NAME="pgfId-1087703"></A><A NAME="marker-1087701"></A><A NAME="marker-1087702"></A>When you run your application, if you find it would be faster to walk the object to the other computer on a floppy, you have a network configuration problem. The source of the problem is how host names and IP addresses are resolved, and there is a workaround. </P><P CLASS="Body"><A NAME="pgfId-1087707"></A>RMI and other naming services use the <EM CLASS="CODE">InetAddress</EM><A NAME="marker-1087704"></A> class to obtain <A NAME="marker-1087705"></A><A NAME="marker-1087706"></A>resolved host name and IP addresses. <EM CLASS="CODE">InetAddress</EM> caches look up results to improve subsequent calls, but when it is passed a new IP address or host name, it performs a cross-reference between the IP address and the host name to prevent address spoofing. If you supply the host name as an IP address, <EM CLASS="CODE">InetAddress</EM> still tries to verify the name of the host. To work around this problem, include the host name and IP address in a <EM CLASS="CODE">hosts</EM> file on the client. </P><P CLASS="Body"><A NAME="pgfId-1087708"></A><EM CLASS="Bold">Unix Systems. </EM>On Unix, the host file is usually <EM CLASS="CODE">/etc/hosts</EM>. </P><P CLASS="Body"><A NAME="pgfId-1087709"></A><EM CLASS="Bold">Windows. </EM>On Windows 95 or 98, the <EM CLASS="CODE">hosts</EM> file is <EM CLASS="CODE">c:&#92;windows&#92;hosts</EM>, (<EM CLASS="CODE">hosts.sam</EM> is a sample file). On Windows NT, the <EM CLASS="CODE">hosts</EM> file is <EM CLASS="CODE">c:&#92;winnt&#92;system32&#92;drivers&#92;etc&#92;hosts.</EM> All you do is put these lines in the host file. The <EM CLASS="CODE">myserver1</EM> and <EM CLASS="CODE">myserver2</EM> entries are the hosts running the remote server and <EM CLASS="CODE">rmiregistry</EM>.</P><PRE CLASS="CODE"><A NAME="pgfId-1087710"></A>127.0.0.1  localhost</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087711"></A>129.1.1.1  myserver1</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087712"></A>129.1.1.2  myserver2</PRE></DIV></DIV><DIV><H4 CLASS="A"><A NAME="pgfId-1087714"></A><A NAME="98657"></A>RMI Registration Server</H4><P CLASS="Body"><A NAME="pgfId-1087716"></A><A NAME="marker-1087715"></A>RMI API enables client and server communications over the Net between programs written in the Java programming language. The Enterprise JavaBeans server transparently implements the necessary RMI code so the client program can reference the enterprise beans running on the server and access them as if they are running locally to the client program. </P><P CLASS="Body"><A NAME="pgfId-1087717"></A>Having RMI built into the Enterprise JavaBeans server is very convenient and saves you coding time, but if you need to use advanced RMI features or integrate RMI with an existing application, you need to override the default RMI implementation and write your own RMI code. </P><P CLASS="Body"><A NAME="pgfId-1087718"></A>This section replaces the container-managed <EM CLASS="CODE">RegistrationBean</EM> from the section How Enterprise Beans Are Used in the Example (from Chapter 2) with an RMI-based registration server. The container-managed <EM CLASS="CODE">SellerBean</EM> (Chapter 2) is also changed to call the new RMI registration server using a Java 2 RMI lookup call. </P><DIV><H5 CLASS="B"><A NAME="pgfId-1087719"></A>About RMI</H5><P CLASS="Body"><A NAME="pgfId-1087721"></A><A NAME="marker-1087720"></A>The RMI API lets you access a remote server object from a client program by making simple method calls on the server object. While other distributed architectures for accessing remote server objects such as Distributed Component Object Model (DCOM) and Common Object Request Broker Architecture (CORBA) return references to the remote object, the RMI API not only returns references, but provides these additional benefits. </P><UL><LI CLASS="BL"><A NAME="pgfId-1087722"></A>The RMI API handles remote object references (call by reference) and can also return a copy of the object (call by value). </LI><LI CLASS="BL"><A NAME="pgfId-1087723"></A>If the client program does not have local access to the class from which a local or remote object was instantiated, RMI services can download the class file.</LI></UL><P CLASS="Body"><A NAME="pgfId-1087727"></A><EM CLASS="Bold">Serialization and Data Marshaling. </EM><A NAME="marker-1087724"></A><A NAME="marker-1087725"></A><A NAME="marker-1087726"></A>To transfer objects, the RMI API uses the Serialization API to wrap (marshal) and unwrap (unmarshal) the objects. To marshal an object, the Serialization API converts the object to a stream of bytes, and to unmarshal an object, the Serialization API converts a stream of bytes into an object. You can find more informationon data marshaling in Data Marshaling (page 73).</P><P CLASS="Body"><A NAME="pgfId-1087729"></A><EM CLASS="Bold">RMI over IIOP. </EM><A NAME="marker-1087728"></A>One of the initial disadvantages to RMI was that its sole reliance on the Java platform to write the interfaces made integration into existing legacy systems difficult. However, RMI over IIOP discussed in the section Lookup Services earlier in this chapter lets RMI communicate with any system or language that CORBA supports. </P><P CLASS="Body"><A NAME="pgfId-1087730"></A>If you combine improved integration with the ability of RMI to burrow through firewalls using HTTP firewall proxying, you might find distributing your business logic using RMI is easier than a socket-based solution. </P><UL><LI CLASS="NOTE"><A NAME="pgfId-1087731"></A>NOTE Transferring code and data are key parts of the Jini System software specification. In fact, adding a discovery and join service to the RMI services would create something very similar to what you get in the Jini architecture. </LI></UL></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087732"></A>RMI in the Auction Application</H5><P CLASS="Body"><A NAME="pgfId-1087734"></A><A NAME="marker-1087733"></A>The RMI-based <EM CLASS="CODE">RegistrationServer</EM> (RMI) has the following new methods: </P><UL><LI CLASS="BL"><A NAME="pgfId-1087735"></A>A new <EM CLASS="CODE">create</EM> method for creating a new user.</LI><LI CLASS="BL"><A NAME="pgfId-1087736"></A>A new <EM CLASS="CODE">find</EM> method for finding a user. </LI><LI CLASS="BL"><A NAME="pgfId-1087737"></A>A new <EM CLASS="CODE">search</EM> method for the custom search of users in the database.</LI></UL><P CLASS="Body"><A NAME="pgfId-1087741"></A><A NAME="marker-1087738"></A><A NAME="marker-1087739"></A><A NAME="marker-1087740"></A>The new custom search passes results back to the calling client by way of an RMI callback. The RMI callback custom search is similar to the finder methods used in the bean- and container-managed examples from Auction House Application (Chapter 2) and Data and Transaction Management (Chapter 3), except in the RMI version, it can take more time to generate the results because the remote registration server calls a remote method exported by the RMI-based <EM CLASS="CODE">

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -