我在上一篇文章中,简单地介绍了RMI的原理,这一篇文章我想在通过一个稍微复杂一点的例子,更好的向大家说明。读这篇文章需要你先参考我的上一篇文章: RMI(Remote Method Invocation)原理浅析。
例子中,用到了javaUI的swing和事件处理,以及线程知识,如果你对这方面的知识不是太清楚的话,希望你能参考一下资料,非常简单 !
例子的思想就是通过在远程启动服务,客户端提交任务,处理完以后,把结果反馈给客户端完成任务。程序的功能就是计算加减乘除, 有六个文件,分别为:
- AllCalculate.java,接口,定义了客户端和服务端共用的接口;
- AllCalculateImpl.java,服务端接口实现;
- AllCalculateServer.java,服务端服务提供者,它需要实例接口实现,导入到注册表中;
- MyRMIExam.java,客户端启动
- MyRMIGui.java,客户端UI,实现了加减乘除,分别在不同的线程里处理,是程序不会猛然间显得没有反应;
- ServiceListFrame.java,使用在客户端,用以检索服务端机器的远程服务名字。
-
tools包是我自己写的一个工具包,辅助我来验证客户的输入,有关这个包中的文本验证和窗体居中显示,请你参考我的三片文章: 文本控件内容录入限制(含源代码说明)(一), Java 文本控件内容录入限制(含源代码说明)(二), Java窗体居中显示。由于源代码比较长,在这里就是简单的罗列了: AllCalculate.java,AllCalculateServer.java和MyRMIExam.java代码清单,如果你需要参考完整的源代码,请你到CSDN资源下载中心下载,文件名称为:MyRMI.rar(搜索下载, 我得源代码中使用的UTF-8的编码格式,工程是Eclipse),如果你有任何问题的话,请给我留言。
下面是程序运行的几幅演示图片,你可以在你的电脑上演示:
所在环境的文件结构,方便你的实验
Eclipse中的结构
在Eclipse中启动设置,注意此时需要先启动rmiregistry服务环境
客户端启动配置
如果你没有安装Eclipse,需要手动命令行启动
命令行启动客户端,注意此时client.policy放在exam目录下
图片中,小三角加感叹号是由于我使用恶java的SecurityManager,你可以在源代码中注释掉这个功能。
以下是几个程序源码清单:
- package net.csdn.blog.qb2049_xg;
- import java.rmi.Remote;
- import java.rmi.RemoteException;
- /**
- *AllCalculate.java
- * @author Ulysses Ma
- * @date 2008-9-9
- *Remote 在这里标识远程对象
- */
- public interface AllCalculate extends Remote
- {
- //加
- public float add(float a,float b) throws RemoteException;
- //减
- public float minus(float a,float b) throws RemoteException;
- //除
- public float div(float a,float b) throws RemoteException;
- //乘
- public float mul(float a,float b) throws RemoteException;
- }
- package net.csdn.blog.qb2049_xg;
- import java.rmi.AccessException;
- import java.rmi.AlreadyBoundException;
- import java.rmi.RemoteException;
- import java.rmi.registry.LocateRegistry;
- import java.rmi.registry.Registry;
- /**
- * AllCalculateServer.java
- * @author Ulysses Ma
- * @date 2008-9-9
- */
- public class AllCalculateServer {
- public static void main(String[] args) {
- try{
- //实现要导出的远程对象,它来完成运算(创建远程对象实例)
- AllCalculateImpl allCalculate=new AllCalculateImpl();
- //获得本地的(RMI,要求是在rmiregistry启动情况下)注册表
- Registry rg=LocateRegistry.getRegistry();
- //实现对象的绑定,完成远程对象的注册工作
- rg.bind("allCalculate1", allCalculate);
- //状态提示
- System.out.println("实现所有方法的服务现在已成功启动!");
- }catch(NullPointerException ne){
- System.out.println("服务端出现了异常,可能是bind方法中name或是对象为空。/n"+ne.getMessage());
- }catch(AlreadyBoundException abe){
- System.out.println("服务端出现了异常,可能是bind名字已被占用。/n"+abe.getMessage());
- }catch(AccessException ae){
- System.out.println("服务端出现了异常,可能是访问被拒绝。/n"+ae.getMessage());
- }catch(RemoteException re){
- System.out.println("服务端出现了异常,可能是连接通信出现了问题。/n"+re.getMessage());
- }
- }
- }
- package net.csdn.blog.qb2049_xg;
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.Container;
- import java.awt.GridBagConstraints;
- import java.awt.GridBagLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.rmi.NotBoundException;
- import java.rmi.RemoteException;
- import java.rmi.registry.LocateRegistry;
- import java.rmi.registry.Registry;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JMenu;
- import javax.swing.JMenuBar;
- import javax.swing.JMenuItem;
- import javax.swing.JOptionPane;
- import javax.swing.JPanel;
- import javax.swing.JScrollPane;
- import javax.swing.JTextArea;
- import javax.swing.JTextField;
- import javax.swing.border.LineBorder;
- import net.csdn.blog.qb2049_xg.tools.JTextHelp;
- import net.csdn.blog.qb2049_xg.tools.MidScr;
- /**
- * MyRMIGui.java
- * @author Ulysses Ma
- *
- */
- public class MyRMIGui extends JFrame implements ActionListener
- {
- //序列化标识使用
- private static final long serialVersionUID = 2049L;
- //窗体布局面板的定义
- private JPanel title_p=new JPanel();
- private JPanel body_p=new JPanel();
- private JPanel bottom_p=new JPanel();
- private JTextField addA_t,addB_t,minusA_t,minusB_t,divA_t,divB_t,mulA_t,mulB_t;
- private JTextField addResult_t,addServer_t,minusResult_t,minusServer_t,divResult_t,
- divServer_t,mulResult_t,mulServer_t,serviceAdd_t,serviceMinus_t,serviceMul_t,serviceDiv_t;
- //分
- private ServiceListFrame listFrame;
- //一些关键性部件声明
- private JLabel title_l=new JLabel("<html><font color=red size=6>RMI 加、减、乘、除实验</font></html>");
- private JLabel exception_l=new JLabel("异常处理:");
- private JTextArea exception_ta=new JTextArea(10,70);
- //构造函数
- public MyRMIGui()
- {
- //标题部分显示的设置
- title_p.setAlignmentX(JPanel.CENTER_ALIGNMENT);
- title_p.add(title_l);
- //主体部分的设置
- GridBagLayout gbl1=new GridBagLayout();
- body_p.setLayout(gbl1);
- GridBagConstraints c1 = new GridBagConstraints();
- //表题说明
- JLabel numberA,numberB,result,equal,operate,server,start,service;
- numberA=new JLabel("数A");
- numberA.setHorizontalAlignment(JLabel.CENTER);
- numberB=new JLabel("数B");
- numberB.setHorizontalAlignment(JLabel.CENTER);
- result=new JLabel("结果");
- result.setHorizontalAlignment(JLabel.CENTER);
- equal=new JLabel("等号");
- equal.setHorizontalAlignment(JLabel.CENTER);
- operate=new JLabel("操作符");
- operate.setHorizontalAlignment(JLabel.CENTER);
- server=new JLabel("服务器");
- server.setHorizontalAlignment(JLabel.CENTER);
- service=new JLabel("服务名称");
- service.setHorizontalAlignment(JLabel.CENTER);
- start=new JLabel("开始");
- start.setHorizontalAlignment(JLabel.CENTER);
- c1.fill=GridBagConstraints.VERTICAL;
- c1.gridx=0;
- c1.gridy=0;
- body_p.add(numberA,c1);
- c1.gridx=1;
- body_p.add(operate,c1);
- c1.gridx=2;
- body_p.add(numberB,c1);
- c1.gridx=3;
- body_p.add(equal,c1);
- c1.gridx=4;
- body_p.add(result,c1);
- c1.gridx=5;
- body_p.add(server,c1);
- c1.gridx=6;
- body_p.add(service,c1);
- c1.gridx=7;
- body_p.add(start,c1);
- //加运算UI
- addA_t=new JTextField(10);
- addB_t=new JTextField(10);
- new JTextHelp(addA_t,JTextHelp.NUMBER).insertCheck();
- new JTextHelp(addB_t,JTextHelp.NUMBER).insertCheck();
- addResult_t=new JTextField(10);
- serviceAdd_t=new JTextField(10);
- addServer_t=new JTextField(15);
- JButton addStart_b=new JButton("开始计算");
- addStart_b.addActionListener(this);
- addStart_b.setActionCommand("add");
- JLabel add_l=new JLabel("+");
- add_l.setHorizontalAlignment(JLabel.CENTER);
- JLabel addEqual_l=new JLabel("=");
- addEqual_l.setHorizontalAlignment(JLabel.CENTER);
- c1.gridx=0;
- c1.gridy=1;
- body_p.add(addA_t,c1);
- c1.gridx=1;
- body_p.add(add_l,c1);
- c1.gridx=2;
- body_p.add(addB_t,c1);
- c1.gridx=3;
- body_p.add(addEqual_l,c1);
- c1.gridx=4;
- body_p.add(addResult_t,c1);
- c1.gridx=5;
- body_p.add(addServer_t,c1);
- c1.gridx=6;
- body_p.add(serviceAdd_t,c1);
- c1.gridx=7;
- body_p.add(addStart_b,c1);
- //减运算UI
- minusA_t=new JTextField(10);
- minusB_t=new JTextField(10);
- new JTextHelp(minusA_t,JTextHelp.NUMBER).insertCheck();
- new JTextHelp(minusB_t,JTextHelp.NUMBER).insertCheck();
- minusResult_t=new JTextField(10);
- minusServer_t=new JTextField(15);
- serviceMinus_t=new JTextField(10);
- JButton minusStart_b=new JButton("开始计算");
- minusStart_b.addActionListener(this);
- minusStart_b.setActionCommand("minus");
- JLabel minus_l=new JLabel("-");
- minus_l.setHorizontalAlignment(JLabel.CENTER);
- JLabel minusEqual_l=new JLabel("=");
- minusEqual_l.setHorizontalAlignment(JLabel.CENTER);
- c1.gridx=0;
- c1.gridy=2;
- body_p.add(minusA_t,c1);
- c1.gridx=1;
- body_p.add(minus_l,c1);
- c1.gridx=2;
- body_p.add(minusB_t,c1);
- c1.gridx=3;
- body_p.add(minusEqual_l,c1);
- c1.gridx=4;
- body_p.add(minusResult_t,c1);
- c1.gridx=5;
- body_p.add(minusServer_t,c1);
- c1.gridx=6;
- body_p.add(serviceMinus_t,c1);
- c1.gridx=7;
- body_p.add(minusStart_b,c1);
- //除运算UI
- divA_t=new JTextField(10);
- divB_t=new JTextField(10);
- new JTextHelp(divA_t,JTextHelp.NUMBER).insertCheck();
- new JTextHelp(divB_t,JTextHelp.NUMBER).insertCheck();
- divResult_t=new JTextField(10);
- divServer_t=new JTextField(15);
- serviceDiv_t=new JTextField(10);
- JButton divStart_b=new JButton("开始计算");
- divStart_b.setActionCommand("div");
- divStart_b.addActionListener(this);
- JLabel div_l=new JLabel("÷");
- div_l.setHorizontalAlignment(JLabel.CENTER);
- JLabel divEqual_l=new JLabel("=");
- divEqual_l.setHorizontalAlignment(JLabel.CENTER);
- c1.gridx=0;
- c1.gridy=3;
- body_p.add(divA_t,c1);
- c1.gridx=1;
- body_p.add(div_l,c1);
- c1.gridx=2;
- body_p.add(divB_t,c1);
- c1.gridx=3;
- body_p.add(divEqual_l,c1);
- c1.gridx=4;
- body_p.add(divResult_t,c1);
- c1.gridx=5;
- body_p.add(divServer_t,c1);
- c1.gridx=6;
- body_p.add(serviceDiv_t,c1);
- c1.gridx=7;
- body_p.add(divStart_b,c1);
- //乘运算UI
- mulA_t=new JTextField(10);
- mulB_t=new JTextField(10);
- new JTextHelp(mulA_t,JTextHelp.NUMBER).insertCheck();
- new JTextHelp(mulB_t,JTextHelp.NUMBER).insertCheck();
- mulResult_t=new JTextField(10);
- mulServer_t=new JTextField(15);
- serviceMul_t=new JTextField(10);
- JButton mulStart_b=new JButton("开始计算");
- mulStart_b.addActionListener(this);
- mulStart_b.setActionCommand("mul");
- JLabel mul_l=new JLabel("×");
- mul_l.setHorizontalAlignment(JLabel.CENTER);
- JLabel mulEqual_l=new JLabel("=");
- mulEqual_l.setHorizontalAlignment(JLabel.CENTER);
- c1.gridx=0;
- c1.gridy=4;
- body_p.add(mulA_t,c1);
- c1.gridx=1;
- body_p.add(mul_l,c1);
- c1.gridx=2;
- body_p.add(mulB_t,c1);
- c1.gridx=3;
- body_p.add(mulEqual_l,c1);
- c1.gridx=4;
- body_p.add(mulResult_t,c1);
- c1.gridx=5;
- body_p.add(mulServer_t,c1);
- c1.gridx=6;
- body_p.add(serviceMul_t,c1);
- c1.gridx=7;
- body_p.add(mulStart_b,c1);
- //状态初始化
- addResult_t.setEditable(false);
- minusResult_t.setEditable(false);
- mulResult_t.setEditable(false);
- divResult_t.setEditable(false);
- //异常问题的处理
- GridBagLayout gbl=new GridBagLayout();
- bottom_p.setLayout(gbl);
- GridBagConstraints c = new GridBagConstraints();
- c.fill=GridBagConstraints.NONE;
- c.gridx=0;
- c.gridy=0;
- bottom_p.add(exception_l,c);
- c.gridx=5;
- JButton clear_b=new JButton("清空");
- clear_b.addActionListener(this);
- clear_b.setActionCommand("clear");
- bottom_p.add(clear_b,c);
- exception_ta.setBorder(new LineBorder(new Color(0,0,0)));
- exception_ta.setLineWrap(true);
- JScrollPane scrollPane=new JScrollPane(exception_ta);
- c.fill=GridBagConstraints.HORIZONTAL;
- c.gridx=0;
- c.gridy=1;
- c.gridwidth=6;
- bottom_p.add(scrollPane,c);
- //设置菜单栏
- JMenuBar jmb=new JMenuBar();
- JMenu help_m=new JMenu("帮助");
- JMenuItem listService=new JMenuItem("浏览已注册的服务");
- listService.addActionListener(this);
- listService.setActionCommand("list");
- JMenuItem exit=new JMenuItem("退出");
- exit.addActionListener(this);
- exit.setActionCommand("exit");
- help_m.add(listService);
- help_m.add(exit);
- jmb.add(help_m);
- //加载面板
- this.setJMenuBar(jmb);
- Container rp=this.getContentPane();
- rp.add(title_p,BorderLayout.NORTH);
- rp.add(body_p,BorderLayout.CENTER);
- rp.add(bottom_p,BorderLayout.SOUTH);
- //设置窗体展示宽度
- this.setSize(800,450);
- //设置显示位置
- MidScr ms=new MidScr(this);
- this.setLocation(ms.getX(),ms.getY());
- //设置标题
- this.setTitle("测试Java RMI的使用问题");
- //关闭点击后的处理
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- this.setVisible(true);
- this.validate();
- }
- //事件的处理
- public void actionPerformed(ActionEvent e)
- {
- //add,minus,div,mul commands
- exception_ta.setForeground(new Color(255,0,0));
- //加事件的处理
- if(e.getActionCommand().equals("add"))
- {
- String arg1=addA_t.getText().trim();
- String arg2=addB_t.getText().trim();
- String host=addServer_t.getText().trim();
- String service=serviceAdd_t.getText().trim();
- if(arg1.equals("")&&arg2.equals(""))
- {
- JOptionPane.showMessageDialog(this,"参与计算的两个数字不能为空,请检查你的输入,谢谢!",
- "远程调用",JOptionPane.INFORMATION_MESSAGE);
- return ;
- }
- new Thread(new LoadRMI(host,arg1,arg2,service,e.getActionCommand())).start();
- }
- //减事件的处理
- if(e.getActionCommand().equals("minus"))
- {
- String arg1=minusA_t.getText().trim();
- String arg2=minusB_t.getText().trim();
- String host=minusServer_t.getText().trim();
- String service=serviceMinus_t.getText().trim();
- if(arg1.equals("")&&arg2.equals(""))
- {
- JOptionPane.showMessageDialog(this,"参与计算的两个数字不能为空,请检查你的输入,谢谢!",
- "远程调用",JOptionPane.INFORMATION_MESSAGE);
- return ;
- }
- new Thread(new LoadRMI(host,arg1,arg2,service,e.getActionCommand())).start();
- }
- //乘事件的处理
- if(e.getActionCommand().equals("mul"))
- {
- String arg1=mulA_t.getText().trim();
- String arg2=mulB_t.getText().trim();
- String host=mulServer_t.getText().trim();
- String service=serviceMul_t.getText().trim();
- if(arg1.equals("")&&arg2.equals(""))
- {
- JOptionPane.showMessageDialog(this,"参与计算的两个数字不能为空,请检查你的输入,谢谢!",
- "远程调用",JOptionPane.INFORMATION_MESSAGE);
- return ;
- }
- new Thread(new LoadRMI(host,arg1,arg2,service,e.getActionCommand())).start();
- }
- //除事件的处理
- if(e.getActionCommand().equals("div"))
- {
- String arg1=divA_t.getText().trim();
- String arg2=divB_t.getText().trim();
- String host=divServer_t.getText().trim();
- String service=serviceDiv_t.getText().trim();
- if(arg1.equals("")&&arg2.equals(""))
- {
- JOptionPane.showMessageDialog(this,"参与计算的两个数字不能为空,请检查你的输入,谢谢!",
- "远程调用",JOptionPane.INFORMATION_MESSAGE);
- return ;
- }
- new Thread(new LoadRMI(host,arg1,arg2,service,e.getActionCommand())).start();
- }
- //清理文本框按钮事件
- if(e.getActionCommand().equals("clear")){
- exception_ta.setText("");
- }
- //退出菜单事件处理
- if(e.getActionCommand().equals("exit")){
- System.exit(HIDE_ON_CLOSE);
- }
- //查看注册服务菜单事件
- if(e.getActionCommand().equals("list")){
- if(listFrame==null)
- listFrame=new ServiceListFrame();
- else
- listFrame.setVisible(true);
- }
- }
- //完成各种方法调用,在这里使用了多线程的方法,可以多个任务同时的进行,不会有等待的感觉
- class LoadRMI implements Runnable
- {
- String host,arg1,arg2,service;
- String actionCommand;
- public LoadRMI(String host,String arg1,String arg2,String service,String actionCommand){
- this.arg1=arg1;
- this.arg2=arg2;
- this.host=host;
- this.service=service;
- this.actionCommand=actionCommand;
- }
- public void run(){
- try{
- //如果host的值是null的话,那么系统就默认调用本地远程方法
- Registry rg=LocateRegistry.getRegistry(host);
- AllCalculate ac=(AllCalculate)rg.lookup(service);
- float a=Float.valueOf(arg1).floatValue();
- float b=Float.valueOf(arg2).floatValue();
- //根据事件名称调用方法
- if(this.actionCommand.equals("add")){
- addResult_t.setText(String.valueOf(ac.add(a, b)));
- }
- if(this.actionCommand.equals("minus")){
- minusResult_t.setText(String.valueOf(ac.minus(a, b)));
- }
- if(this.actionCommand.equals("mul")){
- mulResult_t.setText(String.valueOf(ac.mul(a, b)));
- }
- if(this.actionCommand.equals("div")){
- divResult_t.setText(String.valueOf(ac.div(a, b)));
- }
- }catch(NullPointerException npe){
- exception_ta.append("调用的服务名称为空"+npe.getMessage()+"/n");
- }catch(NotBoundException nbe){
- exception_ta.append("调用的服务不存在,请检查你的输入"+nbe.getMessage()+"/n");
- }
- catch(RemoteException re){
- exception_ta.append("调用远程方法时出现了问题,情况可能是:"+re.getMessage()+"/n");
- }
- }
- }
- }
如果你对这个小例子感兴趣的话,请你到CSDN资源中心下载!
<script type="text/JavaScript"> alimama_pid="mm_11642003_1480608_3725409"; alimama_titlecolor="0000FF"; alimama_descolor ="000000"; alimama_bgcolor="FFFFFF"; alimama_bordercolor="E6E6E6"; alimama_linkcolor="008000"; alimama_bottomcolor="FFFFFF"; alimama_anglesize="0"; alimama_bgpic="0"; alimama_icon="0"; alimama_sizecode="11"; alimama_width=760; alimama_height=90; alimama_type=2; </script> <script src="http://a.alimama.cn/inf.js" type="text/javascript"> </script>