📅  最后修改于: 2023-12-03 15:31:31.895000             🧑  作者: Mango
Java RMI(Remote Method Invocation)是一种基于Java语言实现的远程调用机制,允许Java应用程序通过网络访问远程对象。Java RMI可以使得分布式应用程序的开发更加简单、易于维护和扩展。
RMI可以作为一种分布式技术,将远程对象暴露给其他应用程序。这使得客户端程序可以调用远程对象的方法,在本地机器上实现远程函数调用(Remote Method Invocation),具有并发、安全性、扩展性和松耦合性的特点。
本文将介绍如何使用Java RMI实现一个简单的数据库应用程序,包括服务端和客户端代码。具体实现使用Java内置的H2数据库,可以根据需要进行其他的数据库连接。
服务端实现需要完成以下步骤:
定义一个名为PersonService的接口,有getPersons、addPerson、removePerson三个方法。
public interface PersonService extends Remote {
List<Person> getPersons() throws RemoteException;
void addPerson(Person p) throws RemoteException;
void removePerson(Person p) throws RemoteException;
}
我们使用H2嵌入式数据库来存储Person对象。在PersonService接口的实现类中,我们可以使用以下代码实现:
public class PersonServiceImpl extends UnicastRemoteObject implements PersonService {
private Connection conn;
public PersonServiceImpl() throws RemoteException, SQLException {
super();
conn = DriverManager.getConnection("jdbc:h2:./database/person");
Statement stmt = conn.createStatement();
stmt.execute("create table if not exists Person (id int primary key, name varchar(255))");
}
@Override
public List<Person> getPersons() throws RemoteException {
List<Person> persons = new ArrayList<>();
try {
PreparedStatement stmt = conn.prepareStatement("select * from Person");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
persons.add(new Person(rs.getInt("id"), rs.getString("name")));
}
rs.close();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
return persons;
}
@Override
public void addPerson(Person p) throws RemoteException {
try {
PreparedStatement stmt = conn.prepareStatement("insert into Person (id, name) values (?, ?)");
stmt.setInt(1, p.getId());
stmt.setString(2, p.getName());
stmt.executeUpdate();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void removePerson(Person p) throws RemoteException {
try {
PreparedStatement stmt = conn.prepareStatement("delete from Person where id = ?");
stmt.setInt(1, p.getId());
stmt.executeUpdate();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
在实现类中,我们使用了UnicastRemoteObject来提供远程对象的访问。在构造函数中,我们建立了H2嵌入式数据库连接并创建了一个名为Person的表,其中包含id和name两个字段。在getPersons、addPerson和removePerson方法中,我们编写了相应的SQL语句,并使用Java JDBC进行数据库操作。
在服务端,我们需要在服务启动之前启动RMI服务器。这可以通过以下代码实现:
LocateRegistry.createRegistry(1099);
Naming.rebind("PersonService", new PersonServiceImpl());
System.out.println("Server started!");
LocateRegistry.createRegistry(1099)创建了一个1099端口的RMI registry。Naming.rebind("PersonService", new PersonServiceImpl())将PersonServiceImpl对象绑定到registry上,使其对客户端可见。System.out.println("Server started!")输出了一个启动消息。
客户端实现需要完成以下步骤:
客户端通过以下代码获取远程对象:
PersonService personService = (PersonService) Naming.lookup("rmi://localhost:1099/PersonService");
其中,rmi://localhost:1099是RMI registry的URL字符串,PersonService是服务端注册远程对象时使用的名称。注意,客户端需要知道服务端RMI的URL和端口才能查找服务。
客户端可以通过personService调用服务端的接口方法:
List<Person> persons = personService.getPersons();
personService.addPerson(new Person(1, "Alice"));
personService.removePerson(new Person(1, "Alice"));
服务端代码:
public class Server {
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(1099);
Naming.rebind("PersonService", new PersonServiceImpl());
System.out.println("Server started!");
} catch (RemoteException | MalformedURLException | SQLException e) {
e.printStackTrace();
}
}
}
public interface PersonService extends Remote {
List<Person> getPersons() throws RemoteException;
void addPerson(Person p) throws RemoteException;
void removePerson(Person p) throws RemoteException;
}
public class PersonServiceImpl extends UnicastRemoteObject implements PersonService {
private Connection conn;
public PersonServiceImpl() throws RemoteException, SQLException {
super();
conn = DriverManager.getConnection("jdbc:h2:./database/person");
Statement stmt = conn.createStatement();
stmt.execute("create table if not exists Person (id int primary key, name varchar(255))");
}
@Override
public List<Person> getPersons() throws RemoteException {
List<Person> persons = new ArrayList<>();
try {
PreparedStatement stmt = conn.prepareStatement("select * from Person");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
persons.add(new Person(rs.getInt("id"), rs.getString("name")));
}
rs.close();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
return persons;
}
@Override
public void addPerson(Person p) throws RemoteException {
try {
PreparedStatement stmt = conn.prepareStatement("insert into Person (id, name) values (?, ?)");
stmt.setInt(1, p.getId());
stmt.setString(2, p.getName());
stmt.executeUpdate();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void removePerson(Person p) throws RemoteException {
try {
PreparedStatement stmt = conn.prepareStatement("delete from Person where id = ?");
stmt.setInt(1, p.getId());
stmt.executeUpdate();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
客户端代码:
public class Client {
public static void main(String[] args) {
try {
PersonService personService = (PersonService) Naming.lookup("rmi://localhost:1099/PersonService");
List<Person> persons = personService.getPersons();
personService.addPerson(new Person(1, "Alice"));
personService.removePerson(new Person(1, "Alice"));
} catch (MalformedURLException | RemoteException | NotBoundException e) {
e.printStackTrace();
}
}
}