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

อาร์เอ็มไอ - 1

"ว้าว!

"ใช่ แต่ฉันจะพยายามให้ภาพรวมกับคุณเท่านั้น ด้วยสิ่งนี้ หากคุณเจาะลึกเกินไป คุณอาจสับสนกับความแตกต่างของวิธีการทำงาน"

"แต่ถ้าคุณไม่ทำอะไรให้สุดโต่ง 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 หลังจากความพยายามครั้งที่สามที่จะยึดครองโลก หุ่นยนต์ไม่สามารถเข้าถึงมันได้ ไม่มีทางที่จะดึงคุณออกจากมันได้ คุณจะวิ่งไปรอบๆ ตะโกนว่า «ฆ่ามนุษย์ให้หมด!»"

"อืม ตกลง แต่ฉันยังคงต้องถามดิเอโก คุณไม่มีทางรู้ บางทีเขาอาจมีบางอย่างที่น่าสนใจที่จะพูดเกี่ยวกับเรื่องนี้"

“งั้นไปถามเขาได้เลย โอเค พรุ่งนี้ค่อยว่ากัน”

"ลาก่อน ริชิ ขอบคุณสำหรับบทเรียนที่น่าสนใจ"