Javaالكلاس URLConnection
في جافا
- مقدمة
- كونستركتورات الكلاس
URLConnection
- دوال الكلاس
URLConnection
- أمثلة شاملة
مقدمة
الكلاس URLConnection
عبارة عن كلاس مجرّد ( Abstract Class ) و هو يستخدم للقراءة و الكتابة في الملف الذي يشير له كائن الـ URL
بالإضافة إلى أنه يمكن من خلاله معرفة و تحديد كافة المعلومات المتعلقة بإجراء الإتصال مع الملف.
فمثلاً يتيح لنا معرفة آخر مرة تم فيها تحديث الملف, تاريخ صلاحية الملف, إسم الكلاس المناسب لإرسال المعلومات منه و استقبالها فيه إلخ..
بناؤه
public abstract class URLConnection extends Object
حقول الملف ( File Header Fields )
أي ملف موجود في أي موقع, يمكن وضع معلومات خاصة فيه لا يراها المستخدم العادي, لكنها تكون مهمة جداً للبرنامج أو للسيرفر الذي يملك هذا الملف.
هذه المعلومات تفيد في عملية تحديث محتوى الملف, صلاحيات التعامل معه, نوعه, الترميز المتبع فيه إلخ..
جميع هذه المعلومات مع بعضها تسمى حقول الملف.
سنتعرف لاحقاً على دوال مصممة خصيصياً لإضافة حقول جديدة تحدد طريقة تعامل البرنامج مع الملف.
التعامل مع الملفات عن بعد
للوصول إلى الملفات عن بعد سواء لقراءة محتواها أو التعديل عليها, عليك اتباع الخطوات التالية:
- إنشاء كائن من الكلاس
URL
يمثل رابط لملف موجود في موقع معين. - إستدعاء الدالة
openConnection()
و التي ترجع كائن نوعهURLConnection
يسمح لنا بالتعامل مع هذا الملف. - معرفة البروتوكول المستخدم في إجراء عملية الإتصال.
- تحويل كائن الـ
URLConnection
إلى كائن من إحدى الكلاسات التي ترث منه يكون مخصص للتعامل مع البروتوكول المستخدم في عملية الإتصال.
تحويل نوع كائن الـ URLConnection
الكلاس URLConnection
عبارة عن كلاس مجرّد تم تصميمه لإنشاء إتصال مع الملف الذي يشير إليه كائن الـ URL
مهما كان البروتوكول المستخدم في عملية الإتصال.
في حال أردت أن تتعامل مع هذا الملف, سيكون عليك تحويل نوع كائن الـ URLConnection
لنوع يلائم البروتوكول المستخدم لإجراء هذا الإتصال.
إذاً نوع البروتوكول المستخدم لإجراء الإتصال هو الذي يحدد النوع الذي يجب تحويل كائن الـ URLConnection
إليه, أمثلة:
- في حال كان البروتوكول
http
هو المستخدم في إجراء الإتصال, سيكون عليك تحويل نوع الكائن إلى النوعHttpURLConnection
. - في حال كان البروتوكول
https
هو المستخدم في إجراء الإتصال, سيكون عليك تحويل نوع الكائن إلى النوعHttpsURLConnection
. - في حال كان البروتوكول
ftp
هو المستخدم في إجراء الإتصال, سيكون عليك تحويل نوع الكائن إلى النوعFtpURLConnection
. - في حال كان البروتوكول
jar
هو المستخدم في إجراء الإتصال, سيكون عليك تحويل نوع الكائن إلى النوعJarURLConnection
إلخ..
كونستركتورات الكلاس URLConnection
الكلاس URLConnection
يملك الكونستركتور التالي فقط.
الكونستركتور مع تعريفه | |
---|---|
1 | protected URLConnection(URL url)
ينشئ كائن نوعه URLConnection يمثل كافة المعلومات المتعلقة بالملف الذي يشير له كائن الـ URL , أي يمثل صلة الوصل بين البرنامج و الملف الذي يشير له كائن الـ URL كـ Argument.بما أنه معرف كـ protected فهذا يعني أنه لا يمكن إستخدامه إلا في حال قمنا بإنشاء كلاس يرث منه و يفعل Override للدالة connect() الموجودة فيه.ملاحظة: لست بحاجة إلى إستخدام هذا الكونستركتور لأنك لن تقوم ببناء كلاس خاص للتعامل مع الشبكات. |
دوال الكلاس URLConnection
الجدول التالي يحتوي على دوال الكلاس URLConnection
.
الدالة مع تعريفها | |
---|---|
1 | public String getContent()
ترجع كائن يمثل إسم الكلاس الذي يجب استخدامه للتعامل مع محتوى الملف الذي يشير إليه كائن الـ URLConnection .في حال حدث خطأ بسبب الملف يتم رمي الإستثناء IOException و في حال كان البروتوكول المستخدم غير ملائم للتعامل مع الملف, يتم رمي الإستثناء UnknownServiceException. |
2 | public String getContentEncoding()
ترجع نص يمثل قيمة الحقل content-encoding في حال تم تحديدها في كائن الـ URLConnection .و ترجع null في حال كانت قيمته غير معروفة.معلومة: هذا الحقل يحدد الطريقة التي سيتم فيها تجزيء الملف عند إرساله إلى الجهة المطلوبة, و هو عبارة عن إسم الترميز المستخدم من قبل البروتوكول المعنمد عليه للتعامل مع هذا الملف. |
3 | public long getContentLengthLong()
ترجع نص يمثل قيمة الحقل content-encoding في حال تم تحديدها في كائن الـ URLConnection .و ترجع 1- في حال كانت غير محددة. معلومة: هذا الحقل يمثل حجم البيانات الأساسية المتعلقة بهذا الإتصال في حال قمت بتحديده, أي عدد الأحرف المتوقع إستقبالها. طبعاً لا ضرورة لتحديدها لأنه سيقوم بذلك بشكل تلقائي في حال لم تفعل ذلك. |
4 | public String getContentType()
ترجع نص يمثل قيمة الحقل Content-Type و هو عبارة نوع الملف الذي يشير إليه كائن الـ URLConnection .و ترجع null في حال كان النوع غير معروف. |
5 | public int getDate()
ترجع قيمة الحقل date , و هو عبارة عن رقم يمثل التاريخ و الوقت الذي قام فيه السيرفر بإرسال الملف الذي يشير إليه كائن الـ URLConnection .الرقم الذي ترجعه عبارة عن عدد الـ milliseconds الموجودة إعتباراً من التاريخ 1/1/1970 00:00:00 GMT .ترجع 0 في حال كان الوقت غير معروف. |
6 | public int getLastModified()
ترجع قيمة الحقل last-modified في حال كانت مذكورة في الملف الذي يشير إليه كائن الـ URLConnection , و هو عبارة عن رقم يمثل تاريخ آخر مرة تم فيها تعديل هذا الملف.الرقم الذي ترجعه عبارة عن عدد الـ milliseconds الموجودة إعتباراً من التاريخ 1/1/1970 00:00:00 GMT .ترجع 0 في حال كان الوقت غير معروف. |
7 | public long getExpiration()
ترجع قيمة الحقل expires في حال كانت مذكورة في الملف الذي يشير إليه كائن الـ URLConnection , و هو عبارة عن رقم يمثل تاريخ صلاحية الملف.الرقم الذي ترجعه عبارة عن عدد الـ milliseconds الموجودة إعتباراً من التاريخ 1/1/1970 00:00:00 GMT .ترجع 0 في حال كانت غير مذكورة في الملف. معلومة: في العادة أي ملف نطلبه من موقع ما يتم إعطائه تاريخ صلاحية, هذا التاريخ يضمن لك أن زوار الموقع سيحصلون دائماً على آخر تحديث فعلته لهذا الملف. فمثلاً, عندما تقوم بفتح أي صفحة من النت, يقوم المتصفح بحفظ هذه الصفحة على القرص الصلب, و في حال طلبت نفس الصفحة من جديد حتى و لو كان بعد سنة, سيقوم المتصفح أولاً بالبحث في الصفحات المخزنة فيه سابقاً, و في حال وجد أن هذه الصفحة أصلاً موجودة عنده, يعرضها لك بسرعة بدل أن تنتظره ليحملها لك من النت. إذاً هنا المشكلة تكون أنك ستحصل دائماً على النسخة القديمة للصفحة. الحل لهذه المشكلة كان بإعطاء الملفات تاريخ صلاحية. فمثلاً تجعل الصفحة صالحة لمدة يوم واحد, عندها في إذا قام المستخدم بطلب نفس الصفحة التي طلبها في اليوم السابق, سيجد المتصفح أن الصفحة التي يمكلها إنتهت صلاحيتها و بالتالي سيطلبها له من السيرفر من جديد و عندها سيحصل على آخر تحديث تم إجراءه على الصفحة. إذاً هذا الحقل مهم جداً و يجب ذكره في جميع الملفات التي ترفع في النت. |
8 | public long getIfModifiedSince()
ترجع قيمة الحقل ifModifiedSince في حال كانت مذكورة في الملف, و هو عبارة عن رقم يمثل تاريخ آخر مرة علم فيها المستخدم أن الملف قد تم تحديثه.الرقم الذي ترجعه عبارة عن عدد الـ milliseconds الموجودة إعتباراً من التاريخ 1/1/1970 00:00:00 GMT .ترجع 0 في حال كان الوقت غير معروف. معلومة: هنا مثلاً يتم تصميم البرنامج لمقارنة آخر مرة قام فيها هو بتعديل محتوى الملف مع آخر مرة قام فيها أي أحد بتعديل محتوى هذا الملف. في حال وجد نفسه هو آخر من قام بتحديث الملف, يعلم عندها أن المعلومات المذكورة فيه لم تتغير و بالتالي يمكنه إستعمال النسخة التي يملكها من هذا الملف بدل تحميلها من النت من جديد. لكن في حال وجد أن هذا الملف قد تم تحديثه من قبل شخص آخر, عندها سيقوم بتحميل النسخة الموجودة في السيرفر من جديد و تجاهل النسخة التي يملكها. |
9 | public void setDoInput(boolean input)
تحدد قيمة الحقل doinput في كائن الـ URLConnection .إذا قمت بتمرير القيمة true لها فهذا يعني أنك تنوي استخدام كائن الـ URLConnection لقراءة محتوى الملف.ترمي الإستثناء IllegalStateException في حال كان الكائن متصلاً بالملف قبل استدعائها. |
10 | public boolean getDoInput()
ترجع قيمة الحقل doinput في حال قمنا بتحديدها في كائن الـ URLConnection . |
11 | public void setDoOutput(boolean output)
تحدد قيمة الحقل doinput في كائن الـ URLConnection .إذا قمت بتمرير القيمة true لها فهذا يعني أنك تنوي استخدام كائن الـ URLConnection للكتابة في الملف.ترمي الإستثناء IllegalStateException في حال كان الكائن متصلاً بالملف قبل استدعائها. |
12 | public boolean getDoOutput()
ترجع قيمة الحقل dooutput في حال قمنا بتحديدها في كائن الـ URLConnection . |
13 | public void setUseCaches(boolean usecaches)
تحدد قيمة الحقل usecaches في كائن الـ URLConnection .إذا قمت بتمرير القيمة true لها فهذا يعني أنك تريد الإحتفاظ بنسخة من الملف في القرص الصلب.ترمي الإستثناء IllegalStateException في حال كان الكائن متصلاً بالملف قبل استدعائها. |
14 | public boolean getUseCaches()
ترجع قيمة الحقل usecaches في حال قمنا بتحديدها في كائن الـ URLConnection . |
15 | public InputStream getInputStream()
ترجع كائن نوعه InputStream يستخدم للقراءة من الملف.في حال حدث خطأ بسبب الملف يتم رمي الإستثناء IOException. و في حال كان البروتوكول المستخدم غير ملائم للتعامل مع الملف, يتم رمي الإستثناء UnknownServiceException. |
16 | public OutputStream getOutputStream()
ترجع كائن نوعه OutputStream يستخدم للكتابة في الملف.في حال حدث خطأ بسبب الملف يتم رمي الإستثناء IOException. و في حال كان البروتوكول المستخدم غير ملائم للتعامل مع الملف, يتم رمي الإستثناء UnknownServiceException. |
17 | public String getHeaderField(String name)
ترجع قيمة أي حقل نمرر إسمه لها كنص. |
18 | public Map<String,List<String>> getHeaderFields()
ترجع كائن نوعه Map يحتوي على جميع أسماء و قيم الحقول الموجودة في Header كائن الـ Connection بشكل key / value.معلومة: هذه الدالة ترجع لك جميع معلومات الإتصال دفعة واحدة كجدول, و بالتالي تسهل عليك جلب جميع المعلومات المتعلقة بعملية الإتصال مع الملف. |
19 | public URL getURL()
ترجع كائن الـ URL المستخدم من قبل كائن الـ Connection . |
أمثلة شاملة
المثال الأول
في المثال التالي قمنا بتعريف كائن نوعه URL
يشير إلى صفحتنا في فيسبوك https://www.facebook.com/harmashcom.
بعدها قمنا باستدعاء الدالة openConnection()
و التي ترجع كائن نوعه URLConnection
يتيح لنا تجهيز معلومات الإتصال.
بعدها قمنا باستدعاء الدالة getHeaderFields()
و التي ترجع كائن نوعه Map
يمثل جميع الحقول الموجودة في كائن الـ URLConnection
.
بعدها قمنا بإنشاء حلقة For Each تعرض لنا في كل دورة معلومات حقل واحد, أي Entry واحد.
ملاحظة: الإنترفيس Map
يملك Inner Interface إسمه Entry
نستخدمه للتعامل مع العناصر التي يملكها كائن الـ Map
.
بما أن الإنترفيس Entry
معرف بداخل الإنترفيس Map
يمكننا إستدعاءه هكذا Map.Entry
.
import java.net.URL; // URL هنا قمنا باستدعاء الكلاس import java.net.URLConnection; // URLConnection هنا قمنا باستدعاء الكلاس import java.util.Map; // Map هنا قمنا باستدعاء الكلاس import java.util.List; // هنا قمنا باستدعاء الكلاس public class Main { public static void main(String[] args) { // الآن سنحاول إجراء إتصال عبر الشبكة للوصول إلى ملف محدد و عرض كافة معلومات الإتصال المتوفرة try { // يشير إلى رابط موقعنا في فيسبوك url إسمه URL هنا قمنا بتعريف كائن نوعه URL url = new URL("https://www.facebook.com/harmashcom"); // connection إسمه URLConnection هنا قمنا بتعريف كائن نوعه URLConnection connection = url.openConnection(); // map في الكائن getHeaderFields() هنا قمنا بتخزين أسماء و قيم الحقول التي سترجعها الدالة Map<String,<String>> map = connection.getHeaderFields(); // و بعدها سيتم عرضهم entry بجلب إسم حقل و قيمته و وضعهم في الكائن entrySet() هنا في كل دورة تقوم الدالة for (Map.Entry<String,<String>> entry : map.entrySet()) { System.out.println(entry.getKey() +" : "+ entry.getValue()); } } catch( Exception e ) { System.out.println(e.getMessage()); } } }
سنحصل على النتيجة التالية عند التشغيل.
null : [HTTP/1.1 200 OK] Expires : [Sat, 01 Jan 2000 00:00:00 GMT] X-XSS-Protection : [0] Set-Cookie : [fr=0R31HwmcA2qNYUaC..BX7LPo.cm.AAA.0.0.BX7LPo.AWWl-1aI; expires=Wed, 27-Dec-2016 06:25:44 GMT; Max-Age=7776000; path=/; domain=.facebook.com; httponly] Connection : [keep-alive] public-key-pins-report-only : [max-age=500; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliasfasTH32Us5sud4PB18="; pin-sha256="r/mIkG3eEpVdm+u/ko/cwxzOMo1bJ4TyHIlByibiA5E="; pin-sha256="q4PO2G4cbkZhZ82+JgmRUyGMoAeozA+BSXVXQWA8XWQ="; report-uri="http://reports.fb.com/hpkp/"] Cache-Control : [private, no-cache, no-store, must-revalidate] X-Content-Type-Options : [nosniff] Pragma : [no-cache] X-FB-Debug : [k1P7SDLc7cblje32GG3ydHZ8awX/he/64uiyasdf34f4BF4HYuiXpPSGYahNfpx+7F+vnKq3z4IbNvEEXYjgg==] X-Frame-Options : [DENY] Strict-Transport-Security : [max-age=15552000; preload] Vary : [Accept-Encoding] Date : [Thu, 29 Sep 2016 06:25:44 GMT] Transfer-Encoding : [chunked] P3P : [CP="Facebook does not have a P3P policy. Learn why here: http://fb.me/p3p"] Content-Type : [text/html]
المثال الثاني
في المثال التالي قمنا بتعريف برنامجين, الأول هو برنامج صغير جداً مكتوب بلغة PHP موجود على السيرفر أي في موقع ما, و الثاني عبارة عن برنامج مكتوب بلغة جافا. أنت الآن مسؤول عن كود الجافا فقط, لأنك تدرس لغة جافا و ليس لغة PHP التي تستعمل في بناء المواقع.
فكرة البرنامج هي الوصول إلى ملف موجود في سيرفر معين عبر شبكة النت و إدخال بيانات فيه إضافة إلى البيانات الموجودة فيه, بعدها قمنا بقراءة محتوى هذا الملف.
- من السطر 24 إلى السطر 41, قمنا بإرسال البيانات التي أدخلها المستخدم إلى الملف الموجود في السيرفر.
- من السطر 44 إلى السطر 60, قمنا باستقبال كامل البيانات التي أصبحت موجودة في الملف و من ثم عرضناها.
هذا ملف PHP و هو عبارة عن صفحة ويب موجودة على السيرفر, نمرر لها إيميل و كلمة مرور عند استدعائها, فتعرضهم في الصفحة عندما تفتح.
إنتبه: لم نشرح هذا الكود لأنك الآن تدرس لغة جافا و ليس لغة PHP و لست بحاجة إلى فهمه أيضاً.
if(isset($_GET['email']) &↦ isset($_GET['password'])) { $email = $_GET['email']; $password = $_GET['password']; echo "your email is '$email' and your password is '$password'"; }
import java.io.BufferedReader; // BufferedReader هنا قمنا باستدعاء الكلاس import java.io.InputStreamReader; // InputStreamReader هنا قمنا باستدعاء الكلاس import java.net.HttpURLConnection; // HttpURLConnection هنا قمنا باستدعاء الكلاس import java.net.URL; // URL هنا قمنا باستدعاء الكلاس import java.util.Scanner; // Scanner هنا قمنا باستدعاء الكلاس public class Main { public static void main(String[] args) { // سنستخدمه لإستقبال بيانات في البرنامج من لوحة مفاتيح المستخدم input إسمه Scanner هنا قمنا بإنشاء كائن من الكلاس Scanner input = new Scanner(System.in); // لتخزين البيانات التي سيطلب البرنامج من المستخدم إدخالها password و email هنا قمنا بتجهيز المتغيرات String email; String password; // الآن سنحاول إجراء إتصال عبر الشبكة للوصول إلى ملف محدد و إدخال بيانات فيه ثم إسترجاع جميع البيانات التي فيه try { // email هنا سيطلب من المستخدم إدخال بريده الإلكتروني و بعدها سيتم تخزينه في المتغير System.out.print("Enter you email: "); email = input.next(); // password هنا سيطلب من المستخدم إدخال كلمة المرور و بعدها سيتم تخزينها في المتغير System.out.print("Enter you password: "); password = input.next(); // و يمرر له المعلومات التي أدخلها المتسخدم test.php هنا قمنا بإنشاء رابط يوصلنا إلى الملف String urlLink = "http://localhost/java/test.php?email=" +email+ "&password=" +password; // urlLink يشير إلى الرابط url إسمه URL هنا قمنا بتعريف كائن نوعه URL url = new URL(urlLink); // conn و وضعناه في الكائن HttpURLConnection إلى النوع openConnection() الذي سترجعه الدالة URLConnection هنا قمنا بتحويل كائن الـ HttpURLConnection conn = (HttpURLConnection)url.openConnection(); // هنا حددنا الطريقة التي سيتم فيها إرسال البيانات إلى السيرفر conn.setRequestMethod("GET"); // و الذي يسمح لنا بقراءة محتوى الملف br من السيرفر في الكائن getInputStream() هنا قمنا بتخزين الملف الذي سترجعه الدالة BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); // لجلب البيانات الموجودة بشكل مؤقت line لحفظ البيانات التي أرجعها السيرفر, و المتغير data هنا قمنا بتجهيز المتغير String data = ""; String line; // data غير فارغ سيتم قراءة محتوياته سطرا سطرا و تخزينهم في المتغير br هنا قلنا أنه طالما أن الملف الذي يشير له الكائن while((line = br.readLine()) != null) { data += line; } br.close(); // data هنا قمنا بعرض محتوى الملف الذي أرجعه السيرفر و الذي قمنا بتخزينه في المتغير System.out.println("\nServer Response"); System.out.println(data); } catch( Exception e ) { System.out.println(e.getMessage()); } } }
سنحصل على النتيجة التالية عند التشغيل إذا قمنا بإدخال نفس المعلومات التي أدخلناها عند تشغيل البرنامج.
قمنا بتعليم البيانات التي إنتظرنا البرنامج لإدخالها من لوحة المفاتيح باللون الأزرق.
و قمنا بتعليم البيانات التي حصلنا عليها من السيرفر باللون الأخضر.
Enter you password: 1234
Server Response
your email is 'contact@harmash.com' and your password is '1234'