zoukankan      html  css  js  c++  java
  • 分布式计算 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 }
  • 相关阅读:
    [环境]Java 环境变量
    [BZOJ 4008][HNOI2015]亚瑟王(期望Dp)
    [BZOJ 3295][Cqoi2011]动态逆序对(CDQ分治)
    [BZOJ 3668&UOJ #2][Noi2014]起床困难综合症(贪心)
    [BZOJ 4571][Scoi2016]美味(主席树)
    [BZOJ 4408][Fjoi 2016]神秘数(主席树+思路)
    [BZOJ 2212][Poi2011]Tree Rotations(线段树合并)
    [BZOJ 4592][Shoi2015]脑洞治疗仪(线段树)
    [BZOJ 2054]疯狂的馒头(并查集)
    [BZOJ 1455]罗马游戏(左偏树+并查集)
  • 原文地址:https://www.cnblogs.com/HenryThinker/p/2833294.html
Copyright © 2011-2022 走看看