JAVA RMI 对计算器编程实现.docx
《JAVA RMI 对计算器编程实现.docx》由会员分享,可在线阅读,更多相关《JAVA RMI 对计算器编程实现.docx(22页珍藏版)》请在冰点文库上搜索。
![JAVA RMI 对计算器编程实现.docx](https://file1.bingdoc.com/fileroot1/2023-5/12/3c3200b1-d000-4413-8a23-8215aefd8c28/3c3200b1-d000-4413-8a23-8215aefd8c281.gif)
JAVARMI对计算器编程实现
JAVARMI对计算器编程实现
摘要:
本文围绕Java编程语言在网络编程方面的具体应用,论述了面向对象方法,对计算器程序进行需求分析、概要设计、详细设计,最后使用javarmi编程实现了全过程。
Java作为一种风靡一时的网络开发语言,其巨大的威力就体现在它强大的开发分布式网络应用的能力上,而RMI就是开发百分之百纯Java的网络分布式应用系统的核心解决方案之一。
其实它可以被看作是RPC的Java版本。
但是传统RPC并不能很好地应用于分布式对象系统。
而JavaRMI则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。
RMI目前使用Java远程消息交换协议JRMP(JavaRemoteMessaging PRotocol)进行通信。
JRMP是专为Java的远程对象制定的协议。
因此,JavaRMI具有Java的"WriteOnce,RunAnywhere"的优点,是分布式应用系统的百分之百纯Java解决方案。
用JavaRMI开发的应用系统可以部署在任何支持JRE(JavaRunEnvironmentJava,运行环境)的平台上。
本文拟从程序的角度举例介绍怎样利用RMI实现Java分布式应用。
关键词:
JAVARMI分布式应用
Abstract:
ThispaperfocusesonthespecificapplicationintheJavaprogramminglanguagenetworkprogramming,discussestheobject-orientedmethod,thecalculatorprogramneedsanalysis,outlinedesign,detaileddesign,andfinallytheuseofjavarmiprogrammingtheentireprocess.AsarageJavawebdevelopmentlanguage,anditsenormouspowerisreflectedintheabilityofitspowerfuldevelopmentofdistributednetworkapplications,whilethecore100%pureJavaRMIistodevelopanetworkofdistributedapplicationsystemoneofthesolutions.Infact,itcanbeseenasRPCJavaversion.ButtraditionalRPCisnotwellappliedtodistributedobjectsystems.TheJavaRMIsupportscommunicationbetweenthestoredproceduresindifferentaddressspaceseachobjectclass,seamlessremotecallremoteobjects.CurrentlytheuseofJavaRMIremotemessageexchangeprotocolJRMP(JavaRemoteMessagingPRotocol)communication.JRMPisaprotocoldesignedforJavaremoteobjectmaking.Thus,theadvantagesof"WriteOnce,RunAnywhere"TheJavaRMIwithJava,andis100%pureJavadistributedapplicationsystemsolutions.ApplicationsdevelopedusingJavaRMIsystemscanbedeployedonanyplatformsupportedJRE(JavaRunEnvironmentJava,RuntimeEnvironment).Thispaper,forexamplefromtheperspectiveofhowtointroducetheuseoftheprogram'simplementationofJavaRMIdistributedapplications.
Keywords:
JAVARMIDistributedApplication
1引言
随着科学技术的发展,计算机领域也在飞速的发展,人们对于计算器的要求越来越高。
而java语言是今年来比较流行的语言。
经过10多年的发展,java已经渗透到全球的每个角落。
而在这个网络时代,java语言在网络编程方面的有事使得网络编程有了更好的选择。
Java语言最令人瞩目的特点就是其具有跨平台性,使其不受平台影响,并得到了广泛的应用。
1.1RMI系统运行机理
RMI应用程序通常包括两个独立的程序:
服务器程序和客户机程序。
典型的服务器应用程序将创建多个远程对象,使这些远程对象能够被引用,然后等待客户机调用这些远程对象的方法。
而典型的客户机程序则从服务器中得到一个或多个远程对象的引用,然后调用远程对象的方法。
RMI为服务器和客户机进行通信和信息传递提供了一种机制。
在与远程对象的通信过程中,RMI使用标准机制:
stub和skeleton。
远程对象的stub担当远程对象的客户本地代表或代理人角色。
调用程序将调用本地stub的方法,而本地stub将负责执行对远程对象的方法调用。
在RMI中,远程对象的stub与该远程对象所实现的远程接口集相同。
调用stub的方法时将执行下列操作:
(1)初始化与包含远程对象的远程虚拟机的连接;
(2)对远程虚拟机的参数进行编组(写入并传输);(3)等待方法调用结果;(4)解编(读取)返回值或返回的异常;(5)将值返回给调用程序。
为了向调用程序展示比较简单的调用机制,stub将参数的序列化和网络级通信等细节隐藏了起来。
在远程虚拟机中,每个远程对象都可以有相应的skeleton(在JDK1.2环境中无需使用skeleton)。
Skeleton负责将调用分配给实际的远程对象实现。
它在接收方法调用时执行下列操作:
(1)解编(读取)远程方法的参数;
(2)调用实际远程对象实现上的方法;(3)将结果(返回值或异常)编组(写入并传输)给调用程序。
stub和skeleton由rmic编译器生成。
利用RMI编写分布式对象应用程序需要完成以下工作[2]:
(1)定位远程对象。
应用程序可使用两种机制中的一种得到对远程对象的引用。
它既可用RMI的简单命名工具rmiregistry来注册它的远程对象,也可以将远程对象引用作为常规操作的一部分来进行传递和返回。
(2)与远程对象通信。
远程对象间通信的细节由RMI处理,对于程序员来说,远程通信看起来就像标准的Java方法调用。
(3)给作为参数或返回值传递的对象加载类字节码。
因为RMI答应调用程序将纯Java对象传给远程对象,所以,RMI将提供必要的机制,既可以加载对象的代码又可以传输对象的数据。
在RMI分布式应用程序运行时,服务器调用注册服务程序以使名字与远程对象相关联。
客户机在服务器上的注册服务程序中用远程对象的名字查找该远程对象,然后调用它的方法。
1.2对象序列化
在RMI分布式应用系统中,服务器与客户机之间传递的Java对象必须是可序列化的对象。
不可序列化的对象不能在对象流中进行传递。
对象序列化扩展了核心Java输入/输出类,同时也支持对象。
对象序列化支持把对象编码以及将通过它们可访问到的对象编码变成字节流;同时,它也支持流中对象图形的互补重构造。
序列化用于轻型持久性和借助于套接字或远程方法调用(RMI)进行的通信。
序列化中现在包括一个API(application ProgrammingInterface,应用程序接口),答应独立于类的域指定对象的序列化数据,并答应使用现有协议将序列化数据域写入流中或从流中读取,以确保与缺省读写机制的兼容性。
为编写应用程序,除多数瞬态应用程序外,都必须具备存储和检索Java对象的能力。
以序列化方式存储和检索对象的要害在于提供重新构造该对象所需的足够对象状态。
存储到流的对象可能会支持Serializable(可序列化)或Externalizable(可外部化)接口。
对于Java对象,序列化形式必须能标识和校验存储其内容的对象所属的Java类,并且将该内容还原为新的实例。
对于可序列化对象,流将提供足够的信息将流的域还原为类的兼容版本。
对于可外部化对象,类将全权负责其内容的外部格式。
序列化Java对象的目的是:
提供一种简单但可扩充的机制,以序列化方式维护Java对象的类型及安全属性;具有支持编组和解编的扩展能力以满足远程对象的需要;具有可扩展性以支持Java对象的简单持久性;只有在自定义时,才需对每个类提供序列化自实现;答应对象定义其外部格式。
2分布式应用的实现和运行步骤
2.1编写JavaRMI分布式应用程序的步骤主要包括以下几步:
将远程类的功能定义为Java接口。
在Java中,远程对象是实现远程接口的类的实例[1]。
在远程接口中声明每个要远程调用的方法。
远程接口具有如下特点:
1)远程接口必须声明为public。
假如不这样,则除非客户端与远程接口在同一个包内,否则当试图装入实现该远程接口的远程对象时会得到错误结果。
2)远程对象扩展java.rmi.Remote接口。
3)除了所有应用程序特定的例外之外,每个方法还必须抛出java.rmi.RemoteException例外。
4)任何作为参数或返回值传送的远程对象的数据类型必须声明为远程接口类型,而不是实现类。
2.2系统功能图
图2.2计算器系统功能图
3程序设计说明
下面是一个使用RMI实现的计算器,主要分为两个部分,服务器主要实现接受客服端的连接并进行加、减、乘、除,最后将结果返回给客户端,客户端主要实现对计算器的GUI编程,添加事件监听,对用户进行的操作进行判断,并调用客服端的方法进行计算。
下面对结果和程序进行分析:
定义一个接口并从实现Remate接口
定义一个CalculatorImp类实现Calculator这个接口,并重写接口的方法
服务端进行注册
客户端进行远程方法调用
运行结果如下:
启动服务端
启动客户端:
参考文献:
[1]编程思想ThinkinginJava4thBruceEckel著北京;机械工业出版社,2007
[2]分布式操作系统AndrewS.Tanenbaum著北京;电子工业出版社,2008
附源代码:
packagecom.cqupt.RMI;
importjava.rmi.Remote;
publicinterfaceCalculatorextendsRemote{//J2SE的API中Remote确实是个接口,
//只有实现了remote接口的方法才可以被远程调用
Publicdoubleadd(doublea,doubleb)throwsjava.rmi.RemoteException;
publicdoublesub(doublea,doubleb)throwsjava.rmi.RemoteException;
publicdoublemul(doublea,doubleb)throwsjava.rmi.RemoteException;
publicdoublediv(doublea,doubleb)throwsjava.rmi.RemoteException;
}
packagecom.cqupt.RMI;
importjava.rmi.RemoteException;
importjava.rmi.server.UnicastRemoteObject;
publicclassCalculatorImpextendsUnicastRemoteObjectimplementsCalculator{
CalculatorImp()throwsRemoteException{
super();
}
publicdoubleadd(doublea,doubleb)throwsjava.rmi.RemoteException{
//TODOAuto-generatedmethodstub
System.out.println("RMI调用服务端所得结果:
"+a+"+"+b+"="+(a+b));
returna+b;
}
publicdoublediv(doublea,doubleb)throwsjava.rmi.RemoteException{
//TODOAuto-generatedmethodstub
System.out.println("RMI调用服务端所得结果:
"+a+"/"+b+"="+(a/b));
returna/b;
}
publicdoublemul(doublea,doubleb)throwsjava.rmi.RemoteException{
//TODOAuto-generatedmethodstub
System.out.println("RMI调用服务端所得结果:
"+a+"*"+b+"="+(a*b));
returna*b;
}
publicdoublesub(doublea,doubleb)throwsjava.rmi.RemoteException{
//TODOAuto-generatedmethodstub
System.out.println("RMI调用服务端所得结果:
"+a+"-"+b+"="+(a-b));
returna-b;
}
}
packagecom.cqupt.RMI;
import.MalformedURLException;
importjava.rmi.Naming;
importjava.rmi.RemoteException;
importjava.rmi.registry.LocateRegistry;
publicclassCaculatorServer{
CaculatorServer(){
try{
Calculatorc=newCalculatorImp();
LocateRegistry.createRegistry(3000);//使用一个新的端口,默认端口是1109
Naming.rebind("rmi:
//localhost:
3000/CaculatorServer",c);//将server注册
System.out.println("服务器注册成功");
}catch(RemoteExceptione){
e.printStackTrace();
}catch(MalformedURLExceptione1){
e1.printStackTrace();
}
}
publicstaticvoidmain(String[]args){
newCaculatorServer();
}
}
packagecom.cqupt.RMI;
import.MalformedURLException;
importjava.rmi.Naming;
importjava.rmi.NotBoundException;
importjava.rmi.RemoteException;
importjava.awt.*;
importjavax.swing.*;
importjava.awt.event.*;
importjava.io.*;
publicclassCalculatorClientextendsJFrame{
privateStringfront="",behind="";//分别用于记录加减乘除运算符之前,之后输入的内容
privateStringop;//用于记录运算符
privateStringre;//用于存储运算结果的字符串格式
privatebooleanflag=false;//用于记录是否按下了运算符
privatebooleanflag1=false;//用于判断是否输入了点运算符
privatedoubleresult;//用于存储运算结果
privatebooleanflag2=false;//用于判断是否输入了数字
privatebooleanflag3=false;//用于判断是否按下了等号运算符
JPanelcontentPane;
JTextFieldtxtResult=newJTextField("0");
JButtonbtnNull=newJButton("sqrt");
JButtonbtnFour=newJButton("4");
JButtonbtnFive=newJButton("5");
JButtonbtnSix=newJButton("6");
JButtonbtnDecrease=newJButton("-");
JButtonbtnBegin=newJButton("C");
JButtonbtnOne=newJButton("1");
JButtonbtnTwo=newJButton("2");
JButtonbtnThree=newJButton("3");
JButtonbtnMultiply=newJButton("*");
JButtonbtnCancel=newJButton("←");
JButtonbtnZero=newJButton("0");
JButtonbtnMinus=newJButton("+/-");
JButtonbtnPoint=newJButton(".");
JButtonbtnDivide=newJButton("/");
JButtonbtnEqual=newJButton("=");
JButtonbtnIncrease=newJButton("+");
JButtonbtnSeven=newJButton("7");
JButtonbtnEight=newJButton("8");
JButtonbtnNine=newJButton("9");
publicCalculatorClient(){
try{
setDefaultCloseOperation(EXIT_ON_CLOSE);
jbInit();
}catch(Exceptionexception){
exception.printStackTrace();
}
}
privatevoidjbInit()throwsException{
contentPane=(JPanel)getContentPane();
contentPane.setLayout(null);
this.setResizable(false);
setSize(newDimension(400,300));
setTitle("计算器");
txtResult.setEnabled(false);
txtResult.setFont(newjava.awt.Font("Dialog",Font.PLAIN,20));
txtResult.setEditable(false);
txtResult.setHorizontalAlignment(SwingConstants.RIGHT);
txtResult.setBounds(newRectangle(33,19,310,34));
btnNull.setBounds(newRectangle(298,70,46,37));
btnNull.setFont(newjava.awt.Font("Dialog",Font.PLAIN,12));
//btnNull.addActionListener(newFrameCalculate_btnNull_actionAdapter(this));
btnFour.setBounds(newRectangle(33,120,46,37));
btnFour.setFont(newjava.awt.Font("Dialog",Font.PLAIN,20));
btnFive.setBounds(newRectangle(101,120,46,37));
btnFive.setFont(newjava.awt.Font("Dialog",Font.PLAIN,20));
btnSix.setBounds(newRectangle(167,119,46,37));
btnSix.setFont(newjava.awt.Font("Dialog",Font.PLAIN,20));
btnDecrease.setBounds(newRectangle(234,120,46,37));
btnDecrease.setFont(newjava.awt.Font("Dialog",Font.PLAIN,20));
btnBegin.setBounds(newRectangle(298,121,46,37));
btnBegin.setFont(newjava.awt.Font("Dialog",Font.PLAIN,15));
btnBegin.addActionListener(newCalculate_btnBegin_actionAdapter(this));
btnOne.setBounds(newRectangle(33,172,46,37));
btnOne.setFont(newjava.awt.Font("Dialog",Font.PLAIN,