cuốn sách gpt4 ai đã làm

Triển khai RMI thông qua công nghệ cơ bản

In lại Tác giả: Người biết Thời gian cập nhật: 2024-03-13 10:16:03 25 4
mua khóa gpt4 Nike

Bắt mắt một chút

RMI: Gọi phương thức từ xa, chỉ áp dụng cho ngôn ngữ Java. Nói cách khác, ngôn ngữ được sử dụng trên mỗi máy tính phải là Java.

Cơ chế thực hiện: Về phía cục bộ (máy khách), thứ được vận hành trực tiếp là bản sao cục bộ của giao diện máy chủ (được gọi là sơ khai) và sơ khai đóng vai trò là giao diện máy chủ. Ví dụ: nếu đối tượng L của máy khách gọi phương thức() trong giao diện máy chủ R, thì nó không thể được viết trực tiếp dưới dạng L.method() ở phía máy khách. Do đó, trước tiên bạn phải tạo một bản sao cục bộ của giao diện R (nghĩa là sơ khai) của máy chủ trước khi ghi nó vào L.method(). Có thể thấy rằng trong quá trình giao tiếp RMI, giao diện máy khách sử dụng sơ khai và máy chủ cũng thiết lập khung đối tượng phụ trợ để tạo điều kiện thuận lợi cho việc tổ chức và quản lý các giao diện khác nhau của máy chủ và tạo điều kiện giao tiếp với máy khách. Nghĩa là, quá trình giao tiếp RMI thực sự liên quan đến sự tương tác trực tiếp giữa sơ khai máy khách và khung máy chủ, như thể hiện trong hình bên dưới.

2. Quy trình cụ thể

1 Máy khách và máy chủ trao đổi thông tin qua Socket.

a Trước tiên, máy khách xác định tên giao diện được yêu cầu dưới dạng một chuỗi ("remote.procedure.call.server.RMIService"), sau đó phân tích chuỗi này thông qua phản chiếu để lấy tên giao diện, tên phương thức và phương thức được yêu cầu . Các tham số và thông tin khác, đồng thời gửi thông tin này đến máy chủ thông qua luồng đối tượng ObjectOutputStream.

b Máy chủ phân tích từng thông tin này và gọi phương thức được yêu cầu trên máy chủ thông qua phương thứcgọi() trong phản ánh.

2 Vì máy chủ có thể có nhiều giao diện cung cấp phương thức nên máy chủ cần có một "trung tâm đăng ký dịch vụ" để quản lý thống nhất các giao diện này; khi máy khách yêu cầu một giao diện nhất định, "trung tâm đăng ký dịch vụ" có thể lấy và cung cấp ngay giao diện đó. . Trong số đó, "trung tâm đăng ký dịch vụ" có thể là Bản đồ, trong đó Key lưu tên giao diện và value là đối tượng giao diện của phương thức phản hồi.

3. Theo yêu cầu của khách hàng, "Trung tâm đăng ký dịch vụ" tìm giao diện tương ứng (thông qua map.get (tên giao diện)) và cung cấp các phương thức thông qua lớp triển khai của giao diện (nghĩa là thực thi các phương thức trong lớp triển khai ).

4 Sau khi dịch vụ hoàn thành, máy chủ chuyển giá trị trả về cho máy khách thông qua đối tượng.

5 Vì các dịch vụ khác nhau trả về các loại dữ liệu khác nhau cho máy khách nên máy khách cần nhận giá trị trả về từ máy chủ thông qua proxy động.

Ba biểu đồ dòng chảy

Bốn mã

1 Cung cấp giao diện dịch vụ

package rmi.server; // Trên máy chủ, giao diện cung cấp các dịch vụ giao diện công cộng RMIService { String sayHi(String name });

2 Cung cấp lớp triển khai của giao diện dịch vụ

package rmi.server; // Trên máy chủ, lớp triển khai cung cấp giao diện dịch vụ public class RMIServiceImpl triển khai RMIService { @Override public String sayHi(String name) { return "hi," + name;

3 Giao diện trung tâm đăng ký dịch vụ

gói rmi.server; /** * @className: ServerCenter * @description: Giao diện trung tâm đăng ký dịch vụ * @date: 14/5/2022 * @author: cakin */ giao diện công cộng ServerCenter { // Bắt đầu dịch vụ void start() ; // Đóng dịch vụ void stop(); // Đăng ký thanh ghi dịch vụ void(Class service, Class serviceImpl);

4 Lớp triển khai trung tâm đăng ký dịch vụ

gói rmi.server; nhập java.io.IOException; nhập java.io.ObjectInputStream; nhập java.io.ObjectOutputStream; nhập java.lang.reflect.Method; nhập java.net.Socket; nhập java.util.HashMap; nhập java.util.concurrent.ExecutorService; java.util.concurrent.Executors; // Lớp triển khai trung tâm đăng ký dịch vụ public class ServerCenterImpl triển khai ServerCenter { // map: Tất cả các giao diện trên máy chủ mà máy khách có thể truy cập được đã đăng ký trong bản đồ // key: tên của giao diện ( Chẳng hạn as "RMIService"), value: lớp dịch vụ thực (chẳng hạn như lớp RMIServiceImpl) Private static HashMap serviceRegiser = new HashMap<>(); Số cổng của máy chủ Private static int port; // Nhóm luồng: Có nhiều đối tượng luồng trong nhóm luồng, mỗi đối tượng luồng có thể xử lý một yêu cầu của khách hàng riêng tư ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors ( )); // Có nên mở dịch vụ boolean tĩnh dễ bay hơi riêng tư isRunning = false; public ServerCenterImpl(int port) { this.port = port; } // Khởi động dịch vụ máy chủ @Override public void start() { ServerSocket server = null; try { server = new ServerSocket(); (); } isRunning = true; // Mỗi khi máy khách yêu cầu một yêu cầu, máy chủ sẽ khởi động một đối tượng luồng từ nhóm luồng để xử lý while (true) { // Nội dung dịch vụ cụ thể: nhận yêu cầu của khách hàng, xử lý yêu cầu và trả về kết quả System.out.println("Dịch vụ đã bắt đầu..."); Socket socket = null; } Catch (IOException e) { e.printStackTrace(); } // Bắt đầu một luồng để xử lý các yêu cầu của khách hàng executor.execute(new ServiceTask(socket)); } } // Đóng dịch vụ @Override public void stop() { isRunning = false; executor.shutdown(); } // Tương ứng giữa tên giao diện và lớp triển khai giao diện, để khi nhận được yêu cầu, có thể lấy lớp triển khai dịch vụ tương ứng trong time @Override public void register(Class service, Class serviceImpl) { serviceRegiser.put(service.getName(), serviceImpl); } // Thread xử lý các yêu cầu lớp tĩnh riêng tư ServiceTask triển khai Runnable { socket public; ServiceTask() { } public ServiceTask(Socket socket) { this.socket = socket; } // Logic xử lý cụ thể @Override public void run() { ObjectOutputStream input = null; tham số của phần cuối (tên giao diện, tên phương thức, loại tham số, giá trị tham số) input = new ObjectInputStream(socket.getInputStream()); // Bởi vì ObjectInputStream()); Có những yêu cầu nghiêm ngặt về thứ tự gửi dữ liệu, vì vậy nó phải được nhận từng cái một theo thứ tự gửi // Tên giao diện được yêu cầu String serviceName = input.readUTF(); // Tên phương thức được yêu cầu String MethodName = input.readUTF(; ); // Loại tham số Phương thức yêu cầu Class[] tham sốTypes = (Class[]) input.readObject(); // Tên tham số phương thức yêu cầu Object[] đối số = (Object[]) input.readObject(); yêu cầu của khách hàng, tới bản đồ trung tâm đăng ký dịch vụ Tìm giao diện cụ thể tương ứng (nghĩa là RMIService) Class ServiceClass = serviceRegiser.get(serviceName); // Xây dựng phương thức được yêu cầu Method Method = ServiceClass.getMethod(methodName, tham sốTypes); // Thực thi phương thức Object result = Method. (ServiceClass.newInstance(), đối số); // Trả về giá trị trả về sau khi thực thi cho máy khách out = new ObjectOutputStream(socket.getOutputStream()); đầu ra.writeObject(kết quả); } bắt (Ngoại lệ e) { e.printStackTrace(); } cuối cùng { thử { if (output != null) out.close(); ; } bắt (Ngoại lệ e) { e.printStackTrace();

5 khách hàng

gói rmi.client; nhập java.io.ObjectInputStream; nhập java.io.ObjectOutputStream; nhập java.lang.reflect.InvocationHandler; nhập java.lang.reflect.Method; .InetSocketAddress; nhập java.net.Socket; lớp công khai RMIClient { /** * Mô tả chức năng: Lấy đối tượng proxy động (RMIService) đại diện cho giao diện máy chủ * * @param serviceInterface: tên giao diện được yêu cầu * @param addr: ip: cổng của máy chủ được yêu cầu * @author cakin * @date 2022/5/14 * / @SuppressWarnings("unchecked") public static  T getRemoteProxyObj(Class serviceInterface, InetSocketAddress addr) { /* Trong newProxyInstance(a,b,c), ý nghĩa của hai tham số đầu tiên như sau: a: Trình nạp lớp: Trình nạp lớp của đối tượng cần được ủy quyền b: Được sử dụng để chỉ ra những phương thức nào được đối tượng cung cấp cần phải được ủy quyền. Java có tính kế thừa đơn và triển khai nhiều giao diện. Do đó, nếu một đối tượng triển khai nhiều giao diện thì đối tượng đó có tất cả các phương thức của tất cả các giao diện của nó, vì vậy nó là một mảng giao diện. Ví dụ: nếu có A thực hiện giao diện B, giao diện C và có 3 phương thức trong giao diện B và 2 phương thức trong giao diện C thì đối tượng của A có 5 phương thức (không tính đến các phương thức do chính A cung cấp) */ return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[]{serviceInterface}, new InvocationHandler() { /** * Mô tả chức năng: * * @author cakin * @date 14/5/2022 * @param proxy: đối tượng proxy * Phương thức @param: phương thức nào (sayHi (danh sách tham số)) * @param args: danh sách tham số * @return T */ @Override public Object gọi (Proxy đối tượng, Phương thức phương thức , Object[] args) { // Máy khách gửi yêu cầu đến máy chủ: yêu cầu một giao diện cụ thể Ổ cắm socket = new Socket(); ObjectOutputStream đầu ra = null; = null; try { // addr chứa IP và cổng của máy chủ được truy cập socket.connect(addr); // Gửi yêu cầu đến máy chủ thông qua luồng tuần tự hóa (luồng đối tượng) out = new ObjectOutputStream(socket.getOutputStream () ); // Tên giao diện để gửi yêu cầu out.writeUTF(serviceInterface.getName()); // Tên phương thức gửi yêu cầu out.writeUTF(method.getName()); Loại tham số của phương thức gửi yêu cầu out.writeObject(method.getParameterTypes()); // Giá trị tham số của phương thức gửi yêu cầu out.writeObject(args); // Đang chờ xử lý phía máy chủ. .. // Nhận xử lý phía máy chủ Giá trị trả về sau input = new ObjectInputStream(socket.getInputStream()); return input.readObject(); } Catch (Ngoại lệ e) { e.printStackTrace() cuối cùng; { thử { if (output != null) out.close(); if (input != null) input.close(); } Catch (Ngoại lệ e) { e.printStackTrace();

6 Lớp khởi động máy chủ

gói rmi.test; nhập rmi.server.RMIService; nhập rmi.server.RMIServiceImpl; nhập rmi.server.ServerCenter; nhập rmi.server.ServerCenterImpl; lớp công khai TestRMIServer { public static void main(String[] args) { Bắt đầu dịch vụ dưới dạng một luồng new Thread(() -> { // Trung tâm dịch vụ ServerCenter server = new ServerCenterImpl(9999); // Đăng ký giao diện RMIService và lớp triển khai tới trung tâm dịch vụ server.register(RMIService.class, RMIServiceImpl.class);

7 Lớp khởi động máy khách

gói rmi.test; import rmi.client.RMIClient; import rmi.server.RMIService; import java.net.InetSocketAddress; // Khởi động máy chủ trước, sau đó là máy khách và bạn sẽ thấy máy khách đã gọi thành công máy chủ sayHi( ) phương pháp trên. public class TestRMIClient { public static void main(String[] args) ném ClassNotFoundException { // Gọi giao diện rmi.server.RMIService từ xa và thực thi phương thức sayHi() trong giao diện RMIService service = RMIClient.getRemoteProxyObj( Class.forName(" rmi.server.RMIService" ), mới InetSocketAddress("127.0.0.1", 9999)) ; System.out.println( service.sayHi("zs") ) ;

Năm kết quả kiểm tra

xin chào, zs

25 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress