تصف هذه المقالة طريقة الحصول على معلمات Servlet في طلبات Post Ajax في بيانات النموذج وحمولة الطلب. شاركه للرجوع إليه ، على النحو التالي:
في طلب HTTP ، إذا كان طلب GET ، يتم إرفاق معلمة النموذج بعنوان URL في نموذج الاسم = value & name1 = value1. إذا كان طلبًا منشورًا ، فإن معلمة النموذج موجودة في هيئة الطلب ، وهي أيضًا في هيئة الطلب في شكل name = value & name1 = value1. من خلال أدوات مطور Chrome ، يمكنك رؤية ما يلي (إليك نموذج قابل للقراءة ، وليس تنسيق طلب طلب طلب HTTP الحقيقي):
احصل على طلب:
requesturl: http: //127.0.0.1: 8080/test/test.do؟ name = mikan & address = streetRequest method: getStatus code: 200 OkRequest HeadersAccept: Text/HTML ، Application/XHTML+XML ، Application/XML ؛ Q = 0.9 ، Image/WebP ،*/*؛ Ph: Alexatoolbar/alxg-3.2connection: keep-alivecookie: jsessionid = 74ac93f9f572980b6fc10474cd8ed8dhost: 127.0.0.1: 8080referer: http: //127.0.0.1: 8080/test: (Windows NT 6.1) AppleWebkit/537.36 (KHTML ، مثل Gecko) Chrome/33.0.1750.149 Safari/537.36Query String ParametersName: Mikanaddress: streetresponse HeadersContent-Length: 2Date:
طلب النشر:
requesturl: http://127.0.0.1:8080/test/test.dorequest الطريقة: رمز poststatus: 200 OkRequest HeadersAccept: Text/HTML ، Application/XHTML+XML ، Application/XML ؛ Q = 0.9 ، Image/WebP ،*/*؛ dchaccept-language: Zh-Cn ، Zh ؛ q = 0.8 ، en ؛ q = 0.6alexatoolbar-alx_ns_ph: alexatoolbar/alxg-3.2cache-control: max-ag = 0connection : Keep-AliveContent-Length: 25Content-type: Application/X-WWW-Form-urlencodedcookie: JSessionID = 74AC93F9F572980B6FC10474CD8 Edd8dhost: 127.0.0.1: 8080origin: http: //127.0.0.1: 8080referer: http: //127.0.0.1: 8080/test/index.jspuser-agent: mozilla/5.0 (Windows NT 6.1) AppleWebkit/537.36 (KHTML ، مثل Gecko) Chrome/33.0.1750.149 Safari/537.36form Dataname: Mikanaddress: streetResponse HeaderScontent-Length: 2date: 11 May 2014 11:05:33 Gmtserver:
هنا يجب أن نلاحظ أن نوع المحتوى لطلب النشر هو التطبيق/X-WWW-Form-urlencoded ، والمعلمة في هيئة الطلب ، أي بيانات النموذج في الطلب أعلاه.
في servlet ، يمكن الحصول على معلمات النموذج عن طريق request.getParameter(name) .
وإذا كان استخدام طلب نشر Ajax الأصلي:
وظيفة getxmlHttprequest () {var xhr ؛ if (window.activexObject) {xhr = new ActivexObject ("microsoft.xmlHttp") ؛ } آخر if (window.xmlHttPrequest) {xhr = new xmlhttprequest () ؛ } آخر {xhr = null ؛ } return xhr ؛} وظيفة Save () {var xhr = getxmlhttprequest () ؛ XHR.Open ("post" ، "http://127.0.0.1:8080/test/test.do") ؛ var data = "name = mikan & address = street ..." ؛ XHR.SEND (البيانات) ؛ XHR.OnReadyStateChange = function () {if (xHr.ReadyState == 4 && xhr.status == 200) {Alert ("returner:"+ xhr.responsetext) ؛ }} ؛}من خلال أدوات مطور Chrome ، راجع رأس الطلب على النحو التالي:
requesturl: http://127.0.0.1:8080/test/test.dorequest الطريقة: رمز poststatus: 200 OkRequest HeadersAccept:*/*قبول الترميز: gzip ، deflate ، sdchaccept-language: Zh-Cn ، Zh ؛ q = 0.8 ، en ؛ Ext/Plain ؛ charset = utf-8cookie: jsessionid = c40c7823648e952e7c6f7d2e687a0a89host: 127.0.0.1: 8080o Rigin: http: //127.0.0.1: 8080Referer: http: //127.0.1: 8080/test/index.jspuser-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebkit/537.36 (KHTML ، مثل Gecko) Chrome/33.0.1750.149 Safari/537.36Request PayloadName = Mikan & address = streetresponse headerscontent-length: 2date: 11 May 2014 11:49:23 Gmtser:
لاحظ أن نوع المحتوى المطلوب هو text/plain;charset=UTF-8 ، ومعلمة نموذج الطلب في requestPayload.
ثم request.getParameter(name) في servlet فارغ. لماذا؟ وكيف يجب الحصول على هذه المعلمات؟
من أجل فهم هذه المشكلة ، بحثت عن بعض المعلومات وقراءة الكود المصدري لـ Tomcat7.0.53 عند معالجة معلمات الطلب ، وأخيراً اكتشفت ما يجري.
عند إرسال طلبات نموذج POST HTTP ، فإن نوع المحتوى المستخدم هو application/x-www-form-urlencoded ، وإذا لم يتم تحديد Header requestHeader ، فإن نوع المحتوى المستخدم بشكل افتراضي هو text/plain;charset=UTF-8 .
نظرًا لأن Tomcat يقوم "معالجة خاصة" لمحتوى multipart/form-data (تحميل الملف) والتطبيق/x-www-form-urlencoded (طلب البريد). دعنا نلقي نظرة على رمز المعالجة ذي الصلة أدناه.
فئة تنفيذ فئة httpservletrequest من Tomcat هي org.apache.catalina.connector.request (في الواقع org.apache.coyote.request) ، وطريقة معالجتها المعلمات protected void parseParameters() . رموز المعالجة الخاصة بمحتوى متعدد/نموذج البيانات (تحميل الملف) والتطبيق/X-WWW-form-urlencoded (طلب النشر) في هذه الطريقة هي كما يلي:
parseparameters المحمية () {// حذف بعض التعليمات البرمجية ... المعلمات. handlequeryparameters () ؛ // هنا هي معلمات المعالجة في url // حذف جزء من الكود ... إذا ("multipart/form-data" .equals (contentType)) النجاح = صحيح ؛ يعود؛ } if (! ("application/x-www-form-urlencoded" .equals (contentType))) {// هنا هي معالجة معلمات طلب البريد // حذف جزء من الكود ... حاول {if (treadpostbody (formdata ، len)! }} catch (ioException e) {// client disconnect if (context.getLogger (). isDeBuGenabled ()) {context.getLogger (). debug (sm.getString ("coyoterequest.parseparameters") ، e) ؛ } يعود؛ } parameters.processparameters (formdata ، 0 ، len) ؛ // معالجة معلمة طلب النشر ووضعها في requestParameter في الخريطة (أي ، الخريطة التي تم الحصول عليها بواسطة request.getParameterMap ، يتم الحصول على request.getParameter (الاسم) أيضًا من هذه الخريطة) // إغفال جزء من الكود ...} محمي int redpostbody (Byte Body [] ، int trows ioxpection {int Offset = 0 ؛ do {int inputlen = getStream (). اقرأ (الجسم ، الإزاحة ، len - الإزاحة) ؛ if (inputlen <= 0) {return Offset ؛ } الإزاحة += inputlen ؛ } بينما ((Len - Offset)> 0) ؛ إرجاع len ؛} من الكود أعلاه ، يمكننا أن نرى أن طلب النشر من نوع المحتوى ليس التطبيق/X-WWW-Form-urlencoded لن يقرأ بيانات جسم الطلب ويؤدي معالجة المعلمات المقابلة ، أي أن بيانات النموذج لن يتم تحليلها ووضعها في خريطة معلمة الطلب. لذلك ، لا يمكن الحصول عليها من خلال request.getParameter(name) .
فكيف نحصل على المعلمات المقدمة بهذه الطريقة؟
بالطبع ، إنها الطريقة الأكثر بدائية لقراءة دفق الإدخال للحصول عليه ، كما هو موضح أدناه:
privatestring getRequestPayload (httpservletrequest req) {StringBuildersB = new StringBuilder () ؛ حاول (bufferedReadErreader = req.getReader () ؛) {char [] buff = new char [1024] ؛ intlen بينما ((len = reader.read (buff))! = -1) {sb.append (buff ، 0 ، len) ؛ }} catch (ioException e) {E.PrintStackTrace () ؛ } returnsb.tostring () ؛}بالطبع ، يمكن أيضًا الحصول على طلبات النشر باستخدام Application/X-WWW-Form-Form-urlencoded مجموعة بهذه الطريقة.
لذلك ، عند استخدام طلب نشر Ajax الأصلي ، تحتاج إلى تعيين رأس الطلب بشكل صريح ، أي:
XHR.SetRequestHeader ("نوع المحتوى" ، "التطبيق/X-WWW-Form-urlencoded") ؛ بالإضافة إلى ذلك ، إذا كنت تستخدم jQuery ، فأنا أستخدم الإصدار 1.11.0 لاختباره. لا يحتاج طلب $.ajax post إلى تعيين رأس الطلب هذا بشكل صريح ، ولم أختبره بنفسي لإصدارات أخرى. أعتقد أن الإصدارات بعد 1.11.0 لا تحتاج إلى ضبطها. لكن البعض قبل قد لا يكون متأكدا. لم يتم اختبار هذا.
بوستسكريبت:
لقد فهمت حقًا سبب قيام الخادم بمعالجة خاصة لتقديم النماذج وتحميل الملفات ، لأن بيانات إرسال النموذج عبارة عن زوج القيمة ، ونوع المحتوى هو التطبيق/X-WWW-Form-urlencoded ، بينما يحتاج خادم تحميل الملفات إلى معالجة خاصة. لا يتم إصلاح تنسيق البيانات لطلبات النشر العادية (من نوع المحتوى/X-WWW-form-urlencoded) ، وهو ليس بالضرورة زوجًا من قيمة الأسماء ، لذلك لا يمكن للخادم معرفة طريقة المعالجة المحددة ، لذلك لا يمكن تحليلها إلا عن طريق الحصول على دفق البيانات الأصلي.
عندما تنفذ jQuery طلبًا منشورًا ، فإنه يعين نوع المحتوى على Application/X-WWW-Form-urlencoded ، بحيث يمكن للخادم تحليلًا بشكل صحيح. عند استخدام طلب AJAX الأصلي ، إذا لم يتم عرض نوع المحتوى ، فإن الافتراضي هو نص/عادي. في هذا الوقت ، لا يعرف الخادم كيفية تحليل البيانات ، بحيث يمكنه تحليل بيانات الطلب فقط عن طريق الحصول على دفق البيانات الأصلي.
لمزيد من المعلومات حول خوارزميات Java ، يمكن للقراء المهتمين بهذا الموقع عرض المواضيع: "ملخص مهارات برمجة شبكة Java" ، "دروس في هياكل بيانات Java والخوارزميات" و "ملخص لمهارات تشغيل Java" ، "ملخص لمهارات تشغيل Java ومهارات تشغيل" ملخص "من Java Cache" مهارات التشغيل ".
آمل أن يكون هذا المقال مفيدًا لبرمجة Java للجميع.