在上一章中,我们创建了一个RMI图形用户界面应用程序的示例,客户端调用服务器端显示GUI窗口(JavaFX)的方法。
在本章中,我们将以一个例子来看看客户端程序如何检索位于服务器上的MySQL数据库中的表的记录。
假设在数据库:testdb
中有一个名称为student
的表,其表结构和数据如下所示 -
+----+--------+--------+------------+---------------------+
| ID | NAME | BRANCH | PERCENTAGE | EMAIL |
+----+--------+--------+------------+---------------------+
| 1 | Maxsu | IT | 85 | maxsu@yiibai.com |
| 2 | Curry | EEE | 95 | curry123@gmail.com |
| 3 | Alex | ECE | 90 | alexs130@gmail.com |
+----+--------+--------+------------+---------------------+
创建数据库和表如下语句 -
CREATE DATABASE IF NOT EXISTS testdb DEFAULT CHARSET utf8 COLLATE utf8_general_ci
use testdb
-- ----------------------------
-- Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`
CREATE TABLE `student` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL DEFAULT &apos&apos,
`branch` varchar(16) NOT NULL DEFAULT &apos&apos,
`percentage` float unsigned DEFAULT &apos0&apos,
`email` varchar(48) NOT NULL DEFAULT &apos&apos,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (&apos1&apos, &aposMaxsu&apos, &aposIT&apos, &apos85&apos, &aposmaxsu@yiibai.com&apos)
INSERT INTO `student` VALUES (&apos2&apos, &aposCurry&apos, &aposEEE&apos, &apos96&apos, &aposcurry123@gmail.com&apos)
INSERT INTO `student` VALUES (&apos3&apos, &aposAlex&apos, &aposECE&apos, &apos92&apos, &aposalexs130@gmail.com&apos)
假设所使用的MySQL服务器的用户名是:root,其密码是:123456。
创建 Student 类
创建一个Student类,并创建setter
和getter
方法,创建一个Java源代码文件:Student.java,如下所示。
public class Student implements java.io.Serializable {
private int id, percent
private String name, branch, email
public int getId() {
return id
}
public String getName() {
return name
}
public String getBranch() {
return branch
}
public int getPercent() {
return percent
}
public String getEmail() {
return email
}
public void setID(int id) {
this.id = id
}
public void setName(String name) {
this.name = name
}
public void setBranch(String branch) {
this.branch = branch
}
public void setPercent(int percent) {
this.percent = percent
}
public void setEmail(String email) {
this.email = email
}
}
定义远程接口
在这里,我们定义一个名为Hello
的远程接口,Hello
接口中有一个getStudents()
方法。此方法返回一个包含Student
类对象的列表。
import java.rmi.Remote
import java.rmi.RemoteException
import java.util.*
// Creating Remote interface for our application
public interface Hello extends Remote {
public List<Student> getStudents() throws Exception
}
开发实现类
创建一个类并实现上面创建的Hello
远程接口。
这里我们实现远程接口的getStudents()
方法。当调用此方法时,它将检索数据库:students
表中的记录。使用Student
类的setter
方法设置对象的值并返回该对象列表。创建一个JAVA源文件:ImplExample.java 如下所示 -
import java.sql.*
import java.util.*
// Implementing the remote interface
public class ImplExample implements Hello {
// Implementing the interface method
public List<Student> getStudents() throws Exception {
List<Student> list = new ArrayList<Student>()
// JDBC driver name and database URL
String JDBC_DRIVER = "com.mysql.jdbc.Driver"
String DB_URL = "jdbc:mysql://localhost:3306/testdb"
// Database credentials
String USER = "root"
String PASS = "123456"
Connection conn = null
Statement stmt = null
//Register JDBC driver
Class.forName("com.mysql.jdbc.Driver")
//Open a connection
System.out.println("Connecting to a selected database...")
conn = DriverManager.getConnection(DB_URL, USER, PASS)
System.out.println("Connected database successfully...")
//Execute a query
System.out.println("Creating statement...")
stmt = conn.createStatement()
String sql = "SELECT * FROM student_data"
ResultSet rs = stmt.executeQuery(sql)
//Extract data from result set
while(rs.next()) {
// Retrieve by column name
int id = rs.getInt("id")
String name = rs.getString("name")
String branch = rs.getString("branch")
int percent = rs.getInt("percentage")
String email = rs.getString("email")
// Setting the values
Student student = new Student()
student.setID(id)
student.setName(name)
student.setBranch(branch)
student.setPercent(percent)
student.setEmail(email)
list.add(student)
}
rs.close()
return list
}
}
服务器程序
RMI服务器程序应实现远程接口或扩展实现类。 在这里,我们将创建一个远程对象并将其绑定到RMI注册表。
以下是本应用程序的服务器程序。 在这里,我们将扩展上述创建的类,创建一个远程对象并使用绑定名称为:hello ,将其注册到RMI注册表。创建一个JAVA源文件:Server.java 如下所示 -
import java.rmi.registry.Registry
import java.rmi.registry.LocateRegistry
import java.rmi.RemoteException
import java.rmi.server.UnicastRemoteObject
public class Server extends ImplExample {
public Server() {}
public static void main(String args[]) {
try {
// Instantiating the implementation class
ImplExample obj = new ImplExample()
// Exporting the object of implementation class (
// here we are exporting the remote object to the stub)
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0)
// Binding the remote object (stub) in the registry
Registry registry = LocateRegistry.getRegistry()
registry.bind("Hello", stub)
System.err.println("Server ready")
} catch (Exception e) {
System.err.println("Server exception: " + e.toString())
e.printStackTrace()
}
}
}
客户端程序
以下是本应用程序的客户端程序。 在这里,我们获取远程对象并调用getStudents()
方法。它从列表对象中检索表 - student
的行记录并显示它们。创建一个JAVA源文件:Client.java 如下所示 -
import java.rmi.registry.LocateRegistry
import java.rmi.registry.Registry
import java.util.*
public class Client {
private Client() {}
public static void main(String[] args)throws Exception {
try {
// Getting the registry
Registry registry = LocateRegistry.getRegistry(null)
// Looking up the registry for the remote object
Hello stub = (Hello) registry.lookup("Hello")
// Calling the remote method using the obtained object
List<Student> list = (List)stub.getStudents()
for (Student s:list)v {
// System.out.println("bc "+s.getBranch())
System.out.println("ID: " + s.getId())
System.out.println("name: " + s.getName())
System.out.println("branch: " + s.getBranch())
System.out.println("percent: " + s.getPercent())
System.out.println("email: " + s.getEmail())
}
// System.out.println(list)
} catch (Exception e) {
System.err.println("Client exception: " + e.toString())
e.printStackTrace()
}
}
}
运行示例的步骤
以下是运行RMI示例的步骤。
注意:如果手动编译,需要把上面代码存放到目录:F:\worksp\java_rmi\java-dbapp中,并创建一个目录:F:\worksp\java_rmi\java-dbapp\libs,把下载的
mysql-connector-java-5.1.40-bin.jar
库(下载地址:http://downloads.mysql.com/archives/c-j/ )放入到 F:\worksp\java_rmi\java-dbapp\libs 目录中。
第一步 - 打开存储所有程序的文件夹,并编译所有Java文件,如下所示。
F:\worksp\java_rmi\java-dbapp> javac -Djava.ext.dirs=F:\worksp\java_rmi\java-dbapp\libs *.java
第二步 - 使用以下命令启动rmi注册表。
F:\worksp\java_rmi\java-dbapp> start rmiregistry
执行上面命令后,将在单独的窗口中启动一个rmi注册表。
第三步 - 运行服务器类代码,如下所示。
F:\worksp\java_rmi\java-dbapp>java -Djava.ext.dirs=F:\worksp\java_rmi\java-dbapp\libs Server
Server ready
第三步 - 运行客户端类文件,如下所示。
F:\worksp\java_rmi\java-dbapp>java -Djava.ext.dirs=F:\worksp\java_rmi\java-dbapp\libs Client
执行上面命令后,输出结果如下 -
F:\worksp\java_rmi\java-dbapp>java -Djava.ext.dirs=F:\worksp\java_rmi\java-dbapp\libs Client
ID: 1
name: Maxsu
branch: IT
percent: 85
email: maxsu@yiibai.com
ID: 2
name: Curry
branch: EEE
percent: 96
email: curry123@gmail.com
ID: 3
name: Alex
branch: ECE
percent: 92
email: alexs130@gmail.com
F:\worksp\java_rmi\java-dbapp>