当前位置:网站首页 > Java基础 > 正文

java语言基础教程 张化祥



题目:

实验二:Java RMI试验

【实验目的及要求】

在Java语言环境下,通过RMI实现一个学生成绩或教师信息查询的程序。

要求:要求独立完成。

【实验原理和步骤】

1. 定义学生成绩查询或教师信息查询的远程接口

2. 实现服务器端软件(程序):设计远程接口的实现类和服务器对象类,在服务器上启动目录服务,并注册远程对象,供客户端访问。远程接口的实现类要从本地读取数据信息(成绩或教师信息),数据信息可以存储在文件或数据库中。

3. 实现客户端软件(程序):实现访问远程对象的客户程序。

话说前几天考完分布式就蛋疼了,还是回来乖乖把lab都给撸掉...挂了可就不好玩儿了。lab2比较直白,感觉老师就是让我们去敲敲rmi的代码,走走流程熟悉一下。废话不多说,开始记录记录。

这里我实际上要做的只有三件事:

1. 搞定数据库的链接,随便建个表,存点记录进去。

2. 把远程接口、接口实现类、stub、sever和client神马的都写了,编了。

3. 程序跑起,虫子给捉起,动漫给看起,微博刷起....起...起起...

数据库

首先数据库这块要弄好,我比较喜欢从底层往上打代码。本来想复用上学期数据库大作业的代码,可惜当时没有写blog记录的习惯。在图书馆里逛了逛,惊奇地发现了当时做数据库大作业时候参考的那本书,顿时感觉尼玛遇上了初恋啊(初恋总是美好的有木有= =)。数据库方面的代码我就参考上面的demo了,另外还参考了同样封面的另一本书,这里记录一下。

都是清华大学出版社的,尼玛,一个出版社有必要出两本内容几乎一样的书嘛- -.....

要搞成数据库,先要装一个JDBC(Java Data Base Connectivity)驱动。驱动其实就是封装好的一堆代码。因为市面上数据库很多,MySQL和sqlserver什么的,你不可能对所有数据库的语言都了解。Java就定义了一些标准的API,然后让数据库的公司自己根据所定义的API来实现。比如定义一个executeQuery();这个函数有什么功能,参数是什么,返回值是什么,Java给你定义好,实现的过程你丫的爱怎么实现就怎么实现,Java不管。所以我们用Java只要按API来调用,数据库就乖乖地运行了...数据库公司实现的,其实就是JDBC驱动。

我是用的mySQL,自然下了个mySQL的驱动,在相应的工程里添加一下即可。步骤如下:

右击工程,Build Path->Configure Build Path->选Libraries->Add External JARs(这里找到你放驱动的路径,直接add就可以了)

驱动百度一下(或者360一下)很容易找到。

下面的都搞好了,就开始弄上面。首先我们需要知道怎么用代码连数据库,索性初恋Java书告诉了我:

数据库连接类:

 1 import java.sql.*;  2  3  4 public class DbConn {  5 private Connection conn;  6 protected DbConn(String dbDriver, String dbUrl, String username, String password){  7 conn = null;  8  9 10 try { 11 //载入参数指定的驱动,如未找到驱动程序,将抛出ClassNotFound/Exception异常 12  Class.forName(dbDriver); java语言基础教程 张化祥13 14 //建立数据库连接,可能会抛出SQLException异常 15 conn = DriverManager.getConnection(dbUrl, username, password); 16 17 } catch (ClassNotFoundException cnfe) { 18  System.err.println(cnfe.getMessage()); 19 } catch (SQLException se) { 20  System.err.println(se.getMessage()); 21  } 22  } 23 24 public static Connection getConnection(String dbDriver, String dbUrl, String username, String password){ 25 Connection conRet= null; 26 DbConn bc = new DbConn(dbDriver, dbUrl, username, password); 27 28 conRet = bc.conn; 29 30 return conRet; 31  } 32 }

测试用类:

 1 public class testforfun {  2 public static void main(String[] args){  3 Connection conn = DbConn.getConnection("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/distributeds", "root", "password");  4  5 if(conn == null){  6 System.out.println("未能成功连接数据库!");  7  }  8 else{  9 System.out.println("成功连接数据库!"); 10 11 try { 12 Statement st = conn.createStatement(); 13 14 String sql = "select * from student"; 15 16 ResultSet rs = st.executeQuery(sql); 17 18  String id, name, cname; 19 int score; 20 21 while(rs.next()){ 22 id = rs.getString("id"); 23 name = rs.getString("name"); 24 cname = rs.getString("cname"); 25 score = rs.getInt("score"); 26 27 System.out.println(id + " " + name + " " + score + " " + cname); 28  } 29 30  rs.close(); 31  st.close(); 32  conn.close(); 33 } catch (SQLException se) { 34  System.err.println(se.getMessage()); 35  } 36 37  } 38  } 39 40 }

这里需要解释一下的有:

1. distributeds是我建的数据库。

2. student是我建的渣表,很多重复数据,不过因为不是数据库实验,所以将就着吧。

create table student( id varchar(12), name varchar(20), score integer, cname varchar(40), primary key(id) ); 

有一个东东很重要,就是

写在文本里,比较好,一次可以insert多条,也方便交实验代码。

数据库有关的都搞完了。

远程接口、接口实现类、stub、sever和client

远程接口:很简单。一开始返回值用的Resultset,后来发现不行,改成了String[]

接口实现类:关键所在,切记每次修改都要把stub重新生成一次。这里for循环给String[]赋值的时候犯了个二逼错误。程序跑起后老是说有空指针,我看来看去,没发现有数组越界啊。莫非最后的那个用来判定结束的"."出了问题?后来发现自己二逼把for的性质给搞错了,for是每次循环结束时累加,不是开始时。我当时多加了一个周期,难免出错。另外,由于client需要知道查到了多少条记录,是没有还是很多条,我考虑是不是需要封装一个新类,给String[]加一个int标记数量。后来觉得自己傻了,用一个标记结束符(如".")就可以解决了。零个多个都没问题。

stub:这个东西就很坑爹了。考试的时候卷子把它翻译成了什么?= =桩!高贵的stub夫人真是一口老血都得吐出来了,中国的翻译真是伤不起,还是去求教字幕组吧。(那才是真正的中外文化交流大使啊)我们都知道,stub是接口实现类和rmic在cmd这酒店里搞出的私生女。该怎么生呢?rmic SomeImpl.class? rmic SomeImpl.java? 姿势都不对啊= =正确的姿势是rmic SomeImpl。 前提是cmd在实现类的目录下。这里本来还要加包名,就是 rmic packagename.SomeImpl。但是我创的时候没打包名,所以就不用输了。

我在进目录的时候果断囧了。cd d: ,不行;cd d: ,不行;cd d: ,不行。尼玛各种姿势都试过了还不行是闹哪样啊= =。百度了一下原来是d: = = cd是针对当前目录的。比如你在d: ,你想跳到 d:/mylab目录,你就输入cd mylab。想切换目录直接打路径就好。

server和client:这两个都打的比较快,书里的样例代码几乎不用改。

实验代码:

Client

 1 import java.io.BufferedReader;  2 import java.io.IOException;  3 import java.io.InputStreamReader;  4 import java.rmi.Naming;  5 import java.rmi.NotBoundException;  6 import java.sql.ResultSet;  7 import java.sql.SQLException;  8  9 10 public class ScoreClient { 11 public static void main(String[] args) throws IOException { 12 int RMIPort; 13 14 //定义流对象 15 InputStreamReader isr = new InputStreamReader(System.in); 16 BufferedReader br = new BufferedReader(isr); 17 18 //定义端口 19 System.out.println("Enter the port number:"); 20 String portNum = br.readLine(); 21 RMIPort = Integer.parseInt(portNum); 22 23 String registryURL = "rmi://localhost:" + portNum + "/Score"; 24 25  ScoreReferInterface h; 26 27 try { 28 29 //查找远程对象 30 h = (ScoreReferInterface)Naming.lookup(registryURL); 31 System.out.println("Lookup completed."); 32 33 //输入 . 退出,或输入学生姓名以查询该学生的各门课成绩信息 34 System.out.println("Enter the student's name or . to quit"); 35 36 while(true){ 37 38 String sname = br.readLine(); 39 if(sname.equals(".")) 40 break; 41 42 //调用远程方法 43 String[] record = h.getScore(sname); 44 45 int i = 0; 46 while(true){ 47 48 //检查是否读到records的结尾(以防数组越界) 49 if(record[i].equals(new String("."))){ 50 //若并无该学生记录,则提示No such a student. 51 if(i == 0) 52 System.out.println("No such a student."); 53 break; 54  } 55 56 //输出学生课程成绩信息 57 System.out.println(record[i] + " " + record[i+1] + " " + record[i+3] + " " + record[i+2]); 58 i+=4; 59  } 60 61 //输入 . 退出,或输入学生姓名以查询该学生的各门课成绩信息 62 System.out.println("Enter the student's name or . to quit"); 63  } 64 System.out.println("Goodbye."); 65 66 } catch (NotBoundException e) { 67 System.out.println("here I am"); 68  System.err.println(e.getMessage()); 69 } catch (SQLException se) { 70 System.out.println("here I am2."); 71  System.err.println(se.getMessage()); 72  } 73  } 74 75 }

Server:

 1 import java.io.BufferedReader;  2 import java.io.IOException;  3 import java.io.InputStreamReader;  4 import java.net.MalformedURLException;  5 import java.rmi.Naming;  6 import java.rmi.RemoteException;  7 import java.rmi.registry.LocateRegistry;  8 import java.rmi.registry.Registry;  9 10 11 public class ScoreServer { 12 public static void main(String[] args) throws IOException{ 13 //定义流对象 14 InputStreamReader isr = new InputStreamReader(System.in); 15 BufferedReader br = new BufferedReader(isr); 16 17  String portNum, registryURL; 18 19 //设置服务器端口号 20 System.out.println("Enter the RMIregistry port number"); 21 portNum = (br.readLine()).trim(); 22 int RMIPortNum = Integer.parseInt(portNum); 23 24 //在指定端口处注册 25  startRegistry(RMIPortNum); 26 27 //注册接口实现类的引用 28 ScoreReferImpl impl = new ScoreReferImpl(); 29 registryURL = "rmi://localhost:" + portNum + "/Score"; 30  Naming.rebind(registryURL, impl); 31 32 System.out.println("Sever registered. Registry contains:"); 33 34 //列出已注册的信息 35  listRegistry(registryURL); 36 37 System.out.println("Score sever already"); 38 39 40 }//end main 41 42 public static void startRegistry(int RMIPortNum){ 43 try { 44 Registry registry = LocateRegistry.getRegistry(RMIPortNum); 45  registry.list(); 46 } catch (RemoteException e) { 47 System.out.println("RMI registry cannot be located at port" + RMIPortNum); 48 try { 49 Registry registry = LocateRegistry.createRegistry(RMIPortNum); 50 } catch (RemoteException e1) { 51 // TODO Auto-generated catch block 52  e1.printStackTrace(); 53  } 54 System.out.println("RMI registry created at port: " + RMIPortNum); 55  } 56 }//end startRegistry 57 58 private static void listRegistry(String registryURL) throws RemoteException, MalformedURLException{ 59 System.out.println("Registry " + registryURL + " contains: "); 60 String[] names = Naming.list(registryURL); 61 for(int i = 0;i<names.length;i++){ 62  System.out.println(names[i]); 63  } 64 }//end listRegistry 65 66 }//end class

Interface:

1 import java.rmi.Remote; 2 import java.sql.ResultSet; 3 import java.sql.SQLException; 4 5 6 public interface ScoreReferInterface extends Remote{ 7 public String[] getScore(String name) 8 throws java.rmi.RemoteException, SQLException; 9 }

Implement of Interface:

 1 import java.rmi.RemoteException;  2 import java.rmi.server.UnicastRemoteObject;  3 import java.sql.Connection;  4 import java.sql.ResultSet;  5 import java.sql.SQLException;  6 import java.sql.Statement;  7  8  9 public class ScoreReferImpl extends UnicastRemoteObject 10 implements ScoreReferInterface{ 11 12 //定义String数组的最大长度 13 final static int MAX_LEN = 200; 14 15 protected ScoreReferImpl() throws RemoteException { 16 super(); 17 // TODO Auto-generated constructor stub 18  } 19 20  @Override 21 public String[] getScore(String name) throws RemoteException, SQLException { 22 //建立并获取数据库连接 23 Connection conn = DbConn.getConnection("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/distributeds", "root", ""); 24 25 if(conn == null){ 26 System.out.println("未能成功连接数据库!"); 27  } 28 else{ 29 System.out.println("成功连接数据库!"); 30 31 //定义返回值String数组 32 String[] records = new String[MAX_LEN]; 33 34 //定义语句对象 35 Statement st = conn.createStatement(); 36 37 //定义sql语句 38 String sql = "select * from student where name='" + name + "'"; 39 40 //在数据库中查询并获得结果集 41 ResultSet rs = st.executeQuery(sql); 42 43 //将结果集中的记录存入String数组中 44  String id, sname, cname, score; 45 46 int i; 47 for(i = 0;rs.next();i+=4){ 48 id = rs.getString("id"); 49 sname = rs.getString("name"); 50 cname = rs.getString("cname"); 51 score = rs.getString("score"); 52 53 records[i] = id; 54 records[i+1] = sname; 55 records[i+2] = cname; 56 records[i+3] = score; 57  } 58 59 //标记结束字符串 60 records[i] = "."; 61  System.out.println(records[i]); 62 63  rs.close(); 64  st.close(); 65  conn.close(); 66 67 68 69 return records; 70 71  } 72 return null; 73  } 74 75 }

  • 上一篇: java面试的基础
  • 下一篇: java基础视频免费
  • 版权声明


    相关文章:

  • java面试的基础2025-04-17 08:18:02
  • java开发框架基础2025-04-17 08:18:02
  • java基础音频2025-04-17 08:18:02
  • java基础考试2025-04-17 08:18:02
  • JAVA语言基础编辑2025-04-17 08:18:02
  • java基础视频免费2025-04-17 08:18:02
  • java基础编码题2025-04-17 08:18:02
  • java集合基础代码2025-04-17 08:18:02
  • java基础题在线2025-04-17 08:18:02
  • java 常见基础组件2025-04-17 08:18:02