Báo cáo môn học Lập Trình Hệ Thống với Java Đề tài s ố 7 Tìm hiểu Lập trình phân tán trong Java
Trang 1Báo cáo môn học Lập Trình
Trang 2Lời nói đầu
Lập trình đối tượng phân tán là một trong những vấn đề nóng bỏng của công nghệ phần mền ngày nay Java là ngôn ngữ đi tiên phong trong việc giải quyết vấn đề lập trình phân tán Ngày nay nếu bạn không biết đến kỹ thuật lập trình này thì quả là một thiếu sót lớn Từ NET của Microsoft cho đến Java của Sun tất cả đều hướng đến môi trường hợp tác và tận dụng nguồn tài nguyên phân tán trên mạng Chương này sẽ giới thiệu với bạn khái niệm và cách cài đặt các đối tượng phân tán bằng kỹ thuật RMI trong Java
Nội dung chính:
The Roles of Client and Server
Remote Method Invocations
Setup for Remote Method Invocation
Parameter Passing in Remote Methods
Server Object Activation
Java IDL and CORBA
Remote Method Calls with SOAP
Phân chia công việc trong nhóm:
Bạn Huỳnh Thái Bình phụ trách phần:
The Roles of Client and Server
Remote Method Invocations
Bạn Hoàng Minh Hải phụ trách phần:
Setup for Remote Method Invocation
Bạn Huỳnh Xuân Tâm phụ trách phần:
Parameter Passing in Remote Methods Server Object Activation
Bạn Phan Thanh Hưng phụ trách 2 phần cuối:
Java IDL and CORBA Remote Method Calls with SOAP
Trang 3I/ The Roles of Client and Server(Vai trò của Client và
Server):
- Lấy ý tưởng là thu thập thông tin trên một máy tính khách hàng và gửi thông tin qua mạng cho máy chủ Giả sử rằng một người sử dụng trên một máy tính cá nhân sẽ điền vào mẫu yêu cầu thông tin Dữ liệu được gửi đến máy chủ của nhà cung cấp Các máy chủ xử lý yêu cầu và gửi lại thông tin sản phẩm cho khách hàng
Figure 5-1 Transmitting objects between client and server
- Trong mô hình truyền thống client/server, khách hàng yêu cầu một định dạng truyền tải và gửi dữ liệu yêu cầu đến máy chủ Các máy chủ phân tích yêu cầu định dạng và các định dạng phản ứng để truyền cho khách hàng Khách hàng sau đó phân tích những phản ứng và hiển thị nó cho người dùng
- Nếu bạn thực hiện bằng tay, có một rắc rối lớn: Bạn phải thiết kế một định dạng truyền tải, và bạn phải viết code cho việc chuyển đổi giữa dữ liệu và định dạng truyền
Trang 4Note:
Trong ví dụ này, chúng tôi giả định rằng khách hàng là một máy tính tương tác với một người sử dụng Tuy nhiên, khách hàng đều có thể chạy một ứng dụng web và yêu cầu một dịch vụ từ một chương trình chạy trên máy tính khác Có hai đối
tượng giao tiếp, đối tượng khách hàng trong ứng dụng web và các đối tượng máy chủ thực hiện các dịch vụ Đây là một mô hình rất phổ biến trong thực tế
- Chúng tôi quan tâm vào mô hình truyền thống client/server bởi vì nó làm cho vai trò của các máy khách và máy chủ trực quan hơn
- Cơ chế mà các lập trình viên làm cho khách hàng một phương pháp gọi thường xuyên, mà không lo lắng về việc gửi dữ liệu qua mạng hay phân tích phản ứng.đối tượng đã thực hiện công việc đó không nằm trong cùng một máy ảo Nó có thể không được thực hiện trong các ngôn ngữ lập trình Java
- Giải pháp là cài đặt một proxy(sử uỷ quyền) cho các đối tượng server trên client Proxy là một phương pháp phổ biến Các proxy client liên lạc với server
- Lập trình viên của đối tượng máy chủ không muốn phiền phức với các giao tiếp khách hàng Giải pháp là cài đặt một đối tượng proxy thứ hai trên máy chủ Các máy chủ proxy giao tiếp với các proxy của khách hàng, và nó làm cho phương pháp này phổ biến
Figure 5-2 Remote method call with proxies
Trang 5- Vậy làm thế nào để các proxy giao tiếp với nhau?
-> Điều đó phụ thuộc vào công nghệ thực hiện
- Có ba sự lựa chọn phổ biến:
RMI, Java Remote Method Invocation Technology hỗ trợ phương thức gọi
phân phối giữa các đối tượng Java
CORBA, Common Object Request Broker Architecture hỗ trợ phương thức
gọi giữa các đối tượng của bất kỳ ngôn ngữ lập trình CORBA sử dụng
Internet Inter-ORB Protocol, hoặc IIOP, để giao tiếp giữa các đối tượng
SOAP, Simple Object Access Protocol cũng là ngôn ngữ lập trình trung gian
Tuy nhiên, SOAP sử dụng một định dạng truyền dẫn dựa trên XML
Note:
Microsoft sử dụng COM Trong quá khứ, Microsoft đặt COM là một đối thủ so với CORBA Tuy nhiên, tại thời điểm này, Microsoft tập trung vào SOAP
- CORBA và SOAP hoàn toàn là ngôn ngữ trung gian Chương trình client
và server có thể được viết bằng C, C + +, Java, hoặc ngôn ngữ khác Bạn cung cấp một giao diện để xác định tín hiệu của các phương thức và các loại dữ liệu đối tượng của bạn có thể xử lý Những mô tả được định dạng bằng một ngôn ngữ đặc biệt, được gọi là ngôn ngữ định nghĩa giao diện (IDL) cho CORBA và ngôn ngữ
mô tả các dịch vụ Web (WSDL) cho SOAP
- Khá ít người tin rằng CORBA là mô hình đối tượng của tương lai Thành thật mà nói CORBA đã có ích trong việc triển khai các vấn đê phức tạp và các vấn
đề tương thích
- SOAP có thể đơn giản, nhưng nó cũng có thể trở nên khá phức tạp, vì nó yêu cầu nhiều tính năng hơn mà CORBA đã có Các giao thức XML có lợi thế là ngôn ngữ gần gũi với con người nên giúp ích cho việc gỡ rối Nhìn chung,
CORBA hiệu quả hơn, mặc dù SOAP là một phù hợp tốt hơn cho một kiến trúc web
- Nếu cả hai đối tượng giao tiếp được thực hiện trong code Java, thì việc dùng CORBA và SOAP là không cần thiết Sun đã phát triển một cơ chế đơn giản,
đó là phương pháp triệu gọi phương thức từ xa-Remote Method Invocation (RMI),
đặc biệt dùng cho giao tiếp giữa các ứng dụng Java
Trang 6II./ Remote Method Invocations(Gọi phương thức từ xa):
- Nếu bạn có quyền truy cập vào một đối tượng trên một máy tính khác, bạn
có thể gọi các phương thức của đối tượng từ xa Tất nhiên, các tham số phương thức bằng cách nào đó phải được gửi đến các máy khác, máy chủ phải được thông báo để thực hiện các phương thức, và giá trị trả về phải được return trở lại RMI xử
lý việc này
- Ví dụ: client tìm kiếm thông tin sản phẩm có thể truy vấn một đối tượng trên máy chủ Nó gọi một phương thức từ xa, tìm kiếm, trong đó có một tham số: một đối tượng khách hàng Việc tìm thấy trả về một đối tượng cho client: đối tượng của sản phẩm
Figure 5-3 Invoking a remote method on a server object
- Trong thuật ngữ RMI , các đối tượng của phương thức tạo ra lời gọi từ xa
được gọi là client object Các đối tượng từ xa được gọi là server object Điều quan
trọng là phải nhớ rằng thuật ngữ client/server chỉ áp dụng cho một lời gọi phương thức duy nhất Các máy tính đang chạy code Java mà gọi phương thức từ xa là
client và máy tính lưu trữ các đối tượng mà thực hiện lời gọi là server Điều này
hoàn toàn làm cho vai trò được đảo ngược lại Server của một lời gọi trước đó có thể trở thành client khi gọi một một đối tượng bằng phương thức từ xa ở trên máy
tính khác
Trang 71/ Stubs and Parameter Marshalling:
- Khi client muốn gọi một phương thức từ xa trên một đối tượng từ xa, thì nó gọi 1 phương pháp thông thường trên một đối tượng proxy gọi là stub Stub nằm trên máy client, không phải trên server Ví dụ, trong giao thức RMI các đối tượng
được mã hoá với cơ chế tuần tự Quá trình mã hóa các thông số được gọi là tham
số marshalling(parameter marshalling) Mục đích của tham số marshalling là
chuyển đổi các tham số vào một định dạng thích hợp cho việc vận chuyển từ máy
ảo với nhau
- Phương thức stub trên client xây dựng một khối thông tin bao gồm:
o Nhận dạng đối tượng từ xa sẽ được sử dụng;
o Một mô tả của phương thức được gọi ;
o Các tham số marshalled
- Phương thức stub sau đó gửi thông tin này tới server Về phía server, một
đối tượng thực hiện các hành động cho mỗi lời gọi phương thức từ xa:
o Nó không có các thông số marshals
o Nó định vị đối tượng được gọi
o Nó gọi phương thức mong muốn
o Nó sẽ giữ và sắp đặt giá trị trả về hoặc ngoại lệ của cuộc gọi
o Nó sẽ gửi một gói gồm các dữ liệu trả về marshalled tới stub trên client
Trang 8Figure 5-4 Parameter marshalling
- Quá trình này rõ ràng là phức tạp, nhưng nó hoàn toàn tự động và minh bạch cho các lập trình viên Hơn nữa, các nhà thiết kế của các đối tượng Java từ xa
đã cố gắng để cung cấp cho các đối tượng từ xa cùng "look and feel(xem và cảm thấy)" như các đối tượng nội tại
2./ Dynamic Class Loading:
- Khi truyền một đối tượng từ xa đến một chương trình khác, như là một tham số hay giá trị trả về của một phương thức từ xa, thì chương trình đó phải có
các file class cho đối tượng đó Ví dụ, hãy xem xét một phương thức với kiểu trả
về là các sản phẩm Tất nhiên, chương trình client cần các lớp Product.class để biên dịch Nhưng bây giờ giả sử server khởi tạo và trả về một đối tượng sách, và sách là một phân nhóm của sản phẩm Các client có thể chưa bao giờ thấy class
Book, và nó có thể đã không biết nơi để tìm file lớp Book.class
- Do đó, một bộ nạp lớp đó sẽ được tải từ máy chủ Quá trình này cũng tương tự như quá trình nạp lớp của các applet chạy trong trình duyệt Bất cứ khi nào một chương trình tải mới mã từ một vị trí mạng, sẽ phát sinh vấn đề an ninh
Trang 9Vì lý do đó, bạn cần sử dụng một chương trình quản lý bảo mật(security manager)
trong các ứng dụng client RMI Đây là một cơ chế an toàn để bảo vệ các chương trình từ virus trong mã stub Đối với các ứng dụng chuyên ngành, các lập trình có thể thay thế bộ tải lớp của mình và quản lý an ninh, nhưng được cung cấp bởi hệ
thống RMI là đủ cho sử dụng bình thường
III/ Setup for Remote Method Invocation(Cài đặt cho
phương pháp truyền dẫn dữ liệu từ xa):
- Ngay cả khi chạy những ví dụ đơn giản nhất các đối tượng từ xa(remote
object) yêu cầu nhiều hơn những thiết lập không chạy một chương trình độc lập hoặc applet Bạn phải chạy các chương trình trên cả các máy tính máy chủ và máy khách Các thông tin object cần thiết phải được tách vào vào phía giao diện máy khách và giao diện máy chủ phía triển khai Ngoài ra, một cơ chế đặc biệt cho phép client tra cứu để xác định vị trí các object trên máy chủ
- Để bắt đầu, chúng ta đi qua từng yêu cầu, sử dụng ví dụ đơn giản Trong ví
dụ đầu tiên của chúng ta tạo ra một vài đối tượng của một loại sản phẩm trên máy chủ Sau đó chúng ta chạy một chương trình trên một máy tính client để xác định
1/ Interfaces and Implementations(Giao diện và Triển khai):
- Chương trình client cần để thao tác các đối tượng server nhưng nó không
thực sự copy chúng Các đối tượng tự cư trú trên máy chủ Mã client vẫn phải biết những gì nó có thể làm với các đối tượng, khả năng của chúng được thể hiện trong một giao diện được chia sẻ giữa client và server và để cư trú đồng thời trên cả hai máy
interface Product // shared by client and server
extends Remote
{
String getDescription() throws RemoteException;
}
- Cũng như trong ví dụ này tất cả các giao diện cho các remote object phải
pháp trong các giao diện cũng phải biểu thị một Remote Exception Lý do cho việc
khai báo là cuộc gọi phương thức từ xa vốn ít tin cậy hơn cuộc gọi địa phương, luôn luôn có thể có một cuộc gọi từ xa sẽ thất bại Ví dụ, máy chủ hoặc kết nối mạng có thể tạm thời không có hoặc có vấn đề mạng Code máy client của bạn phải được chuẩn bị để đối phó với những khả năng này Đối với những lý do này
Ngôn ngữ lập trình Java buộc bạn phải theo kịp Remote Exception với tất cả các
Trang 10cuộc gọi phương thức từ xa và để xác định các hành động thích hợp để có khi cuộc gọi không thành công Các khách hàng truy cập các đối tượng máy chủ thông qua stub để thực hiện giao diện này
Product p = ; // see below how the client gets a stub
reference
String d = p.getDescription();
System.out.println(d);
- Trong phần tiếp theo, bạn sẽ thấy làm thế nào client có thể có được một
tham chiếu đến loại đối tượng từ xa
- Tiếp theo, ở phía máy chủ, bạn phải thực hiện các lớp mà thực sự thực hiện các phương pháp quảng cáo trong giao diện từ xa
public class ProductImpl // server
UnicastRemoteObject có thể dịch chuyển ngoại lệ nếu nó không thể kết nối với dịch vụ mạng theo dõi các đối tượng máy chủ
từ các khách hàng từ xa
Trang 11- Bạn có thể nói rằng class là một máy chủ cho các phương pháp điều khiển
các đối tượng truy cập từ xa
NOTE
Lớp ProductImpl không phải là một lớp máy chủ điển hình bởi vì nó làm việc quá
ít Thông thường, bạn chỉ muốn có máy chủ làm một số công việc nặng mà một client không thể thực hiện Chúng tôi chỉ sử dụng các ví dụ sản phẩm để hướng dẫn bạn qua các cơ chế gọi các phương thức từ xa
java.rmi.server nhưng RemoteServer là một lớp trừu tượng mà chỉ xác định các cơ chế cơ bản trong giao tiếp giữa máy chủ và các đối tượng khai từ xa Lớp
UnicastRemoteObject mà đi kèm với RMI mở rộng lớp trừu tượng và là
RemoteServer bạn có thể sử dụng nó mà không cần viết bất kỳ mã nào "path of
least resistance "cho một lớp máy chủ là có nguồn gốc từ UnicastRemoteObject,
và tất cả các lớp máy chủ trong chương này làm như vậy
Hình 5-5 cho thấy mối quan hệ thừa kế giữa các lớp này
Trang 12- Một đối tượng UnicastRemoteObject nằm trên máy chủ Nó còn chạy được khi một dịch vụ được yêu cầu và phải được truy cập thông qua giao thức TCP / IP Đây là lớp mà chúng tôi mở rộng cho tất cả các lớp máy chủ trong cuốn sách này và là lớp máy chủ chỉ có trong phiên bản hiện tại của gói RMI Sun(mặt trời) hoặc bên thứ ba nhà cung cấp có thể, trong tương lai, thiết kế các lớp khác để sử dụng bởi các máy chủ cho RMI
NOTE
Thỉnh thoảng, bạn có thể không muốn có một lớp máy chủ mở rộng lớp
UnicastRemoteObject, có lẽ bởi vì nó đã được mở rộng một lớp khác Trong tình hình đó, bạn cần phải tự khởi tạo các đối tượng máy chủ và truyền cho phương
UnicastRemoteObject.exportObject(this, 0);
Trong xây dựng của các đối tượng máy chủ Tham số thứ hai là 0 để chỉ ra rằng bất
kỳ cổng thích hợp có thể được sử dụng để lắng nghe các kết nối client
- Khi bạn sử dụng RMI (hoặc bất kỳ cơ chế đối tượng phân tán, cho từng vấn đề), bạn sẽ cần phải nắm vững một chút bối rối tập các lớp Trong chương này, chúng tôi sử dụng một quy ước đặt tên thống nhất cho tất cả các ví dụ của chúng tôi mà chúng tôi hy vọng làm cho nó dễ dàng hơn để nhận ra mục đích của từng loại(xem Bảng 5-1)
Trang 132/ Stub Class Generation:
- Theo JDK 5.0, tất cả các lớp stub được tạo ra tự động, sử dụng cơ chế
proxy thảo luận trong Tập 1, chương 6 Tuy nhiên, trước khi JDK 5.0, bạn phải tự tạo ra khai với công cụ rmic, như trong ví dụ sau đây
bạn đang tạo ra khai cho một lớp trong một gói, bạn phải cung cấp cho rmic tên gói đầy đủ
3/ Locating Server Objects:
- Để truy cập một đối tượng từ xa mà tồn tại trên máy chủ, khách hàng cần
có một đối tượng stub địa phương, Làm thế nào có thể yêu cầu client như một stub Phương pháp phổ biến nhất là để gọi một phương thức từ xa của một đối tượng server và nhận được một đối tượng stub như là một giá trị trả về
- Tuy nhiên,có một vấn đề "con gà và quả trứng” ở đây Các đối tượng máy chủ đầu tiên đã được đặt một cách khác The Sun RMI thư viện cung cấp dịch vụ đăng ký khởi động để định vị các đối tượng máy chủ đầu tiên, Một chương trình
máy chủ đăng ký các đối tượng với dịch vụ đăng ký khởi động, và client truy khai
cho các đối tượng Bạn đăng ký một đối tượng máy chủ bằng cách cho cơ quan đăng ký khởi động dịch vụ một tham chiếu đến các đối tượng và tên một Tên này
là một chuỗi được (hy vọng) độc đáo
// server
ProductImpl p1 = new ProductImpl("Blackwell Toaster");
Context namingContext = new InitialContext();
namingContext.bind("rmi:toaster", p1);
Trang 14- Mã khách hàng nhận được một stub đối tượng để truy cập máy chủ bằng cách chỉ định tên máy chủ và tên các đối tượng theo cách sau:
// client
Product p = (Product)
namingContext.lookup("rmi://yourserver.com/toaster");
số cổng tùy chọn, giảm khác, và tên của các đối tượng từ xa Một ví dụ khác là:
vụ khởi động đối tượng có thể xác định vị trí các đối tượng khác cho bạn Trong ví
dụ của chúng tôi, chúng tôi tạm thời hành vi vi phạm quy tắc này và đăng ký các đối tượng tương đối nhỏ để cho bạn thấy cơ chế đăng ký, định vị đối tượng
- Vì lý do an ninh, ứng dụng có thể mở ra ràng buộc, hoặc đăng ký tài liệu tham khảo đối tượng rebind chỉ khi nó chạy trên máy chủ giống như đăng ký Điều này ngăn cản các client thù địch từ thay đổi thông tin đăng ký Tuy nhiên, bất kỳ client cũng có thể tra cứu các đối tượng Các dịch vụ RMI đặt tên là tích hợp vào trong đặt tên Java và mục thông tin (JNDI) dịch vụ Trong JDK 1.3 và dưới đây, bạn sử dụng một dịch vụ RMI đặt tên độc, như thế này:
Naming.bind("toaster", p1); // on the server
Product p = (Product) Naming.lookup("rmi://yourserver.com/toaster");
TIP
Nếu bạn so sánh các máy chủ của chúng tôi với các ví dụ máy chủ trong tài liệu hướng dẫn Sun, bạn sẽ lưu ý rằng chúng tôi không cài đặt một trình quản lý bảo mật trong máy chủ Trái ngược với các báo cáo trong hướng dẫn này, một quản lý
an ninh là không cần thiết cho các máy chủ RMI Bạn cần một quản lý an ninh, nếu client gửi đến các đối tượng máy chủ thuộc về các lớp mà máy chủ không biết Tuy nhiên, trong dịch vụ của chúng tôi, client chỉ gửi các thông số String Nói chung,
nó có vẻ khôn ngoan để hạn chế nạp lớp động trên các máy chủ
Trang 156 This server program instantiates two remote objects,
7 registers them with the naming service, and waits for
8 clients to invoke methods on the remote objects
Trang 1613 Constructs a product implementation
14 @param n the product name
9 Gets the description of this product
10 @return the product description
11 */
12 String getDescription() throws RemoteException;
13 }
4/ Starting the Server:
- Chương trình máy chủ của chúng tôi là không hoàn toàn sẵn sàng để chạy được Bởi vì nó sử dụng các chương trình khởi động RMI Registry, dịch vụ đó phải có sẵn Để bắt đầu đăng ký RMI theo UNIX, thực hiện các tuyên bố
rmiregistry &
Trang 17- Nếu là Windows thì gọi:
start rmiregistry
- Giờ thì bạn có thể khởi động Server Nếu là Unix thì chạy lệnh:
java ProductServer &
- Nếu là Windows thì chạy lệnh:
start java ProductServer
- Nếu bạn chạy chương trình theo cách sau:
java ProductServer
thì chương trình sẽ không bao giờ thoát ra bình thường.Điều này có vẻ kỳ lạ sau khi tất cả, chương trình chỉ tạo ra hai đối tượng và đăng ký chúng.Trên thực tế,các chức năng chính không xuất cảnh ngay lập tức sau khi đăng ký,như bạn mong đợi
một chủ đề riêng biệt để duy trì chương trình còn sống vô thời hạn được bắt đầu
Vì vậy, chương trình tồn tại xung quanh để cho phép khách hàng để kết nối với nó
TIP
dịch bytecode là một quá trình Windows riêng biệt và giữ nó chạy Một số nguồn
trong nền trong Windows cho RMI Làm như vậy không phải là một ý tưởng tốt, vì
thị trong danh sách công việc Nó chỉ ra rằng bạn cần phải giết và khởi động lại dịch vụ đăng ký khởi động khi bạn thay đổi STUB của một lớp đăng ký Để giết một quá trình mà bạn bắt đầu với lệnh bắt đầu, tất cả các bạn phải làm là nhấp chuột vào cửa sổ và nhấn Ctrl + C
Đặc biệt, họ không được hiển thị ở bất cứ đâu Nếu bạn muốn xem kết quả hoặc
diện điều khiển Và tin tưởng chúng TÔI, bạn sẽ muốn nhìn thấy những tin nhắn này Rất nhiều những thứ có thể đi sai khi bạn thử nghiệm với RMI Các lỗi phổ
đầu của bạn tự hỏi tại sao các CLIENT không có thể tìm thấy các đối tượng máy chủ
Trang 185/ Listing Remote Objects:
- Trước khi viết chương trình client, hãy xác minh rằng chúng ta đã thành công trong việc đăng ký các đối tượng từ xa Ta gọi:
NamingEnumeration<NameClassPair> e = namingContext.list("rmi:");
chứa cả tên của đối tượng bị ràng buộc và tên của các lớp Chúng tôi chỉ quan tâm đến những cái tên:
while (e.hasMore()) System.out.println(e.next().getName());
- Ví dụ 5-4 chứa chương trình đầy đủ Output sẽ là:
Trang 19- Bây giờ, chúng ta có thể viết các chương trình CLIENT có yêu cầu từng đối tượng sản phẩm mới được đăng ký để in mô tả của nó chương trình CLIENT
có sử dụng RMI nên cài đặt một trình quản lý an ninh để kiểm soát các hoạt động
mật Bạn cài đặt nó với chỉ dẫn sau:
System.setSecurityManager(new RMISecurityManager());
NOTE
Nếu tất cả các lớp (bao gồm cả stub ) có sẵn tại địa phương, sau đó bạn không thực
sự cần một người quản lý bảo mật Nếu bạn biết tất cả các tập tin lớp của chương trình của bạn tại thời gian triển khai, bạn có thể triển khai chúng tất cả các địa phương Tuy nhiên, nó thường xảy ra rằng chương trình tiến hóa máy chủ và các lớp mới được thêm vào theo thời gian Sau đó, bạn được hưởng lợi từ việc nạp lớp năng động Bất cứ lúc nào bạn mã tải từ một nguồn khác, bạn cần một người quản
6 This program demonstrates how to call a remote method
7 on two objects that are located through the naming
Trang 2016 // change to "rmi://yourserver.com/" when server runs on remote machine
yourserver.com
17 try
18 {
19 Context namingContext = new InitialContext();
20 Product c1 = (Product) namingContext.lookup(url +
7/ Running the Client:
chương trình từ việc thiết lập kết nối mạng Tuy nhiên, chương trình cần để làm cho các kết nối mạng Để đạt được đăng ký RMI, và để liên hệ với các đối tượng máy chủ
- Một khi các chương trình client được triển khai, nó cũng cần sự cho phép
để tải các lớp stub của nó Chúng tôi quyết vấn đề này sau khi chúng tôi thảo luận triển khai
- Để cho phép các client để kết nối đến cơ quan đăng ký RMI và đối tượng máy chủ, bạn cung cấp một tập tin chính sách Chúng tôi thảo luận về các tập tin chính sách cụ thể hơn trong chương 9 Để bây giờ, chỉ cần sử dụng và sửa đổi các mẫu mà chúng tôi cung cấp Dưới đây là một tập tin chính sách cho phép một ứng dụng để thực hiện bất kỳ kết nối mạng vào một cổng với số cổng ít nhất là 1024 (Cổng RMI là 1099 theo mặc định, và các đối tượng máy chủ cũng sử dụng cổng ≥ 1024.)
grant
{
permission java.net.SocketPermission
"*:1024-65535", "connect";
Trang 21System.setProperty ("java.security.policy", "client.policy");
- Ngoài ra, bạn có thể chỉ định thiết lập hệ thống tài sản trên dòng lệnh:
java-Djava security.policy = client.policy ProductClient
NOTE
Trong JDK 1.1, một tập tin chính sách đã không được yêu cầu cho khách hàng RMI Bạn không cần một tập tin chính sách cho các applet, hoặc, cung cấp máy chủ và đăng ký RMI RMI đều nằm trên máy chủ phục vụ các mã applet
- Nếu đăng ký RMI và máy chủ vẫn còn đang chạy, bạn có thể tiến hành để chạy các máy khách Hoặc, nếu bạn muốn bắt đầu từ đầu, giết RMI registry và máy chủ Sau đó làm theo các bước sau:
1) Compile the source files for the interface, implementation, client, and server classes
Trang 224) Start the server
java ProductServer &
or
start java ProductServer
5) Run the client
java ProductClient
- Chương trình đơn giản là in ra:
I am a Blackwell Toaster Buy me!
I am a ZapXpress Microwave Oven Buy me!
- Output này không có vẻ tất cả những gì ấn tượng, nhưng xem xét những gì diễn ra ở hậu trường khi các chương trình client thực hiện các cuộc gọi đến các
đối tượng stub rằng nó thu được từ phương pháp tra cứu Nó gọi phương pháp
geTDescription, đó gửi một thông điệp mạng cho một đối tượng thu trên phía
Người nhận sẽ gửi chuỗi trên mạng stub Các nhận được nó và trả về nó như là kết quả (xem Hình 5-6)
Trang 238/ Preparing for Deployment:
- Triển khai một ứng dụng sử dụng RMI có thể được khó khăn bởi vì rất nhiều điều có thể đi sai và các thông báo lỗi mà bạn nhận được khi một cái gì đó
mơ hồ Chúng tôi đã tìm thấy rằng nó thực sự đền đáp cho giai đoạn triển khai tại địa phương Trong bước chuẩn bị, riêng các lớp tập tin vào ba thư mục con:
Nếu bạn sử dụng JDK 1.4 hoặc dưới đây, thêm các lớp stub (như
ProductImpl_Stub.class) vào thư mục máy chủ Chúng là cần thiết khi máy chủ đăng ký các đối tượng thực hiện Trái ngược với niềm tin phổ biến, máy chủ sẽ không xác định vị trí chúng trong thư mục tải về, ngay cả khi bạn thiết lập các cơ
- Bạn cần phải chạy một máy chủ web để phục vụ các tập tin lớp học trên máy tính của bạn Nếu bạn không có một máy chủ web cài đặt, tải về từ
http://jakarta.apache.org/tomcat và cài đặt nó Tạo một thư mục tomcat / webapps
Trang 24/ download, nơi tomcat là thư mục gốc cài đặt Tomcat của bạn Tạo một thư mục
tomcat / webapps / download / WEB-INF, và để các tập tin tối thiểu sau đây
web.xml trong thư mục WEB-INF:
- Thay đổi file sao cho giống như sau:
- Cuối cùng, bạn đã sẵn sàng để thử nghiệm thiết lập của bạn
1 Khởi động máy chủ web
2 Điểm một trình duyệt web vào URL download
(http://localhost:8080/download/Product.class cho Tomcat) để xác minh rằng các máy chủ web đang chạy
3 Bắt đầu một lớp vỏ mới Hãy chắc chắn rằng đường dẫn lớp là không được đặt để bất cứ điều gì Thay đổi vào một thư mục mà không chứa các tập tin lớp Sau đó bắt đầu đăng ký RMI
4 Bắt đầu một lớp mới Thay đổi vào thư mục máy chủ Khởi động máy chủ, cho một URL vào thư mục tải về là giá trị của tài sản
java.rmi.server.codebase:
java -Djava.rmi.server.codebase=http://localhost:8080/download/ ProductServer &
Trang 255 Thay đổi vào thư mục client Hãy chắc chắn rằng các file client.policy là trong thư mục đó Bắt đầu cho client
java -Djava.security.policy=client.policy ProductClient
TIP
Nếu bạn không muốn cài đặt một máy chủ web tại địa phương, bạn có thể sử dụng một URL tập tin để kiểm tra nạp lớp Tuy nhiên, thiết lập được một chút phức tạp hơn Thêm dòng
permission java.io.FilePermission "downloadDirectory", "read ";
vào tập tin chính sách client của bạn Ở đây, các thư mục tải về là tên đường dẫn đầy đủ đến thư mục tải về, kèm theo trong dấu ngoặc kép, và kết thúc bằng một dấu trừ (để chỉ tất cả các file trong thư mục và thư mục con của nó) Ví dụ:
permission java.io.FilePermission "/ home/test/download/-",
"read";
Trong tên tập tin Windows, bạn phải tăng gấp đôi mỗi dấu chéo ngược Ví dụ,
permission java.io FilePermission "c: \ \ home \ \ test \ \ download \ \ -", "read";
Bắt đầu đăng ký RMI sau đó các bắt đầu máy chủ với
9./ Deploying the Program(Triển khai chương trình):
- Bây giờ bạn đã kiểm tra việc triển khai các chương trình của bạn, bạn đã
sẵn sàng để phân phối nó vào thực tế khách hàng và máy chủ Di chuyển các lớp trong thư mục tải về vào máy chủ web
- Hãy chắc chắn để sử dụng URL khi bắt đầu các máy chủ Di chuyển các
lớp trong thư mục server vào máy chủ của bạn và bắt đầu đăng ký RMI và máy chủ thiết lập máy chủ của bạn bây giờ hoàn thành, nhưng bạn cần phải thực hiện hai thay đổi trong máy khách Đầu tiên, chỉnh sửa các tập tin chính sách và thay
Trang 26"yourserver.com:80", "connect";
};
String url = "rmi://yourserver.com/";
Product c1 = (Product) namingContext.lookup(url + "toaster");
- Sau đó, biên dịch lại client và thử nó Nếu công trình tất cả mọi thứ, sau đó xin chúc mừng là theo thứ tự Nếu không, bạn có thể tìm được danh sách kiểm tra bên hữu ích Nó liệt kê một số vấn đề mà thường có thể phát sinh khi bạn đang cố gắng
để có được RMI để làm việc
10/ Logging RMI Activity:
- Việc thực thi Sun RMI được cung cấp để tạo ra logging messages, sử dụng
tiêu chuẩn Java logging API
dung như sau:
handlers=java.util.logging.ConsoleHandler
.level=FINEST
java.util.logging.ConsoleHandler.level=FINEST
java.util.logging.ConsoleHandler.formatter=java.util.logging.Sim pleFormatter
- Bạn có thể tinh chỉnh các thiết lập bằng cách thiết lập mức độ riêng lẽ cho mỗi người đăng nhập hơn là thiết lập mức độ tổng thể.Bảng 5-2 danh sách logger của RMI:
Trang 27- Bắt đầu đăng ký RMI với lựa chon sau:
-J-Djava.util.logging.config.file=directory/logging.properties
- Khởi động client và server với:
-Djava.util.logging.config.file=directory/logging.properties
- Đó là cách tốt nhất để khởi động RMI, client, server trong môi trường khác nhau
- Sau đây là ví dụ của logging message cho ta thấy vấn đề của 1 lớp đang tải:
1/ Passing Nonremote Objects (truyền các đối tượng không từ xa):
- Khi một đối tượng từ xa được truyền từ máy chủ tới máy con, máy con nhận một stub Sử dụng stub này, máy con có thể thao tác đối tượng máy chủ bằng cách gọi ra phương thức từ xa.Tuy nhiên,đối tượng vẫn lưu trên máy chủ Nó cũng
có thể truyền và trả lại bất kỳ đối tượng khi gọi một phương thức từ xa không chỉ vậy mà còn thực hiện giao diện từ xa
String
Chuỗi đó được tạo ra trên máy chủ và đã được chuyển đến máy con Bởi vì kiểu
String không thực hiện giao diện từ xa nên máy chủ không thể trả về đối tượng stub kiểu chuỗi Thay vào đó, máy con lấy một bản sao của chuỗi.Khi đó, sau khi
Trang 28bất kỳ kết nối nào thêm nữa cho bất kỳ đối tượng trên máy chủ để phân tán chuỗi
đó
chuyển từ -máy ảo Java đến vùng khác,máy ảo Java thực hiện sao chép và gửi bản sao chép đó thông qua kết nối mạng.Kỹ thuật này sử dụng phương pháp cục bộ để truyền tham số.Khi ta truyền đối tượng vào một phương thức cục bộ,hoặc trả về đối tượng từ kết quả của phương thức này,lưu ý là chỉ có đối tượng tham chiếu được truyền.Tuy nhiên, các đối tượng tham chiếu là những địa chỉ nhớ của các đối tượng trong máy ảo Java cục bộ.Thông tin này là vô nghĩa với một máy ảo Java khác
chuỗi sao chép đó có thể được chuyển qua mạng.Cơ chế RMI có thể thực hiện sao chép nhiều đối tượng phức tạp hơn nữa, miễn là chúng được tuần tự hóa(được sắp xếp có thứ tự) RMI sử dụng cơ chế tuần tự hóa được mô tả trong “ Tập 1 Java, Chương 12” ,nó thực hiện gửi các đối tượng qua một kết nối mạng Điều này có nghĩa rằng chỉ có các thông tin trong bất kỳ lớp mà thực hiện giao diện
Serializable có thể được sao chép
Hình 5-7: Lấy sản phẩm đề xuất từ máy chủ
*Chú ý: Hình 5-7 có một biểu ngữ "Java Applet Window" Đây là kết quả của việc
chạy chương trình với một quản lý bảo mật Biểu ngữ cảnh báo này được cung cấp
để bảo vệ chống vi mã "phishing" (vi mã : 1 chương trình ứng dụng nhỏ thực hiện một nhiệm vụ cụ thể) Một vi mã chống đối có lẽ bật lên một cửa sổ, nhắc nhở điền mật khẩu hoặc số thẻ tín dụng, và sau đó gửi thông tin lại đến host của nó Để tắt
permission java.awt.AWTPermission
Trang 29"showWindowWithoutWarningBanner";
- Ghi chú : phish : (máy tính) sự lợi dụng sự không hiểu biết của người dùng
để đánh cắp thông tin cá nhân của họ,bằng cách mượn tên công ty(ngân hàng,công
customer không phải là đối tượng từ xa nên một sao chép đối tượng được thực hiện trên máy chủ Chương trình máy chủ gửi lại một danh sách mảng các sản phẩm.Danh sách mảng chứa các sản phẩm mà phù hợp với hồ sơ khách hàng, và
nó luôn luôn chứa một mục mà sẽ thỏa đáng bất cứ ai, cụ thể như một bản sao của
danh sách mảng được sao chép từ máy chủ trở lại cho máy con Như mô tả trong
“Tập 1 Java, chương 12”,cơ chế tuần tự hóa thực hiện sao chép tất cả các đối tượng được tham chiếu bên trong một đối tượng được sao chép Trong trường hợp của ta,
nó thực hiện một sao chép tất cả các mảng danh sách truy cập tốt Chúng ta thêm
người nhận sẽ lấy một bản sao của mảng danh sách,chứa đầy các đối tượng stub với các sản phẩm trên máy chủ (xem Hình 5-8)
Figure 5-8 Sao chép tham số cục bộ và trả về các đối tượng
Trang 30-Tổng kết, các đối tượng từ xa được truyền qua mạng như là các stub Các đối tượng không từ xa được sao chép Tất cả điều này là tự động và yêu cầu không
có người lập trình can thiệp
- Bất cứ khi nào đoạn mã gọi một phương phức từ xa, stub thực hiện một gói
có chứa các bản sao chép của tất cả các giá trị tham số và gửi nó tới máy chủ, sử dụng cơ chế tuần tự hóa đối tượng để sắp xếp có thứ tự các thông số.Máy chủ không sắp xếp thứ tự cho chúng Đương nhiên, tiến trình có thể khá là chậm khi các đối tượng tham số rất lớn
- Hãy nhìn vào các chương trình hoàn tất bên dưới Trước tiên, chúng ta có các giao diện cho các dịch vụ sản phẩm và nhà kho, như trong ví dụ 5-6 và 5-7
9 Gets the description of this product
10 @return the product description
10 Gets products that are good matches for a customer
11 @param c the customer to match
12 @return an array list of matching products
13 */
14 ArrayList<Product> find(Customer c) throws
RemoteException;
15 }
Trang 31- Ví dụ 5-8 bên dưới cho thấy việc thực hiện của dịch vụ sản phẩm Sản phẩm lưu trữ một bản mô tả gồm độ tuổi, giới tính được nhắm đến (nam, nữ, hoặc
cả hai), và sở thích phù hợp Lưu ý rằng lớp này thực hiện các phương thức
getdescription (lấy mô tả)trong giao diện Product, và nó cũng thực hiện một
dụ về phương thức cục bộ, phương thức đó có thể được được gọi chỉ từ chương
không phải là lớp từ xa hay các phương thức của nó có thể được thực thi từ xa Tuy nhiên, lớp này là tuần tự Do đó, các đối tượng của lớp này có thể được chuyển từ máy ảo đến vùng khác
- Ví dụ 5-10 và 5-11 bên dưới cho thấy giao diện và việc thực hiện của dịch
máy con để tìm các mục(sản phẩm) trong kho hàng
mà nó gửi đến máy chủ Như ta thấy, đối tượng đó không được thay đổi Máy chủ
không có hữu ích ngoại trừ việc chứng minh rằng đối tượng cục bộ được sao chép khi chúng được truyền như là các tham số
- Nó có thể cho nhiều stub con để thực hiện gọi đồng thời tới một đối tượng máy chủ, ngay cả khi một số phương thức thay đổi trạng thái của máy chủ Trong
WarehouseImpl vì nó hiểu được rằng phương thức add cục bộ và phươn thức find
từ xa được gọi một cách đồng thời Ví dụ 5-12 cho thấy chương trình máy chủ tạo
ra một đối tượng kho hàng và đăng ký nó với chương trình khởi động đăng ký dịch
vụ
Trang 32Chú ý: Hãy nhớ rằng bạn phải bắt đầu chương trình đăng ký và chương trình
máy chủ, và giữ cho cả hai đang chạy trước khi bạn bắt đầu máy con
- Ví dụ 5-13 cho thấy đoạn mã của máy con Khi người dùng nhấp nút
Submit, một đối tượng khách hàng mới được tạo ra và được truyền tới phương
phẩm của các sản phẩm được trả về trong danh sách mảng được thêm vào vùng
Đây không phải là một thiết kế tốt trong thực tiễn,bạn thường truyền các đối tượng nhỏ như mô tả sản phẩm bởi giá trị Tuy nhiên, chúng ta muốn chứng minh rằng một đối tượng từ xa sẽ tự động được thay thế bằng một stub trong suốt thời gian sắp xếp thứ tự
Tip: Nếu bạn khởi động máy chủ với
java -Djava.rmi.server.logCalls=true WarehouseServer &
sau đó máy chủ ký nhận tất cả phương thức từ xa gọi trên giao diện điều khiển của nó Hãy thử nó,ta sẽ có được một ấn tượng tốt đẹp của vận tải RMI
13 Constructs a product implementation
14 @param n the product name
Trang 3311 @param theAge the customer's age
12 @param theSex the customer's sex (MALE or FEMALE)
13 @param theHobbies the customer's hobbies
23 Gets the customer's age
24 @return the age
25 */
26 public int getAge() { return age; }
27
28 /**
29 Gets the customer's sex
30 @return MALE or FEMALE
31 */
32 public int getSex() { return sex; }
33
34 /**
35 Tests whether this customer has a particular hobby
36 @param aHobby the hobby to test
37 @return true if this customer has the hobby
38 */
39 public boolean hasHobby(String aHobby)
Trang 3440 {
41 if (aHobby == "") return true;
42 for (int i = 0; i < hobbies.length; i++)
43 if (hobbies[i].equals(aHobby)) return true;
60 String result = "Age: " + age + ", Sex: ";
61 if (sex == Product.MALE) result += "Male";
62 else if (sex == Product.FEMALE) result += "Female";
63 else result += "Male or Female";
70 private int age;
71 private int sex;
72 private String[] hobbies;
10 Gets products that are good matches for a customer
11 @param c the customer to match
Trang 3512 @return an array list of matching products
22 products = new ArrayList<ProductImpl>();
23 add(new ProductImpl("Core Java Book", 0, 200,
Trang 3652 // add all matching products
53 for (ProductImpl p : products)
54 {
55 if (p.match(c)) result.add(p);
56 }
57 // add the product that is a good match for
everyone, a copy of Core Java
71 private ArrayList<ProductImpl> products;
72 private ReadWriteLock rwlock = new
Trang 377 object, registers it with the naming service, and waits
8 for clients to invoke methods
17 WarehouseImpl w = new WarehouseImpl();
18 w.add(new ProductImpl("Blackwell Toaster",
Trang 3834 System.out.println("Waiting for invocations from clients ");
22 Properties props = new Properties();
23 String fileName = "WarehouseClient.properties";
30 Context namingContext = new InitialContext();
31 Warehouse centralWarehouse = (Warehouse)
namingContext.lookup(url);
Trang 3932 JFrame frame = new
64 female = new JRadioButton("Female", true);
65 male = new JRadioButton("Male", true);
66 ButtonGroup group = new ButtonGroup();
67 panel.add(female); group.add(female);
68 panel.add(male); group.add(male);
69
70 panel.add(new JLabel("Hobbies: "));
71 hobbies = new ArrayList<JCheckBox>();
72 for (String h : new String[] { "Gardening", "Beauty",
"Computers", "Household",
"Sports" })
Trang 4082 JPanel buttonPanel = new JPanel();
83 JButton submitButton = new JButton("Submit");