分布式计算 lab2 Java RMI

题目:

 

 

实验二:Java RMI试验

 

 

【实验目的及要求】

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

要求:要求独立完成。

 

 

【实验原理和步骤】

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

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

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

 

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

 

 

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

 

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

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

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

 

 

数据库

 

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

 

1. Java程序设计实践教程(颜志军 栾媛媛)
2. Java程序设计(张化祥 陆晶)

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

 

要搞成数据库,先要装一个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);
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 + "\t" + name + "\t" + score + "\t" + 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)
);    

 

有一个东东很重要,就是

导入sql文件的命令:
mysql> source d:/myprogram/database/db.sql;

写在文本里,比较好,一次可以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] + "\t" + record[i+1] + "\t" + record[i+3] + "\t" +  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.\n 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 }

 

 

 

 

 

 

转载于:https://www.cnblogs.com/HenryThinker/archive/2012/12/26/2833294.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值