📜  Java RMI-数据库应用程序(1)

📅  最后修改于: 2023-12-03 15:31:31.895000             🧑  作者: Mango

Java RMI-数据库应用程序

简介

Java RMI(Remote Method Invocation)是一种基于Java语言实现的远程调用机制,允许Java应用程序通过网络访问远程对象。Java RMI可以使得分布式应用程序的开发更加简单、易于维护和扩展。

RMI可以作为一种分布式技术,将远程对象暴露给其他应用程序。这使得客户端程序可以调用远程对象的方法,在本地机器上实现远程函数调用(Remote Method Invocation),具有并发、安全性、扩展性和松耦合性的特点。

本文将介绍如何使用Java RMI实现一个简单的数据库应用程序,包括服务端和客户端代码。具体实现使用Java内置的H2数据库,可以根据需要进行其他的数据库连接。

实现步骤
创建服务端

服务端实现需要完成以下步骤:

  1. 定义远程接口。
  2. 实现远程接口。
  3. 启动RMI服务器。

定义远程接口

定义一个名为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服务器

在服务端,我们需要在服务启动之前启动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!")输出了一个启动消息。

创建客户端

客户端实现需要完成以下步骤:

  1. 获取远程对象。
  2. 调用远程对象方法。

获取远程对象

客户端通过以下代码获取远程对象:

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();
        }
    }

}