سيكون الأمر أسهل إذا تم تنفيذ جميع المكونات على نفس مساحة الكومة من نفس جهاز Java الظاهري على نفس الكمبيوتر، ولكن في الممارسة العملية، غالبًا ما لا نواجه مثل هذا الموقف إذا كان العميل مجرد جهاز يمكنه تنفيذ Java يفعل؟ ماذا لو لأسباب أمنية فقط البرامج الموجودة على الخادم يمكنها الوصول إلى قاعدة البيانات؟
نحن نعلم أنه في معظم الحالات، تحدث استدعاءات الأساليب بين كائنين في نفس الكومة. ماذا لو كنت تريد استدعاء الأساليب على كائنات على أجهزة مختلفة؟
عادة، نحصل على المعلومات من كمبيوتر إلى كمبيوتر آخر من خلال دفق الإدخال والإخراج للمقبس، ونفتح اتصال المقبس للكمبيوتر الآخر، ثم نحصل على دفق الإخراج لكتابة البيانات، ولكن إذا أردنا الاتصال بجهاز كمبيوتر آخر الكمبيوتر، ما هي طرق الكائنات الموجودة على جهاز Java ظاهري آخر؟ بالطبع، يمكننا تحديد وتصميم بروتوكول الاتصال بأنفسنا للاتصال به، ثم إرسال نتائج التنفيذ مرة أخرى من خلال المقبس، ويمكن أن يكون ذلك أيضًا مثل طرق الاتصال على الجهاز المحلي، أي إذا أردنا استدعاء كائنات بعيدة (مثل كأكوام أخرى) )، ولكن يجب أن تكون مثل المكالمة العادية.
هذا ما تقدمه لنا RMI.
تصميم مكالمات الإجراء عن بعد
هناك 4 أشياء يجب إنشاؤها: الخادم والعميل والمرافق المساعدة للخادم والمرافق المساعدة للعميل.
1. إنشاء تطبيقات العميل والخادم، تطبيق الخادم هو خدمة عن بعد، وهو كائن له طرق سيتصل بها العميل.
2. قم بإنشاء مساعدين من جانب العميل والخادم، حيث سيتعاملون مع جميع تفاصيل الإدخال/الإخراج الأساسية للشبكة الخاصة بالعميل والخادم، مما يجعل العميل والبرنامج يبدوان وكأنهما يعالجان المكالمات المحلية.
مهام المرافق المساعدة هي كائنات تقوم بالفعل بإجراء الاتصال، فهي تجعل العميل يشعر كما لو أنه يستدعي كائنًا محليًا. يبدو أن كائن العميل يستدعي طريقة بعيدة، ولكنه في الواقع يستدعي طريقة فقط الوكيل الذي يتعامل مع تفاصيل المقبس والدفق محليًا من جانب الخادم، ستقوم المرافق المساعدة للخادم بتوصيل الطلبات من مرافق العميل من خلال المقبس، وتحليل المعلومات المجمعة، ثم الاتصال بالخدمة الحقيقية، لذلك بالنسبة لكائن الخدمة، هذا هو ما بعد. باستدعاء المنشأة المساعدة من الخدمة المحلية، فإنها تحصل على قيمة الإرجاع، وتغلفها وترسلها مرة أخرى (عبر دفق إخراج المقبس) إلى المنشأة المساعدة للعميل، وتقوم بتفريغ المعلومات ونقلها إلى كائن العميل.
عملية استدعاء الأسلوب
1. يستدعي كائن العميل doBigThing() على كائن المنشأة المساعدة
2. تقوم المرافق المساعدة للعميل بتعبئة معلومات المكالمة وإرسالها إلى المرافق المساعدة للخادم عبر الشبكة.
3. تقوم الأداة المساعدة من جانب الخادم بفك تشفير المعلومات من الأداة المساعدة من جانب العميل وتستخدمها للاتصال بالخدمة الحقيقية.
الرسم البياني الذي يصف هذه العملية هو كما يلي:
يوفر JavaRMI كائنات مساعدة من جانب العميل والخادم
في Java، ساعدنا RMI في إنشاء مرافق مساعدة من جانب العميل والخادم، كما يعرف أيضًا كيفية جعل المرافق المساعدة من جانب العميل تبدو وكأنها خدمات حقيقية. وبعبارة أخرى، يعرف RMI كيفية توفير نفس الأساليب لمكالمات العملاء .
بالإضافة إلى ذلك، توفر RMI كل البنية التحتية اللازمة للتنفيذ، بما في ذلك الاستعلام عن الخدمة والمرافق المساعدة التي تسمح للعملاء بالعثور على العملاء والحصول عليهم (وكلاء الخدمة الحقيقيين).
عند استخدام RMI، ليست هناك حاجة لكتابة أي شبكة أو برامج إدخال/إخراج. إن استدعاء العميل للأسلوب البعيد هو نفس استدعاء الأسلوب على نفس جهاز Java الظاهري.
تختلف المكالمات العامة قليلاً عن مكالمات RMI، على الرغم من أن استدعاء الطريقة هذا يبدو محليًا للعميل، إلا أن المنشأة المساعدة للعميل ستجري المكالمة عبر الشبكة في النهاية، وستبدأ كمكالمة محلية. وسيقوم الوكيل بتحويلها إلى جهاز بعيد. تعتمد كيفية إرسال المعلومات الوسيطة من جهاز Java الظاهري إلى جهاز Java الظاهري على البروتوكول الذي يستخدمه كائن المنشأة المساعدة.
عند استخدام RMI، يجب عليك تحديد البروتوكول: JRMP أو IIOP هو البروتوكول الأصلي لـ RMI وهو مصمم للمكالمات عن بعد بين Java. بالنسبة للكائنات أو الأنواع الأخرى من الأساليب البعيدة، عادةً ما يكون CORBA أكثر إزعاجًا من RMI، لأنه إذا لم يكن كلا الطرفين Java، فستحدث مجموعة من عمليات الترجمة والمحادثة الرهيبة.
نحن نهتم فقط بعمليات Java-to-Java، لذلك سنستخدم RMI بسيطًا إلى حد ما.
في RMI، تسمى المرافق المساعدة من جانب العميل بذرة، وتسمى المرافق المساعدة من جانب الخادم الهياكل العظمية.
كيفية إنشاء خدمة عن بعد
1. إنشاء واجهة عن بعد
تحدد الواجهة البعيدة الطرق التي يمكن للعميل الاتصال بها عن بعد، وهي فئة متعددة الأشكال كخدمة.
2. تنفيذ الواجهة البعيدة
هذه هي فئة التنفيذ الفعلية التي تنفذ الأساليب المحددة على الواجهة، وهي الكائن الذي سيتصل به العميل.
3. استخدم rmic لإنشاء كعب الروتين والهيكل العظمي
لدى كل من العميل والخادم مساعدين. لا نحتاج إلى إنشاء هذه الفئات أو إنشاء الكود المصدري لهذه الفئات. سيتم التعامل مع هذا تلقائيًا عند تنفيذ أداة rmic المرفقة بـ JDK.
4. ابدأ تسجيل RMI (تسجيل RMI)
يشبه rmiregistry دليل الهاتف، وسيحصل المستخدم على الوكيل (الكائن المساعد/كعب الروتين الخاص بالعميل) من هنا
5. ابدأ الخدمة عن بعد
يجب أن يبدأ كائن الخدمة في التنفيذ، وستبدأ الفئة التي تنفذ الخدمة في مثيل الخدمة وتسجيله في RMIRegistry.
رمز الخادم
تعريف الواجهة
/**
*
*MyRemote.java
*
* الوظيفة: المهام
* اسم الفئة: MyRemote.java
*
* الإصدار. حامل الشخصية المحدث والمحتوى الجديد.
*─────────────────────────────────── ────
* V1.00 19/3/2013 الإصدار الأول من الوحدة Su Ruo
*
* حقوق الطبع والنشر (ج) 2013 لشركة دينيسيت جميع الحقوق محفوظة.
*
* البريد الإلكتروني:<a href="mailto:[email protected]">أرسل بريدًا إلكترونيًا</a>
*
*
* جهاز التحكم عن بعد عبارة عن واجهة مميزة، مما يعني عدم وجود طرق، إلا أن له معنى خاصًا بالنسبة لـ RMI، لذا يجب اتباع هذه القاعدة.
* لاحظ أنه يتم استخدام الامتدادات هنا، ويمكن أن ترث الواجهات واجهات أخرى.
*
*/
الواجهة العامة MyRemote تمتد عن بعد {
/**
* تحدد الواجهة البعيدة الطرق التي يمكن للعميل الاتصال بها عن بعد، وهي فئة متعددة الأشكال كخدمة
* قم بتعبئة كعب الروتين الذي ينفذ هذه الواجهة، ولأن هذا كعب الروتين سيقوم بعمل الشبكة والإدخال/الإخراج، فقد تحدث أشياء مختلفة
* المشكلة، يتعامل العميل مع الاستثناءات أو يعلن عنها للتعرف على هذا النوع من المخاطر. إذا أعلنت الطريقة عن استثناء في الواجهة، فاستدعاء الطريقة
* يجب على كافة الإجراءات التعامل مع هذا الاستثناء أو إعادة تعريفه.
*
* يجب أن تكون المعلمات وقيم الإرجاع للطرق البعيدة بدائية أو قابلة للتسلسل
* يتم إرسال الحزمة عبر الشبكة، وعند اكتمالها من خلال التسلسل، تكون قيمة الإرجاع هي نفسها، لذلك في حالة استخدام نوع مخصص
*، يجب أن تكون متسلسلة
* @يعود
* @throws RemoteException
* يجب أن تعلن جميع الطرق في الواجهة عن RemoteException
*/
السلسلة العامة sayHello() تطرح RemoteException؛
}
/**
*
*MyRemoteImpl.java
*
* الوظيفة: المهام
* اسم الفئة: MyRemoteImpl.java
*
* الإصدار. حامل الشخصية المحدث والمحتوى الجديد.
*─────────────────────────────────── ────
* V1.00 19/3/2013 الإصدار الأول من الوحدة Su Ruo
*
* حقوق الطبع والنشر (ج) 2013 لشركة دينيسيت جميع الحقوق محفوظة.
*
* البريد الإلكتروني:<a href="mailto:[email protected]">أرسل بريدًا إلكترونيًا</a>
*
* لكي يصبح كائن خدمة عن بعد، يجب أن يكون للكائن وظائف مرتبطة عن بعد. إن أبسط طريقة هي وراثة UnicastRemoteObject
* (من java.rmi.server) للسماح لهذه الفئة الرئيسية بالتعامل مع العمل
*
*/
الطبقة العامة MyRemoteImpl تمتد UnicastRemoteObject تنفذ MyRemote{
/**
* يعلن منشئ الفئة الأصل عن استثناء، لذلك يجب عليك كتابة المنشئ لأنه يعني أن المنشئ الخاص بك سوف يستدعي كود برنامج محفوف بالمخاطر
*
* لدى UnicastRemoteObject مشكلة صغيرة، حيث يقوم منشئه بطرح RemoteException والطريقة الوحيدة للتعامل معها هي
* قم بتعريف مُنشئ للتنفيذ الخاص بك بحيث يكون هناك مكان للإعلان عن RemoteException عند تهيئة الفصل، وهو الفصل الأصلي
* سيتم بالتأكيد استدعاء المُنشئ إذا قام مُنشئ الفئة الأصلية بطرح استثناء، فإن المُنشئ المخصص الذي يجب أن نعلن عنه أيضًا سيطرح استثناءً.
* @throws RemoteException
*/
MyRemoteImpl () المحمي يطرح RemoteException {
}
/**
* تنفيذ كافة أساليب الواجهة الصادرة، ولكن لا تحتاج إلى إعلان RemoteException
*/
@تجاوز
السلسلة العامة sayHello(){
إرجاع "يقول الخادم، RMI مرحبًا بالعالم!"؛
}
public static void main(String[] args) {
يحاول {
/**
* لدينا بالفعل خدمة عن بعد، ويجب أن نسمح للمستخدمين عن بعد بالوصول إليها، ويمكن القيام بذلك عن طريق تهيئتها وإضافتها إلى سجل RMI.
* (يجب أن يكون قيد التشغيل، وإلا فسوف يفشل هذا البرنامج). عند تسجيل كائن، سيقوم نظام RMI بإضافة كعب الروتين إلى السجل،
* لأن هذا هو ما يحتاجه العميل، استخدم rebind() لـ java.rmi.Naming لتسجيل الخدمة
*/
خدمة MyRemote = new MyRemoteImpl();
/**
* أنشئ كائنًا بعيدًا، ثم استخدم Naming.rebind() الثابت لإنشاء اقتران. سيتم توفير الاسم المسجل لاستعلام العميل
*/
Naming.rebind("Remote Hello World"، خدمة)؛
} قبض (الاستثناء ه) {
printStackTrace();
}
}
}
إكسيك الفراغ العام () {
يحاول {
/**
* يجب على العميل الحصول على كائن كعب الروتين لأنه يجب على العميل الاتصال بطريقته، وهذا يعتمد على سجل RMI، وسيقوم العميل بالاستعلام عن الهاتف
* ابحث في نفس الدليل للعثور على الخدمات ذات الأسماء المطابقة.
* يستعلم العميل عن RMIRegistry ويعيد كائن كعب الروتين
* Naming.lookup("rmi://127.0.0.1/Remote Hello World");
* وصف المعلمة
* rmi://127.0.0.1/Remote مرحبا بالعالم
* 127.0.0.1 يمثل اسم المضيف أو عنوان IP للمضيف
* يجب أن يكون Remote Hello World هو نفس الاسم المسجل
*
*/
خدمة MyRemote = (MyRemote)Naming.lookup("rmi://127.0.0.1/Remote Hello World");
String tmp =service.sayHello();
System.out.println(tmp);
} قبض (الاستثناء ه) {
printStackTrace();
}
}
public static void main(String[] args) {
new MyRemoteClient().exec();
}
}
ستقوم أداة rmic التي تأتي مع JDK بإنشاء فئتين، كعب الروتين والهيكل العظمي، بناءً على تنفيذ الخدمة وستضيف _Stub أو _Skeleton بعد اسم التنفيذ عن بعد وفقًا لقواعد التسمية. لدى rmic عدة خيارات، بما في ذلك عدم إنشاء الهياكل العظمية، أو مراقبة الكود المصدري للفئات التي تم إنشاؤها، أو استخدام IIOP كبروتوكول اتصال. سيتم وضع الفئات التي تم إنشاؤها في الدليل الحالي. تذكر أن rmic يجب أن يكون قادرًا على العثور على الفئات المنفذة. لذلك، قد تحتاج إلى تنفيذ rmic من الدليل الذي يوجد به التنفيذ (في الممارسة العملية، قد تحتاج إلى مراعاة بنية دليل الحزمة والاسم الكامل، من أجل البساطة، لا يتم استخدام الحزمة هنا)
اتصل بسطر الأوامر لبدء rmiregistry وتأكد من تشغيله من دليل يمكنه الوصول إلى الفصل الدراسي. أسهل طريقة هي تشغيله من دليل الفصل.
لقطة الشاشة قيد التشغيل هي كما يلي
يلاحظ:
يستخدم العميل الواجهة لاستدعاء الطريقة على كعب الروتين. يجب أن يحتوي جهاز Java الظاهري الخاص بالعميل على فئة كعب الروتين، لكن العميل لن يشير إلى فئة كعب الروتين في رمز البرنامج.
يجب أن يحتوي الخادم على كعب روتين وهياكل عظمية، بالإضافة إلى واجهات الخدمة والبعيدة. ويتطلب ذلك فئة كعب الروتين لأنه سيتم استبدال كعب الروتين بالخدمة الحقيقية المتصلة بـ RMIRegistry.
الأخطاء الشائعة عند استخدام RMI:
1. نسيت بدء تسجيل rmiregistry قبل بدء الخدمة عن بعد (يجب بدء تسجيل rmiregistry قبل استخدام Naming.rebind() لتسجيل الخدمة)
2. نسيت جعل المعلمات وأنواع الإرجاع قابلة للتسلسل (لن يتم اكتشافها أثناء التجميع وسيتم اكتشافها فقط أثناء التنفيذ)
3. ننسى تسليم فئة كعب الروتين إلى العميل
يعد RMI مناسبًا جدًا لكتابة الخدمات عن بعد وتشغيلها، لكننا لن نستخدم RMI بمفردها لتنفيذ خدمات موقع الويب. بالنسبة للتطبيقات واسعة النطاق على مستوى المؤسسة، نحتاج إلى وظائف أكثر وأفضل، مثل إدارة المعاملات والمعالجة المتزامنة على نطاق واسع. والأمن وإدارة قواعد البيانات وما إلى ذلك. وهذا يتطلب استخدام EnterpriseApplicationServer.
يشتمل خادم JavaEE على خادم ويب وخادم Enterprise JavaBeans (EJB). يعمل خادم EJB بين مكالمات RMI وطبقة الخدمة.
تطبيق RMI في JINI
يستخدم Jini أيضًا RMI (على الرغم من إمكانية استخدام بروتوكولات أخرى أيضًا)، إلا أنه يحتوي على العديد من الوظائف الرئيسية.
1. الاكتشاف التكيفي
2. شبكات الشفاء الذاتي
يجب أن يحصل عميل RMI أولاً على عنوان واسم الخدمة البعيدة، ويجب أن يحتوي رمز برنامج الاستعلام الخاص بالعميل على عنوان IP أو اسم المضيف للخدمة البعيدة (نظرًا لوجود RMIRegistry عليه) والاسم المسجل بواسطة الخدمة.
ولكن عند استخدام JINI، يحتاج المستخدمون إلى معرفة شيء واحد فقط، وهو الواجهة التي تنفذها الخدمة.
تستخدم Jini خدمة البحث، وهي أقوى وأكثر قدرة على التكيف من RMIRegistry، لأن Jini ستعلن تلقائيًا على الشبكة عندما تصبح خدمة الاستعلام عبر الإنترنت، وسوف تستخدم تقنية البث المتعدد IP لإرسال المعلومات إلى الشبكة بأكملها، إذا كان العميل كذلك يأتي عبر الإنترنت بعد بث خدمة الاستعلام، ويمكن للعميل أيضًا إرسال رسائل إلى الشبكة بأكملها للاستعلام.
عندما تصبح الخدمة متصلة بالإنترنت، ستستكشف خدمة استعلام JINI على الشبكة ديناميكيًا وتقدم طلبًا للتسجيل، عند التسجيل، سترسل الخدمة كائنًا متسلسلًا إلى خدمة الاستعلام برنامج تشغيل جهاز الشبكة، أو حتى الخدمة نفسها التي يمكن تنفيذها على العميل، وما يتم تسجيله هو الواجهة المنفذة.
كيف يعمل الاستكشاف التكيفي
1. تبدأ خدمة الاستعلام Jini على الشبكة وتستخدم تقنية البث المتعدد IP للترويج لنفسها
2. ستسعى خدمة Jini الأخرى التي تم تشغيلها إلى التسجيل في خدمة الاستعلام التي تم تشغيلها حديثًا، حيث تقوم بتسجيل الوظيفة بدلاً من الاسم، أي الواجهة المنفذة، ثم ترسل الكائن المتسلسل إلى خدمة الاستعلام.
3. يرغب عملاء الإنترنت في الحصول على شيء ما لتنفيذ الحاسبة العلمية، لكنهم لا يعرفون مكان العثور عليه، لذلك يطلبون خدمة الاستعلام
4. خدمة الاستعلام تستجيب لنتائج الاستعلام
تشغيل شبكة الشفاء الذاتي
1. تتطلب خدمة Jini معينة التسجيل، وستمنح خدمة الاستعلام عقد إيجار، ويجب على الخدمات المسجلة حديثًا تجديد عقد الإيجار بانتظام. وإلا ستفترض خدمة الاستعلام أن الخدمة غير متصلة بالإنترنت وستسعى جاهدة لتقديم خدمة استعلام دقيقة استكمال حالة شبكة الخدمة المتاحة.
2. الخدمة غير متصلة بالإنترنت بسبب إيقاف التشغيل، لذلك لا يتم تحديث عقد الإيجار ويتم بدء تشغيل خدمة الاستعلام.