"สวัสดี! และอีกหนึ่งหัวข้อที่น่ายินดี: RMI RMIย่อมาจากRemote Method Invocationกล่าวอีกนัยหนึ่งRMI เป็นกลไกที่อนุญาตให้ออบเจกต์จากเครื่อง Java เครื่องหนึ่งเรียกเมธอดบนออบเจ็กต์จากเครื่อง Java อีกเครื่องหนึ่งแม้ว่าจะอยู่บนเครื่องอื่นก็ตาม คอมพิวเตอร์ในประเทศต่างๆ หรือคนละซีกโลก"

"ว้าว!
"ใช่ แต่ฉันจะพยายามให้ภาพรวมกับคุณเท่านั้น ด้วยสิ่งนี้ หากคุณเจาะลึกเกินไป คุณอาจสับสนกับความแตกต่างของวิธีการทำงาน"
"แต่ถ้าคุณไม่ทำอะไรให้สุดโต่ง RMI ไม่เพียงแต่เรียบง่ายเท่านั้น แต่ยังทำให้ชีวิตของโปรแกรมเมอร์ง่ายขึ้นอย่างมาก ด้วยเหตุนี้ เราขอแสดงความนับถืออย่างสุดซึ้ง"
"ดังนั้นเราจึงต้องการให้วัตถุหนึ่งในโปรแกรม Java เรียกใช้เมธอดบนวัตถุที่อยู่ในโปรแกรม Java อื่น โดยไม่คำนึงว่าโปรแกรมเหล่านี้จะทำงานอยู่ที่ใด"
"ลองพิจารณาตัวอย่างที่ง่ายที่สุด: เมื่อทั้งสองโปรแกรมทำงานบนคอมพิวเตอร์เครื่องเดียวกัน ในการอนุญาตให้โปรแกรมโต้ตอบผ่านอินเทอร์เน็ต คุณต้องกำหนดค่าการอนุญาตของ JVMแต่เราจะไม่พูดถึงเรื่องนั้นในวันนี้"
"ใน Java คุณสามารถเรียกใช้เมธอดของอินเตอร์เฟสจากระยะไกลเท่านั้น ไม่ใช่คลาส"
“งั้นเรามีสองโปรแกรม จะเรียกเมธอดของกันและกันได้ยังไง”
"ลองพิจารณาสถานการณ์ที่โปรแกรมหนึ่งมีวัตถุอยู่ และโปรแกรมที่สองต้องการเรียกใช้เมธอดบนวัตถุนั้น ให้เรียกโปรแกรมแรกว่าเซิร์ฟเวอร์ และโปรแกรมที่สอง - ไคลเอ็นต์ "
"ก่อนอื่น ฉันจะให้ตัวอย่างโค้ด จากนั้นเราจะวิเคราะห์โค้ดนั้น"
“แล้วโปรแกรมของเราจะทำยังไง”
"อืม เพื่อความง่าย โปรแกรมจะมีเมธอดหนึ่งที่กลับค่าสตริงที่ส่งผ่านไป"
"ง่ายพอ"
"ดี งั้นเริ่มกันเลย:"
"อันดับแรก เราต้องมีอินเทอร์เฟซที่ตอบสนองความต้องการของเรา:"
interface Reverse extends Remote
{
public String reverse(String str) throws RemoteException;
}
"ฉันสร้างอินเทอร์เฟซ Reverse และเพิ่มอินเทอร์เฟซตัวทำเครื่องหมายระยะไกล เช่นเดียวกับ RemoteException ข้อผิดพลาดที่ไม่คาดคิดอาจเกิดขึ้นเมื่อเมธอดนี้ถูกเรียกใช้ หากเกิดข้อผิดพลาดนี้ ข้อยกเว้นนี้จะหายไป"
"ตอนนี้เราต้องเขียนคลาสเซิร์ฟเวอร์ที่ใช้อินเทอร์เฟซนี้:"
class ReverseImpl implements Reverse
{
public String reverse(String str) throws RemoteException
{
return new StringBuffer(str).reverse().toString();
}
}
"เข้าใจแล้ว เราจะย้อนกลับสตริงด้วยวิธีนี้"
"ใช่."
"ตอนนี้เราต้องทำให้วัตถุนี้สามารถเรียกได้จากโปรแกรมอื่น นี่คือวิธีการ:"
public static final String UNIC_BINDING_NAME = "server.reverse";
public static void main(String[] args) throws Exception
{
// Create an object to be accessible remotely.
final ReverseImpl service = new ReverseImpl();
// Create a registry of shared objects.
final Registry registry = LocateRegistry.createRegistry(2099);
// Create a stub for receiving remote calls.
Remote stub = UnicastRemoteObject.exportObject(service, 0);
// Register the stub in the registry.
registry.bind(UNIC_BINDING_NAME, stub);
// Put the main thread to sleep, or else the program will exit.
Thread.sleep(Integer.MAX_VALUE);
}
“ฉันจะอธิบายทีละบรรทัด”
" ในบรรทัดที่ 1เราจัดเก็บชื่อเฉพาะ (ซึ่งเราสร้างขึ้น) สำหรับวัตถุระยะไกลของเรา (วัตถุที่เข้าถึงได้จากระยะไกล) ในตัวแปรUNIC_BINDING_NAME หากโปรแกรมทำให้วัตถุหลายชิ้นสามารถเข้าถึงได้ แต่ละวัตถุจะต้องมีชื่อเฉพาะของตัวเอง ของเรา ชื่อเฉพาะของวัตถุคือ 'server.reverse'"
" ในบรรทัดที่ 6เราสร้าง วัตถุ ReverseImplที่จะสามารถเข้าถึงได้จากระยะไกล วิธีการของมันจะถูกเรียกใช้"
" ในบรรทัดที่ 9เราสร้างวัตถุพิเศษที่เรียกว่ารีจิสตรี เราจำเป็นต้องใช้มันเพื่อลงทะเบียนวัตถุที่เราแบ่งปัน JVM จะโต้ตอบกับพวกเขาในภายหลัง 2099 เป็นพอร์ต (หมายเลขเฉพาะที่โปรแกรมอื่นสามารถใช้เพื่อเข้าถึงของเรา การลงทะเบียนวัตถุ)"
"กล่าวอีกนัยหนึ่ง ในการเข้าถึงวัตถุ คุณจำเป็นต้องทราบหมายเลขเฉพาะของวัตถุ (พอร์ต) และชื่อเฉพาะของวัตถุ และมีอินเทอร์เฟซเดียวกันกับที่วัตถุระยะไกลนำมาใช้"
"เข้าใจแล้ว บางอย่างเช่น: โทรทางโทรศัพท์ (ต้องการหมายเลข) แล้วขอบิล (ชื่อของวัตถุ)"
"ใช่ ตอนนี้ไปกันต่อเถอะ"
" ในบรรทัดที่ 11 เราสร้าง stub โดย stub เป็นวัตถุพิเศษที่รับข้อมูลเกี่ยวกับการโทรระยะไกล แกะมันออก ยกเลิกการซีเรียลไลซ์อาร์กิวเมนต์เมธอด และเรียกใช้เมธอดที่ต้องการ จากนั้นจะทำให้เป็นอนุกรมผลลัพธ์หรือข้อยกเว้น ถ้ามี และส่งทั้งหมดกลับไปยังผู้โทร"
"ฉันเข้าใจแล้ว เกือบแล้ว คุณบอกว่ามัน 'ดีซีเรียลไลซ์อาร์กิวเมนต์ของเมธอด' นั่นหมายความว่าอาร์กิวเมนต์ของเมธอดรีโมตจะต้องทำให้เป็นอนุกรมได้"
"ใช่ คุณจะส่งผ่านเครือข่ายด้วยวิธีอื่นได้อย่างไร จริงอยู่ มีข้อยกเว้น เช่น วัตถุที่ส่งผ่านโดยการอ้างอิง แต่เราจะไม่พูดถึงสิ่งเหล่านี้ในวันนี้"
"เราจะพูดแบบนี้: คุณไม่สามารถส่งวัตถุที่ไม่สามารถจัดลำดับได้ แต่ถ้าคุณต้องการจริงๆ คุณก็ทำได้ แต่มันเจ็บปวด คุณรู้ไหม"
"ตกลง."
"งั้นก็ไปกันต่อ"
" ในบรรทัดที่ 13เราลงทะเบียนต้นขั้วของวัตถุภายใต้ชื่อเฉพาะในรีจิสทรี"
" ในบรรทัดที่ 16เราทำให้เธรดหลักเข้าสู่โหมดสลีป การโทรระยะไกลทั้งหมดจะถูกประมวลผลบนเธรดที่แยกจากกัน สิ่งสำคัญคือโปรแกรมกำลังทำงานอยู่ ดังนั้นเราจึงทำให้เธรดหลักเข้าสู่โหมดสลีปที่นี่ แค่นั้นแหละ"
"ตกลง."
"เยี่ยมมาก นี่คือตัวอย่างของลูกค้า:"
public static final String UNIC_BINDING_NAME = "server.reverse";
public static void main(String[] args) throws Exception
{
// Create a registry of shared objects
final Registry registry = LocateRegistry.createRegistry(2099);
// Get the object (actually, this is a proxy object)
Reverse service = (Reverse) registry.lookup(UNIC_BINDING_NAME);
// Call the remote method
String result = service.reverse("Home sweet home.");
}
"ฉันจะอธิบายรหัสนี้ทีละบรรทัด:"
" บรรทัดที่ 1 เป็น ชื่อเฉพาะ ของวัตถุระยะไกลซึ่งจะต้องเหมือนกันทั้งบนไคลเอ็นต์และเซิร์ฟเวอร์"
" ในบรรทัดที่ 6 เราสร้าง « รีจีสทรีของวัตถุระยะไกล » พอร์ต (2099) จะต้องเหมือนกับพอร์ตของรีจิสตรีสำหรับแอปพลิเคชันเซิร์ฟเวอร์"
" ในบรรทัดที่ 9เราได้รับวัตถุจากรีจิสทรี วัตถุที่ส่งคืนเป็นวัตถุพร็อกซีและถูกแปลงเป็นอินเทอร์เฟซ อินเทอร์เฟซต้องสืบทอดอินเทอร์เฟซตัวทำเครื่องหมายระยะไกล"
" ในบรรทัดที่ 12เราเรียกเมธอดของอินเตอร์เฟสราวกับว่าอ็อบเจกต์ถูกสร้างขึ้นภายในโปรแกรมเดียวกัน ไม่มีความแตกต่าง"
"เจ๋ง! ตอนนี้ฉันสามารถเขียนแอปพลิเคชันแบบกระจาย หรือเกมเช่น Battleship สำหรับ Android"
"ไม่กล้าหรอก Amigo! ระบบปฏิบัติการ Android ถูกแบนในศตวรรษที่ 27 หลังจากความพยายามครั้งที่สามที่จะยึดครองโลก หุ่นยนต์ไม่สามารถเข้าถึงมันได้ ไม่มีทางที่จะดึงคุณออกจากมันได้ คุณจะวิ่งไปรอบๆ ตะโกนว่า «ฆ่ามนุษย์ให้หมด!»"
"อืม ตกลง แต่ฉันยังคงต้องถามดิเอโก คุณไม่มีทางรู้ บางทีเขาอาจมีบางอย่างที่น่าสนใจที่จะพูดเกี่ยวกับเรื่องนี้"
“งั้นไปถามเขาได้เลย โอเค พรุ่งนี้ค่อยว่ากัน”
"ลาก่อน ริชิ ขอบคุณสำหรับบทเรียนที่น่าสนใจ"
GO TO FULL VERSION