我現在的編程方法,不再是以前的整塊應用,和C/S應用的兩層架構,現在流行的編程方式是三層架構,就是表示層,商業邏輯,還有數據庫都相互獨立。
遠程方法調用正是基于三層架構設計的中間層。遠程方法調用的原理是樁和骨架結構。主要有三層,分別是樁/骨架層,遠程引用層,還有傳輸層。
要完成一個簡單的RMI應用要分為以下幾個簡單的步驟:
1。定義遠程接口
2。定義和實現RMI服務器類
3。定義和實現客戶端類
4。編譯以上的源碼
5。生成樁/骨架
6。創建安全策略
7。啟動RMI注冊表
8。啟動服務器
9。啟動客戶端
我們來做一個例子,在服務器上有一個連接數據庫,插入值的方法,我們在客戶端要使用這個方法,來真正的插入一個值!
第一步:先編寫一個接口AccountServer.java,這個接口要繼承Remote接口,并且提供一個遠程方法insertDetails(),這個方法要拋出RemoteException異常,代碼如下:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface AccountServer extends Remote
{
public String insertDetails(String firstName, String lastName,
String phone, String income, String accountType)
throws RemoteException;
}
第二步:實現遠程對象類,就是RMI服務器,AccountServerImpl.java,這個類要繼承UnicastRemoteObject類,并且要實現自己寫的遠程接口類AccountServer,首先要定義遠程對象構造器,然后就是要實現遠程接口中的方法,這個方法來連接mysql數據庫,并且插入值.然后我們main方法中,設置安全管理程序,然后創建遠程對象,接著注冊遠程對象.代碼如下:
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class AccountServerImpl extends UnicastRemoteObject implements
AccountServer
{
private Connection con;
public AccountServerImpl() throws RemoteException
{
super();
}
public String insertDetails(String firstName, String lastName,
String phone, String income, String accountType)
throws RemoteException
{
int rowsAffected = 0;
String sReturn = "fail";
try
{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager
.getConnection(
"jdbc:mysql://127.0.0.1/jsptest?useUnicode=true&characterEncoding=GBK",
"root", "");
PreparedStatement ps = con
.prepareStatement("insert into User_info values(?,?,?,?,?)");
ps.setString(1, "firstName");
ps.setString(2, "lastName");
ps.setString(3, "phone");
ps.setString(4, "income");
ps.setString(5, "accountType");
rowsAffected = ps.executeUpdate();
if (rowsAffected > 0)
{
sReturn = "success";
}
}
catch (Exception e)
{
e.printStackTrace();
}
return sReturn;
}
public static void main(String[] args)
{
//設置安全管理程序
System.setSecurityManager(new RMISecurityManager());
try
{
//創建遠程對象
AccountServerImpl as = new AccountServerImpl();
//注冊遠程對象
Naming.rebind("AccountServer", as);
System.out.println("RMI服務器啟動成功");
}
catch (RemoteException e)
{
e.printStackTrace();
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
}
第三步:編寫客戶端代碼,Client.java 這個代碼中有兩個重要的任務,就是得到遠程對象的應用,然后調用遠程對象,其余的都是界面部分,就不再講解,代碼如下:
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.Naming;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Client
{
public static void main(String[] args)
{
ClientFrame frame = new ClientFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}
class ClientFrame extends JFrame
{
public ClientFrame()
{
setTitle("客戶端");
setSize(200, 220);
Container con = getContentPane();
ClientPanel panel = new ClientPanel();
con.add(panel);
}
}
class ClientPanel extends JPanel
{
private JLabel lfirst, llast, lphone, lincome, ltype;
private JTextField ffirst, flast, fphone, fincome, ftype;
private JButton submit;
public ClientPanel()
{
lfirst = new JLabel(" 姓:");
llast = new JLabel(" 名:");
lphone = new JLabel("電話:");
lincome = new JLabel("來自:");
ltype = new JLabel("類型:");
ffirst = new JTextField(10);
flast = new JTextField(10);
fphone = new JTextField(10);
fincome = new JTextField(10);
ftype = new JTextField(10);
submit = new JButton(" 提 交 ");
submit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
//得到遠程對象
AccountServer as = (AccountServer) Naming
.lookup("rmi://localhost/AccountServer");
String firstName = ffirst.getText();
String lastName = flast.getText();
String phone = fphone.getText();
String income = fincome.getText();
String accountType = ftype.getText();
//調用遠程方法
String str = as.insertDetails(firstName, lastName, phone,
income, accountType);
if ("fail".equals(str))
{
JOptionPane.showMessageDialog(null, "插入失敗");
}
else
{
JOptionPane.showMessageDialog(null, "插入成功");
}
}
catch (Exception e2)
{
e2.printStackTrace();
}
}
});
add(lfirst);
add(ffirst);
add(llast);
add(flast);
add(lphone);
add(fphone);
add(lincome);
add(fincome);
add(ltype);
add(ftype);
add(submit);
}
}
第四步:在Dos下,進入代碼所在目錄,使用javac *.java 來編譯所有代碼
第五步:在class文件所在目錄使用 rmic AccountServerImpl來生成樁和骨架(AccountServerImpl_Skel.class和AccountServerImpl.Stub.class)
第六步:用policytool工具來創建安全策略文件,放開所有的權限,保存.java.policy文件在C:\Documents and Settings\Administrator文件夾下
第七步:使用start rmiregistry命令來啟動注冊表,默認使用1099端口,我們不需要改變
第八步:java -Djava.rmi.server.codebase=file:/e:/aa/ -classpath .;%CLASSPATH% AccountServerImpl來啟動服務器,注意由于服務器中要使用Mysql數據庫,所有我們引入使用數據庫的jar包,將mysql的jar包添加的CLASSPATH,就OK呢
第九步:使用java Client來啟動客戶端,和得到圖形界面的客戶端,填入數據,點擊提交,數據就會添加進入數據庫
附:
數據庫名稱:jsptest
表名:user_info
表結構:
CREATE TABLE user_info (
firstName varchar(50) NOT NULL default '',
lastName varchar(50) NOT NULL default '',
phone varchar(20) NOT NULL default '',
income varchar(30) NOT NULL default '',
accountType varchar(50) NOT NULL default '',
PRIMARY KEY (firstName)
)