📄 ch04.html
字号:
Unix:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087791"></A>export CLASSPATH=""</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087792"></A>rmiregistry &</PRE></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087793"></A><EM CLASS="Bold">Win32:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087794"></A>unset CLASSPATH</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087795"></A>start rmiregistry</PRE><P CLASS="Body"><A NAME="pgfId-1087796"></A><EM CLASS="Bold">Start the Remote Server. </EM>Once the <EM CLASS="CODE">rmiregistry</EM> is running, you can start the remote server, <EM CLASS="CODE">RegistrationServer</EM>. The <EM CLASS="CODE">RegistrationServer</EM> program registers the name <EM CLASS="CODE">registration2</EM> with the <EM CLASS="CODE">rmiregistry</EM> name server, and any client can use this name to retrieve a reference to the remote server object, <EM CLASS="CODE">RegistrationHome</EM>. </P><P CLASS="Body"><A NAME="pgfId-1087797"></A>To run the example, copy the <EM CLASS="CODE">RegistrationServer</EM> and <EM CLASS="CODE">RegistrationImpl</EM> classes and the associated stub classes to a remotely accessible area and start the server program. </P></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087798"></A><EM CLASS="Bold">Unix:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087799"></A>cp *_Stub.class /home/zelda/public_html/registration</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087800"></A>cp RegistrationImpl.class /home/zelda/public_html/registration</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087801"></A>cd /home/zelda/public_html/registration</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087802"></A>java -Djava.server.hostname=phoenix.sun.com registration.RegistrationServer</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087803"></A> </PRE></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087804"></A><EM CLASS="Bold">Windows:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087805"></A>copy *_Stub.class \home\zelda\public_html\registration</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087806"></A>copy RegistrationImpl.class \home\zelda\public_html\registration</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087807"></A>cd \home\zelda\public_html\registration</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087808"></A>java -Djava.server.hostname=phoenix.sun.com registration.RegistrationServer</PRE><P CLASS="Body"><A NAME="pgfId-1087815"></A>The following key <A NAME="marker-1087809"></A><A NAME="marker-1087810"></A><A NAME="marker-1087811"></A><A NAME="marker-1087812"></A><A NAME="marker-1087813"></A><A NAME="marker-1087814"></A>properties are used to configure RMI servers and clients. These properties can be set inside the program or supplied as command line properties to the Java virtual machine. </P><UL><LI CLASS="BL"><A NAME="pgfId-1087817"></A>The <EM CLASS="CODE">java.rmi.server.codebase</EM><A NAME="marker-1087816"></A> property specifies where the publicly accessible classes are located. On the server this can be a simple file URL to point to the directory or JAR file that contains the classes. If the URL points to a directory, the URL must terminate with a file separator character, "<EM CLASS="CODE">/</EM>". If you are not using a file URL, you will either need an HTTP server to download the remote classes or have to manually deliver the remote client stub and remote interface classes in, for example, a JAR file.</LI><LI CLASS="BL"><A NAME="pgfId-1087819"></A>The <EM CLASS="CODE">java.rmi.server.hostname</EM><A NAME="marker-1087818"></A> property is the complete host name of the server where the publicly accessible classes reside. This is only needed if the server has problems generating a fully qualified name by itself. </LI><LI CLASS="BL"><A NAME="pgfId-1087821"></A>The <EM CLASS="CODE">java.rmi.security.policy</EM><A NAME="marker-1087820"></A> property specifies the policy file with the permissions needed to run the remote server object and access the remote server classes for download.</LI></UL></DIV></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087823"></A><A NAME="66513"></A>Establishing Remote Communications</H5><P CLASS="Body"><A NAME="pgfId-1087825"></A><A NAME="marker-1087824"></A>Client programs communicate with each other through the server. The server program consists of three files. The<A NAME="marker-1087826"></A><A NAME="marker-1087827"></A> <EM CLASS="CODE">Registration.java</EM> and <EM CLASS="CODE">RegistrationHome.java</EM> remote interface files define the methods that can be called remotely, and the <EM CLASS="CODE">RegistrationServer.java</EM> class file defines the <EM CLASS="CODE">RegistrationServer</EM> and <EM CLASS="CODE">RegistrationImpl</EM> classes that implement the methods. </P><P CLASS="Body"><A NAME="pgfId-1087829"></A>To establish <A NAME="marker-1087828"></A>remote communications, both the client and server programs need to access the remote interface classes. The server needs the interface classes to generate the interface implementation, and the client uses the remote interface class to call the remote server method implementation. For example, <EM CLASS="CODE">SellerBean</EM> creates a reference to <EM CLASS="CODE">RegistrationHome</EM>, the interface, and not <EM CLASS="CODE">RegistrationServer</EM>, the implementation, when it needs to create a user registration. </P><P CLASS="Body"><A NAME="pgfId-1087830"></A>Besides the server interfaces and classes, you need stub and skeleton classes to establish remote communications. The stub and skeleton classes needed in this example are generated when you run the <EM CLASS="CODE">rmic</EM> compiler command on the <EM CLASS="CODE">RegistrationServer</EM> and <EM CLASS="CODE">SellerBean</EM> classes. </P><P CLASS="Body"><A NAME="pgfId-1087833"></A>The generated <EM CLASS="CODE">SellerBean</EM>, <A NAME="marker-1087831"></A><EM CLASS="CODE">SellerBean_Stub.class,</EM> and <A NAME="marker-1087832"></A><EM CLASS="CODE">SellerBean_ Skel.class</EM> files are needed for the <A NAME="marker-1087834"></A><A NAME="marker-1087835"></A>callback from the server to the <EM CLASS="CODE">SellerBean</EM> client. It is the <EM CLASS="CODE">_Stub.class</EM> file on the client that marshals data to and unmarshals it from the server, while the <EM CLASS="CODE">_Skel.class</EM> class does the same for the server. </P><UL><LI CLASS="NOTE"><A NAME="pgfId-1087836"></A>NOTE In the Java 2 platform, the server side, <EM CLASS="CODE">_Skel.class</EM> file is not used. </LI></UL><P CLASS="Body"><A NAME="pgfId-1087840"></A><EM CLASS="Bold">Data Marshaling. </EM><A NAME="54909"></A><A NAME="marker-1087838"></A><A NAME="marker-1087839"></A>An example of marshaling and unmarshaling data is when you call the <EM CLASS="CODE">RegistrationHome.create</EM> method from <EM CLASS="CODE">SellerBean</EM>, this call is forwarded to the <EM CLASS="CODE">RegistrationServer_Stub.create</EM> method. The <EM CLASS="CODE">RegistrationServer_Stub.create</EM> method wraps the method arguments and sends a serialized stream of bytes to the <EM CLASS="CODE">RegistrationServer_Skel.create</EM> method. </P><P CLASS="Body"><A NAME="pgfId-1087841"></A>As shown in Figure 4.2, the <EM CLASS="CODE">RegistrationServer_Skel.create</EM> method unwraps the serialized bytestream, recreates the arguments to the original <EM CLASS="CODE">RegistrationHome.create</EM> call, and returns the result of calling the real <EM CLASS="CODE">RegistrationServer.create</EM> method back along the same route, but this time wrapping the data on the server side. </P><DIV><H6 CLASS="FC"><A NAME="pgfId-1087846"></A>Figure 4.2 <A NAME="39339"></A>Data marshaling</H6><DIV><IMG SRC="CH04-2.gif"></DIV><P CLASS="Body"><A NAME="pgfId-1087850"></A><A NAME="marker-1087847"></A><A NAME="marker-1087848"></A><A NAME="marker-1087849"></A>Marshaling and unmarshaling data is not without its complications. The first issue is that serialized objects might be incompatible across JDK releases. A Serialized object has an identifier stored with the object that ties the serialized object to its release. If the RMI client and server complain about incompatible serial IDs, you might need to generate backward-compatible <A NAME="marker-1087851"></A><A NAME="marker-1087852"></A>stubs and skeletons using the <EM CLASS="CODE">-vcompat</EM><A NAME="marker-1087853"></A> option to the <A NAME="marker-1087854"></A>rmic compiler. <A NAME="marker-1087855"></A>Another issue is not all objects are serialized by default. </P><P CLASS="Body"><A NAME="pgfId-1087859"></A>Fortunately, in the Java 2 Platform the <A NAME="marker-1087856"></A><A NAME="marker-1087857"></A><A NAME="marker-1087858"></A>Collections API offers alternatives to previously unmarshalable objects. In this example, an <EM CLASS="CODE">ArrayList</EM> from the Collections API replaces the <EM CLASS="CODE">Vector</EM>. If the Collections API is not an option for you, you can create a wrapper class that extends <EM CLASS="CODE">Serializable</EM> and provides <EM CLASS="CODE">readObject</EM> and <EM CLASS="CODE">writeObject</EM> method implementations to convert the object into a bytestream. </P></DIV></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087860"></A><EM CLASS="B-code">RegistrationServer</EM> Class</H5><P CLASS="Body"><A NAME="pgfId-1087862"></A><A NAME="marker-1087861"></A>The <EM CLASS="CODE">RegistrationServer</EM> (RMI) class extends <EM CLASS="CODE">java.rmi.server.UnicastRemoteObject</EM> and implements the <EM CLASS="CODE">create</EM>, <EM CLASS="CODE">findByPrimaryKey,</EM> and <EM CLASS="CODE">findLowCreditAccounts</EM> methods declared in the <EM CLASS="CODE">RegistrationHome</EM> interface. The <EM CLASS="CODE">RegistrationServer.java</EM> source file also includes the implementation for the <EM CLASS="CODE">Registration</EM> remote interface as class <EM CLASS="CODE">RegistrationImpl</EM>. <EM CLASS="CODE">RegistrationImpl</EM> also extends <EM CLASS="CODE">UnicastRemoteObject</EM>. </P><P CLASS="Body"><A NAME="pgfId-1087864"></A><EM CLASS="Bold">Exporting a Remote Object. </EM><A NAME="marker-1087863"></A>Any object you want to be accessible remotely needs to either extend <EM CLASS="CODE">java.rmi.server.UnicastRemoteObject</EM> or use the <EM CLASS="CODE">exportObject</EM> method from the <EM CLASS="CODE">UnicastRemoteObject</EM> class. If you extend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -