📄 ch04.html
字号:
SellerBean</EM> (RMI) client. </P><P CLASS="Body"><A NAME="pgfId-1087742"></A>If the calling client is written in the Java programming language, and is not, for example, a Web page, the server can update the client as soon as the results are ready. But, the HTTP protocol used in most browsers does not allow results to be pushed to the client without a request for those results. This means the resulting Web page is not created until the results are ready, which can add a small delay. </P><P CLASS="Body"><A NAME="pgfId-1087743"></A><EM CLASS="Bold">Class Overview. </EM>The two main classes in the RMI-based auction implementation are <EM CLASS="CODE">SellerBean</EM> (RMI) and <EM CLASS="CODE">RegistrationServer</EM> (RMI). <EM CLASS="CODE">SellerBean</EM> is called from <EM CLASS="CODE">AuctionServlet</EM> (RMI) to insert an auction item into the database and check for low account balances. </P><P CLASS="Body"><A NAME="pgfId-1087744"></A>The example models the Enterprise JavaBeans architecture in that a user's registration details are separate from the code to create and find the registration details. That is, the user's registration details provided by the <EM CLASS="CODE">Registration</EM> (RMI) class are separate from the code to create and find a <EM CLASS="CODE">Registration</EM> object, which is in the <EM CLASS="CODE">RegistrationHome</EM> (RMI) class. </P><P CLASS="Body"><A NAME="pgfId-1087745"></A>The remote interface implementation in <EM CLASS="CODE">RegistrationHome</EM> is bound to the <EM CLASS="CODE">rmiregistry</EM>. When a client program wants to manipulate a user's registration details, it must first look up the reference to the <EM CLASS="CODE">RegistrationHome</EM> object in the <EM CLASS="CODE">rmiregistry</EM>. </P><P CLASS="Body"><A NAME="pgfId-1087747"></A><EM CLASS="Bold">File Summary. </EM><A NAME="marker-1087746"></A>All the source code files for the RMI-based example are described in the bullet list below. </P><UL><LI CLASS="BL"><A NAME="pgfId-1087748"></A><EM CLASS="CODE">SellerBean</EM> (RMI): Client program that calls the <EM CLASS="CODE">RegistrationServer.verifypasswd</EM> and <EM CLASS="CODE">RegistrationServer.findLowCreditAccounts</EM> remote methods. <EM CLASS="CODE">SellerBean</EM> also exports its <EM CLASS="CODE">updateResults</EM> method that <EM CLASS="CODE">RegistrationServer</EM> calls when it completes its <EM CLASS="CODE">RegistrationServer.findLowCreditAccounts</EM> search.</LI><LI CLASS="BL"><A NAME="pgfId-1087749"></A><EM CLASS="CODE">RegistrationServer</EM> (RMI): Remote server object that implements the <EM CLASS="CODE">RegistrationHome</EM> and <EM CLASS="CODE">Registration</EM> remote interfaces. </LI><LI CLASS="BL"><A NAME="pgfId-1087750"></A><EM CLASS="CODE">Registration</EM> (RMI): Remote interface that declares the <EM CLASS="CODE">getUser</EM>, <EM CLASS="CODE">verifypasswd</EM>, and other remote methods for managing a user's registration details. </LI><LI CLASS="BL"><A NAME="pgfId-1087751"></A><EM CLASS="CODE">RegistrationHome</EM> (RMI): Remote interface that declares the <EM CLASS="CODE">create</EM>, <EM CLASS="CODE">findByPrimaryKey</EM>, and <EM CLASS="CODE">findLowCreditAccounts</EM> remote methods that create or return instances of registration details. </LI><LI CLASS="BL"><A NAME="pgfId-1087752"></A><EM CLASS="CODE">RegistrationImpl.java</EM>: The <EM CLASS="CODE">RegistrationServer</EM> (RMI) source file includes the implementation for the <EM CLASS="CODE">Registration</EM> remote interface as class <EM CLASS="CODE">RegistrationImpl</EM>.</LI><LI CLASS="BL"><A NAME="pgfId-1087753"></A><EM CLASS="CODE">RegistrationPK</EM> (RMI): Class that represents a user's registration details using just the primary key of the database record. </LI><LI CLASS="BL"><A NAME="pgfId-1087754"></A><EM CLASS="CODE">ReturnResults</EM> (RMI): Remote interface that declares the <EM CLASS="CODE">updateResults</EM> method the <EM CLASS="CODE">SellerBean</EM> class implements as a callback. </LI><LI CLASS="BL"><A NAME="pgfId-1087755"></A><EM CLASS="CODE">AuctionServlet</EM> (RMI): Modified version of the original <EM CLASS="CODE">AuctionServlet</EM> class where registration accounts are created by calling the RMI <EM CLASS="CODE">RegistrationServer</EM> directly. The <EM CLASS="CODE">auction</EM> servlet also calls the <EM CLASS="CODE">SellerBean.auditAccounts</EM> method, which returns a list of users with a low account balance. </LI></UL><P CLASS="Body"><A NAME="pgfId-1087756"></A>The <EM CLASS="CODE">auditAccounts</EM> method is called with the following URL, which does a simple check to verify the request came from the local host. </P><PRE CLASS="CODE"><A NAME="pgfId-1087757"></A>http://phoenix.eng.sun.com:7001/AuctionServlet?action=auditAccounts</PRE><P CLASS="Body"><A NAME="pgfId-1087760"></A><A NAME="marker-1087758"></A><A NAME="marker-1087759"></A>You also need the following <EM CLASS="CODE">java.policy</EM> security policy file to grant the permissions needed to run the example on the Java 2 Platform. </P><PRE CLASS="CODE"><A NAME="pgfId-1087761"></A>grant {</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087762"></A> permission java.net.SocketPermission "*:1024-65535", "connect,accept,resolve";</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087763"></A> permission java.net.SocketPermission "*:80", "connect";</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087764"></A> permission java.lang.RuntimePermission "modifyThreadGroup";</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087765"></A> permission java.lang.RuntimePermission "modifyThread";</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087766"></A>};</PRE><P CLASS="Body"><A NAME="pgfId-1087767"></A>Most RMI applications need the two socket permissions for socket and HTTP access to the specified ports. The two thread permissions were listed in a stack trace as being needed for the <EM CLASS="CODE">RegistrationImpl</EM> class to create a new inner thread. </P><P CLASS="Body"><A NAME="pgfId-1087768"></A>In the Java 2 platform, when a program does not have all the permissions it needs, the Java virtual machine generates a stack trace that lists the permissions that need to be added to the security policy file. See Signed Applets and Security Managers (page 305) for more information on this and other security topics.</P><P CLASS="Body"><A NAME="pgfId-1087769"></A><EM CLASS="Bold">Compile the Example. </EM>Before describing the RMI-based code for the above classes, here is the command sequence to compile the example on the Unix and Win32 platforms: </P><DIV><H6 CLASS="D"><A NAME="pgfId-1087770"></A><EM CLASS="Bold">Unix:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087771"></A>javac registration/Registration.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087772"></A>javac registration/RegistrationPK.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087773"></A>javac registration/RegistrationServer.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087774"></A>javac registration/ReturnResults.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087775"></A>javac seller/SellerBean.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087776"></A>rmic -d . registration.RegistrationServer</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087777"></A>rmic -d . registration.RegistrationImpl</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087778"></A>rmic -d . seller.SellerBean</PRE></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087779"></A><EM CLASS="Bold">Win32:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087780"></A>javac registration\Registration.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087781"></A>javac registration\RegistrationPK.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087782"></A>javac registration\RegistrationServer.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087783"></A>javac registration\ReturnResults.java javac seller\SellerBean.java</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087784"></A>rmic -d . registration.RegistrationServer</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087785"></A>rmic -d . registration.RegistrationImpl</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087786"></A>rmic -d . seller.SellerBean</PRE><P CLASS="Body"><A NAME="pgfId-1087787"></A><EM CLASS="Bold">Start the RMI Registry. </EM>Because you are using your own RMI code, you have to explicitly start the RMI Registry so the <EM CLASS="CODE">SellerBean</EM> object can find the remote enterprise beans. The <EM CLASS="CODE">RegistrationServer</EM> uses the RMI <EM CLASS="CODE">Registry</EM> to register or bind enterprise beans that can be called remotely. The <EM CLASS="CODE">SellerBean</EM> client contacts the registry to look up and get references to the remote <EM CLASS="CODE">AuctionItem</EM> and <EM CLASS="CODE">Registration</EM> enterprise beans. </P><P CLASS="Body"><A NAME="pgfId-1087788"></A>Because RMI allows code and data to be transferred, you must be sure the system classloader does not load extra classes that could be mistakenly sent to the client. In this example, extra classes would be the stub and skel class files and the <EM CLASS="CODE">RegistrationSever</EM> and <EM CLASS="CODE">RegistrationImpl</EM> classes. To prevent them being mistakenly sent, they should not appear anywhere in the <EM CLASS="CODE">CLASSPATH</EM> when you start the RMI <EM CLASS="CODE">Registry</EM>, and because the current path could be included automatically, you need to start the RMI <EM CLASS="CODE">Registry</EM> away from the code workspace, too. </P><P CLASS="Body"><A NAME="pgfId-1087789"></A>The following commands prevent the sending of extra classes by unsetting the <EM CLASS="CODE">CLASSPATH</EM> before starting the RMI <EM CLASS="CODE">Registry</EM> on the default 1099 port. You can specify a different port by adding the port number as follows: <EM CLASS="CODE">rmiregistry 4321 &</EM>. If you specify a different port number, you must specify the same port number in both your client <EM CLASS="CODE">lookup</EM> and server <EM CLASS="CODE">rebind</EM> calls. </P></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087790"></A><EM CLASS="Bold">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -