สบู่คืออะไร? แล้ว IBM SOAP4J ล่ะ

สบู่คืออะไร? แล้ว IBM SOAP4J ล่ะ

การแปลของ Brett McLaughlin โดย Ilya Chekmenev

SOAP คือ Simple Object Access Protocol หากคุณไม่เคยได้ยินเรื่องนี้มาก่อน คุณจะต้องอาศัยอยู่ในที่ห่างไกลจากอารยธรรม มันได้กลายเป็นแฟชั่นล่าสุดในการเขียนโปรแกรมเว็บและเป็นส่วนสำคัญของบริการเว็บซึ่งใช้กับความคลั่งไคล้ในการพัฒนาเว็บรุ่นล่าสุด หากคุณเคยได้ยินเกี่ยวกับ .NET ของ Microsoft หรือ "การปฏิวัติ" แบบเพียร์ทูเพียร์ แสดงว่าคุณเคยได้ยินเกี่ยวกับเทคโนโลยีที่ใช้ SOAP (แม้ว่าคุณจะไม่รู้ว่ามันคืออะไร) ไม่มีอันใดอันหนึ่งแต่ สองการใช้งาน SOAP จาก Apache และ Microsoft ซึ่งมีเพจหลายพันหน้าโดยเฉพาะบนเว็บไซต์สนับสนุน MSDN (http://msdn.microsoft.com/)

ในบทความนี้ ฉันจะบอกคุณว่า SOAP คืออะไร และเหตุใดจึงเป็นส่วนสำคัญในการพัฒนากระบวนทัศน์การเขียนโปรแกรมเว็บ สิ่งนี้จะช่วยให้คุณข้ามพื้นฐานและเริ่มทำงานกับชุดเครื่องมือ SOAP ได้โดยตรง จากนั้น ฉันจะให้ภาพรวมคร่าวๆ ของโครงการ SOAP ที่มีอยู่ และเจาะลึกการใช้งานของ Apache บทความนี้ไม่ได้มีวัตถุประสงค์เพื่อให้ภาพรวมที่สมบูรณ์ของ SOAP หนังสือของฉัน Java & XML ฉบับที่ 2 เติมเต็มช่องว่างจำนวนมาก คุณจะพบคำตอบสำหรับคำถามมากมายที่เกิดขึ้นหลังจากอ่านบทความนี้ในหนังสือ

การแนะนำ

ก่อนอื่นคุณต้องเข้าใจว่า SOAP คืออะไร คุณสามารถอ่านความคิดเห็น W3C ฉบับเต็ม (และค่อนข้างยาว) ได้ที่ http://www.w3.org/TR/SOAP จากนั้น เมื่อคิดออกและทิ้งเปลือกทั้งหมดทิ้งไป คุณจะเข้าใจว่า SOAP เป็นเพียงโปรโตคอลเท่านั้น มันเป็นโปรโตคอลง่ายๆ (ไม่จำเป็นต้องเขียนโปรโตคอลใหม่เพื่อใช้งาน) โดยอิงจากแนวคิดที่ว่า ณ จุดใดจุดหนึ่งในสถาปัตยกรรมแบบกระจายมีความจำเป็นต้องแลกเปลี่ยนข้อมูล นอกจากนี้ สำหรับระบบที่มีความเป็นไปได้ที่จะเกิดการโอเวอร์โหลดและความยากลำบากในกระบวนการประมวลผล โปรโตคอลนี้มีข้อได้เปรียบอย่างมากตรงที่มีน้ำหนักเบาและต้องการทรัพยากรจำนวนน้อยที่สุด สุดท้ายนี้ ช่วยให้การดำเนินการทั้งหมดดำเนินการผ่าน HTTP ซึ่งทำให้สามารถหลีกเลี่ยงสิ่งที่ยุ่งยาก เช่น ไฟร์วอลล์ และป้องกันตัวเองจากการฟังโดยใช้ซ็อกเก็ตบนพอร์ตจำนวนมากอย่างไม่น่าเชื่อ สิ่งสำคัญคือคุณต้องตระหนักถึงสิ่งนี้ และสิ่งอื่นๆ ก็คือรายละเอียด

แน่นอนว่าคุณต้องการทราบรายละเอียดเหล่านี้ และฉันจะไม่เพิกเฉยต่อพวกเขา ข้อกำหนด SOAP มีองค์ประกอบพื้นฐานสามประการ ได้แก่ ซอง SOAP ชุดกฎการเข้ารหัส และวิธีการโต้ตอบระหว่างคำขอและการตอบกลับ ลองนึกถึงข้อความ SOAP ว่าเป็นตัวอักษรธรรมดา คุณยังจำของโบราณเหล่านั้นในซองพร้อมแสตมป์และที่อยู่เขียนไว้ด้านหน้าหรือไม่? การเปรียบเทียบนี้จะช่วยให้คุณเข้าใจแนวคิดของ SOAP ว่าเป็น "ซองจดหมาย" ได้ชัดเจนยิ่งขึ้น รูปที่ 12-1 แสดงให้เห็นกระบวนการ SOAP ในรูปแบบของการเปรียบเทียบนี้

รูปที่ 12-1. กระบวนการข้อความ SOAP

เก็บภาพนี้ไว้ในใจแล้วมาดูองค์ประกอบสามประการของข้อกำหนด SOAP กัน ฉันจะพูดสั้นๆ เกี่ยวกับแต่ละข้อ โดยยกตัวอย่างที่แสดงถึงแนวคิดได้ดีที่สุด องค์ประกอบหลักทั้งสามนี้ทำให้ SOAP มีความสำคัญและมีความหมายมาก การจัดการข้อผิดพลาด การสนับสนุนการเข้ารหัสต่างๆ การทำให้เป็นอนุกรมพารามิเตอร์ และข้อเท็จจริงที่ว่า SOAP ทำงานบน HTTP ในกรณีส่วนใหญ่ ทำให้มีความน่าสนใจมากกว่าโซลูชันอื่นๆ สำหรับโปรโตคอลแบบกระจาย SOAP มีความสามารถในการทำงานร่วมกันในระดับสูงกับแอปพลิเคชันอื่นๆ ซึ่งฉันได้กล่าวถึงในรายละเอียดเพิ่มเติมในหนังสือของฉัน สำหรับตอนนี้ ฉันต้องการมุ่งเน้นไปที่องค์ประกอบหลักของ SOAP

ซองจดหมาย

ซองสบู่มีลักษณะคล้ายกับซองจดหมายทั่วไป ประกอบด้วยข้อมูลเกี่ยวกับข้อความที่จะถูกเข้ารหัสในส่วน SOAP หลัก รวมถึงข้อมูลเกี่ยวกับผู้รับและผู้ส่ง ตลอดจนข้อมูลเกี่ยวกับตัวข้อความเอง ตัวอย่างเช่น ส่วนหัวของเอนเวโลป SOAP อาจระบุวิธีการประมวลผลข้อความ ก่อนที่แอปพลิเคชันจะเริ่มประมวลผลข้อความ จะตรวจสอบข้อมูลเกี่ยวกับข้อความ รวมถึงสามารถประมวลผลข้อความได้หรือไม่ ไม่เหมือนกับสถานการณ์ที่มีการเรียก XML-RPC มาตรฐาน (จำได้ไหมว่าข้อความ XML-RPC, การเข้ารหัส ฯลฯ ทุกอย่างจะรวมกันเป็นส่วน XML เดียว) โดยที่ SOAP จะดำเนินการประมวลผลอย่างต่อเนื่องเพื่อเรียนรู้บางอย่างเกี่ยวกับข้อความ ข้อความ SOAP ทั่วไปอาจมีรูปแบบการเข้ารหัสที่จะช่วยผู้รับในการประมวลผลข้อความ ตัวอย่างที่ 12-1 แสดงซอง SOAP ที่ลงท้ายด้วยข้อกำหนดการเข้ารหัส

ตัวอย่างที่ 12-1: ซองสบู่

กล่องสบู่ http://www-106.ibm.com/developerworks/library/x-soapbx1.html

อย่างที่คุณเห็น การเข้ารหัสถูกตั้งค่าไว้ภายในซองจดหมาย ซึ่งช่วยให้แอปพลิเคชันสามารถกำหนดได้ (โดยใช้ค่าแอตทริบิวต์ การเข้ารหัสสไตล์) ไม่ว่าจะสามารถอ่านข้อความขาเข้าที่อยู่ในองค์ประกอบได้หรือไม่ ร่างกาย- ตรวจสอบให้แน่ใจว่าเนมสเปซของเอนเวโลป SOAP ถูกต้อง ไม่เช่นนั้นเซิร์ฟเวอร์ SOAP ที่ได้รับข้อความของคุณจะรายงานข้อผิดพลาดเวอร์ชันที่ไม่ตรงกัน และคุณจะไม่สามารถสื่อสารกับเซิร์ฟเวอร์เหล่านั้นได้

การเข้ารหัส

องค์ประกอบที่สำคัญประการที่สองของ SOAP คือความสามารถในการเข้ารหัสประเภทข้อมูลที่กำหนดเอง ด้วย RPC (และ XML-RPC) การเข้ารหัสสามารถทำได้เฉพาะกับประเภทข้อมูลที่กำหนดไว้ล่วงหน้าซึ่งได้รับการสนับสนุนในชุดเครื่องมือ XML-RPC ที่คุณดาวน์โหลด การเข้ารหัสข้อมูลประเภทอื่นๆ กำหนดให้คุณต้องแก้ไขเซิร์ฟเวอร์ RPC และไคลเอนต์ด้วยตนเอง ด้วย SOAP คุณสามารถใช้ XML schema เพื่อระบุประเภทข้อมูลใหม่ได้อย่างง่ายดาย (โดยใช้โครงสร้าง ประเภทที่ซับซ้อนตามที่กล่าวไว้ในบทที่ 2 ของหนังสือของฉัน) และประเภทใหม่เหล่านี้สามารถแสดงในรูปแบบ XML โดยเป็นส่วนหนึ่งของส่วนหลักของ SOAP ด้วยการรวม XML Schema คุณสามารถเข้ารหัสข้อมูลประเภทใดก็ได้ในข้อความ SOAP โดยการอธิบายอย่างมีเหตุผลใน XML Schema

เรียก

วิธีที่ดีที่สุดในการทำความเข้าใจวิธีการทำงานของการเรียก SOAP คือการเปรียบเทียบกับสิ่งที่คุณคุ้นเคย เช่น XML-RPC หากคุณจำได้ การเรียก XML-RPC จะดูคล้ายกับข้อมูลโค้ดที่แสดงในตัวอย่างที่ 12-2

ตัวอย่างที่ 12-2 โทรไปที่ XML-RPC

// ระบุโปรเซสเซอร์ XML (parser) เพื่อใช้ XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser"); // ระบุเซิร์ฟเวอร์ที่จะทำการเชื่อมต่อ XmlRpcClient client = new XmlRpcClient("http://rpc.middleearth.com"); // การสร้างพารามิเตอร์ Vector params = new Vector(); params.addElement(หมายเลขเที่ยวบิน); params.addElement(numSeats); params.addElement(ประเภทบัตรเครดิต); params.addElement(เครดิตการ์ดนัม); // ขอบูลีน buyTickets = (บูลีน) client.execute ("ticketCounter.buyTickets", params); // ประมวลผลการตอบสนอง

ฉันสร้างโปรแกรมง่ายๆ สำหรับสั่งซื้อตั๋วเครื่องบิน ตอนนี้เรามาดูตัวอย่างที่ 12-3 ซึ่งสาธิตการเรียก SOAP

ตัวอย่างที่ 12-3 โทรไปที่สบู่

// การสร้างพารามิเตอร์ Vector params = new Vector(); params.addElement(พารามิเตอร์ใหม่("flightNumber", Integer.class, flightNumber, null)); params.addElement(พารามิเตอร์ใหม่("numSeats", Integer.class, numSeats, null)); params.addElement(พารามิเตอร์ใหม่("creditCardType", String.class, creditCardType, null)); params.addElement(พารามิเตอร์ใหม่("creditCardNumber", Long.class, creditCardNum, null)); // การสร้างวัตถุ Call Call call = new Call(); call.setTargetObjectURI("โกศ:xmltoday-airline-tickets"); call.setMethodName("ซื้อตั๋ว"); call.setEncodingStyleURI (ค่าคงที่ NS_URI_SOAP_ENC); call.setParams(พารามิเตอร์); // การตอบสนองการโทร res = call.inurge (URL ใหม่ ("http://rpc.middleearth.com"), ""); // ประมวลผลการตอบสนอง

อย่างที่คุณเห็น การโทรจริงที่แสดงโดยออบเจ็กต์ เรียก, ที่อยู่อาศัยของหน่วยความจำ ช่วยให้คุณสามารถระบุเป้าหมายการโทร วิธีการโทร รูปแบบการเข้ารหัส พารามิเตอร์ และพารามิเตอร์อื่นๆ อีกมากมายที่ไม่แสดงในตัวอย่างนี้ นี่เป็นกลไกที่ยืดหยุ่นกว่าวิธี XML-RPC ซึ่งช่วยให้คุณสามารถระบุชุดพารามิเตอร์ต่างๆ ที่กำหนดไว้โดยปริยายใน XML-RPC ได้อย่างชัดเจน ภายหลังในบทความนี้ คุณจะได้เรียนรู้เพิ่มเติมเกี่ยวกับกระบวนการโทร รวมถึงวิธีที่ SOAP จัดการกับคำขอที่ไม่ถูกต้อง ลำดับชั้นข้อผิดพลาด และแน่นอนว่าผลลัพธ์การโทรที่ส่งคืน

หลังจากแนะนำสั้นๆ คุณก็รู้ดีพอที่จะสนใจเรื่องตลกๆ นี้แล้ว ตอนนี้ให้ฉันแนะนำคุณเกี่ยวกับการใช้งาน SOAP ที่ฉันจะใช้ ฉันจะอธิบายเหตุผลว่าทำไมฉันถึงเลือกมันและดูตัวอย่างโค้ดบางส่วน

การตั้งค่า

เมื่อคุณได้เรียนรู้พื้นฐานของแนวคิดแล้ว ก็ถึงเวลาสนุก: การเขียนโปรแกรม ในการทำเช่นนี้คุณจะต้องมีโครงการหรือผลิตภัณฑ์ที่สะดวกสบายซึ่งหาได้ง่ายกว่าที่คิดไว้ตั้งแต่แรกเห็น หากคุณต้องการโปรเจ็กต์ Java ที่มีความสามารถ SOAP คุณไม่จำเป็นต้องค้นหานาน ผลิตภัณฑ์มีสองกลุ่ม: เชิงพาณิชย์และฟรี เช่นเดียวกับในหนังสือของฉัน ฉันจะหลีกเลี่ยงการกล่าวถึงผลิตภัณฑ์เชิงพาณิชย์ นี่ไม่ใช่เพราะพวกเขาแย่ (ในทางกลับกัน บางคนก็ยอดเยี่ยม) แต่เป็นเพราะฉันอยากให้ผู้อ่านคนใดคนหนึ่งได้ลองตัวอย่างที่ให้มา นี่เป็นเพราะความสามารถในการเข้าถึงซึ่งผลิตภัณฑ์เชิงพาณิชย์จำนวนมากไม่มี คุณต้องชำระเงินเพื่อใช้งานหรือใช้ชั่วคราวในระยะเวลาที่จำกัดหลังจากดาวน์โหลด

ดังนั้นเราจึงเข้าหาโครงการโอเพ่นซอร์สได้อย่างราบรื่น จากพื้นที่นี้ ฉันสามารถตั้งชื่อผลิตภัณฑ์ได้เพียงผลิตภัณฑ์เดียวเท่านั้น: Apache SOAP ตั้งอยู่ที่http://xml.apache.org/soap และมีชุดเครื่องมือ SOAP สำหรับ Java ในขณะที่เขียน เวอร์ชัน 2.2 เปิดตัวแล้ว ซึ่งคุณสามารถดาวน์โหลดได้จากเว็บไซต์ Apache เป็นเวอร์ชันนี้ที่ฉันจะใช้ในตัวอย่างนี้สำหรับบทความนี้

ทางเลือกอื่น ๆ

ก่อนที่จะดำเนินการติดตั้งและกำหนดค่า Apache SOAP ฉันจะตอบคำถามสองสามข้อที่อาจคืบคลานเข้ามาในใจคุณ ฉันคิดว่าฉันได้อธิบายอย่างชัดเจนแล้วว่าทำไมฉันถึงไม่ใช้ผลิตภัณฑ์เชิงพาณิชย์ อย่างไรก็ตาม คุณอาจนึกถึงโอเพ่นซอร์สหรือโครงการที่เกี่ยวข้องอื่น ๆ ที่คุณอาจต้องการใช้ และคุณแปลกใจที่ฉันไม่ได้แสดงความคิดเห็นเกี่ยวกับพวกเขา

แล้ว IBM SOAP4J ล่ะ?

อันดับแรกในรายการทางเลือกคือการนำไปใช้งานจาก IBM: SOAP4J งานของ IBM เป็นพื้นฐานของโครงการ Apache SOAP เช่นเดียวกับที่ XML4J ของ IBM เติบโตขึ้นจนเป็นที่รู้จักในชื่อโครงการ Apache Xerces XML parser สันนิษฐานว่าการใช้งาน IBM จะได้รับการออกแบบใหม่ โดยรวมกับ Apache SOAP สิ่งเดียวกันนี้เกิดขึ้นกับ XML4J ของ IBM เท่านั้น: ขณะนี้มีเพียงบรรจุภัณฑ์ใน Xerces เท่านั้น นี่เป็นการเน้นย้ำถึงแนวโน้ม - ผู้ผลิตรายใหญ่มักจะสนับสนุนและใช้โครงการ OpenSource ในกรณีนี้ทั้งสองโครงการ (Apache และ IBM) ใช้ฐานรหัสเดียวกัน

Microsoft ออกจากเกมแล้วหรือยัง?

ไม่แน่นอน Microsoft และการใช้งาน SOAP รวมถึงความเคลื่อนไหวของ .NET ทั้งหมด (ตามที่กล่าวถึงในรายละเอียดเพิ่มเติมในหนังสือของฉัน) มีความสำคัญมาก ฉันอยากใช้เวลาส่วนใหญ่ดูรายละเอียดการใช้งาน SOAP ของ Microsoft โดยละเอียด แต่รองรับเฉพาะออบเจ็กต์ COM เท่านั้นและไม่รองรับ Java ด้วยเหตุผลเหล่านี้ จึงไม่สามารถรวมคำอธิบายดังกล่าวในบทความเกี่ยวกับ Java และ XML ได้ อย่างไรก็ตาม Microsoft (แม้จะมีการร้องเรียนทั้งหมดที่เราในฐานะนักพัฒนามีเกี่ยวกับ บริษัท นี้) ได้ทำงานที่สำคัญในด้านบริการเว็บและคุณจะทำผิดพลาดหากคุณละทิ้งมันไปโดยไม่คิดโดยได้รับคำแนะนำจากอารมณ์ความรู้สึกเท่านั้น หากคุณจำเป็นต้องทำงานกับคอมโพเนนต์ COM หรือ Visual Basic ฉันขอแนะนำให้คุณลองใช้ชุดเครื่องมือ Microsoft SOAP ซึ่งอยู่ที่ http://msdn.microsoft.com/library/default.asp?url=/nhp/Default .asp ?contentid=28000523 พร้อมด้วยทรัพยากร SOAP อื่นๆ อีกมากมาย

แกนคืออะไร?

บรรดาผู้ที่ติดตามกิจกรรมของ Apache จะต้องเคยได้ยินเกี่ยวกับ Apache Axis มาก่อน Axis เป็นชุดเครื่องมือ SOAP เจเนอเรชั่นถัดไปที่พัฒนาภายใต้ Apache XML SOAP (ข้อกำหนด ไม่ใช่การใช้งานเฉพาะ) ซึ่งได้รับการพัฒนาอย่างรวดเร็วและรุนแรงในช่วงนี้ เป็นเรื่องยากมากที่จะปฏิบัติตาม การพยายามสร้างเวอร์ชันของ SOAP ที่ตรงตามข้อกำหนดในปัจจุบันอย่างเต็มที่ในขณะที่มีการพัฒนานั้นก็ค่อนข้างท้าทายเช่นกัน ด้วยเหตุนี้ Apache SOAP เวอร์ชันปัจจุบันจึงนำเสนอโซลูชันที่ถูกจำกัดด้วยการออกแบบ เมื่อตัดสินใจว่าไม่คุ้มที่จะลองออกแบบเครื่องมือที่มีอยู่ใหม่ทั้งหมด นักพัฒนา Apache จึงเริ่มสร้างโปรเจ็กต์โดยใช้โค้ดใหม่ ฝ่ายอักษะจึงถือกำเนิดขึ้น ชื่อของ SOAP ก็เปลี่ยนไปเช่นกัน อันดับแรกจาก SOAP เป็น XP จากนั้นเป็น XMLP จากนั้นชื่อสเปคก็หลุดไปจากชื่อ SOAP ใหม่และชื่อ "Axis" ก็ได้ถือกำเนิดขึ้น แต่ตอนนี้ดูเหมือนว่า W3C จะกลับมาใช้ชื่อสเปค SOAP (เวอร์ชัน 1.2 หรือ 2.0) ดังนั้น สิ่งต่างๆ อาจจะยังเปลี่ยนแปลงและยังจะมีความสับสนมากยิ่งขึ้น!

คิดว่า IBM SOAP4J เป็นสถาปัตยกรรม 1 ของชุดเครื่องมือ SOAP แล้ว Apache SOAP (ที่กล่าวถึงในบทความนี้) ที่เป็นสถาปัตยกรรมล่ะ2. และ Axis เป็นตัวแทนของสถาปัตยกรรม ?3 ซึ่งเป็นสถาปัตยกรรมยุคใหม่ โปรเจ็กต์นี้ใช้ SAX ในขณะที่ Apache SOAP เป็นแบบ DOM นอกจากนี้ Axis ต่างจาก Apache SOAP ตรงที่มอบแนวทางการโต้ตอบกับผู้ใช้ที่เป็นมิตรต่อผู้ใช้มากกว่า หลังจากระบุข้อดีเหล่านี้แล้ว คุณอาจสงสัยว่าเหตุใดฉันจึงไม่เลือก Axis เป็นวิชาที่ฉันศึกษา มันจะเร็วไปหน่อย ขณะนี้ Axis เวอร์ชัน 0.51 เท่านั้นที่อยู่ระหว่างการเตรียมการเปิดตัว นี่ยังไม่ใช่เบต้าหรือแม้แต่เวอร์ชันอัลฟ่า ฉันอยากจะพูดคุยเกี่ยวกับคุณสมบัติใหม่ของ Axis แต่คุณจะไม่มีโอกาสโน้มน้าวฝ่ายบริหารของคุณว่าคุณสามารถใช้ซอฟต์แวร์โอเพ่นซอร์สย่อยอัลฟาสำหรับความต้องการระบบที่สำคัญของคุณได้ ฉันจึงตัดสินใจมุ่งความสนใจไปที่สิ่งที่คุณมีอยู่จริง คุณสามารถใช้ได้เรียบร้อยแล้ว วันนี้- สบู่อาปาเช่ ฉันคิดว่าเมื่อ Apache Axis เวอร์ชันสุดท้ายออก ฉันจะอัปเดตเนื้อหานี้ในหนังสือของฉันฉบับถัดไป ถึงเวลานั้น เรามาเน้นที่โซลูชันที่มีอยู่แล้วกันดีกว่า

การติดตั้ง

การติดตั้ง SOAP มีสองรูปแบบที่เป็นไปได้ สิ่งแรกคือการเริ่มไคลเอนต์ SOAP โดยใช้ SOAP API เพื่อสื่อสารกับเซิร์ฟเวอร์ที่สามารถรับข้อความ SOAP วิธีที่สองคือการเรียกใช้เซิร์ฟเวอร์ SOAP ที่สามารถรับข้อความจากไคลเอนต์ SOAP ในส่วนนี้ ฉันได้อธิบายทั้งสองขั้นตอนแล้ว

ลูกค้า

หากต้องการใช้ไคลเอนต์ SOAP คุณต้องดาวน์โหลด Apache SOAP ก่อนซึ่งมีอยู่ที่ http://xml.apache.org/dist/soap ฉันดาวน์โหลดเวอร์ชัน 2.2 ในรูปแบบไบนารี่ (จากไดเรกทอรีย่อย เวอร์ชัน-2.2- จากนั้นคุณจะต้องคลายซิปเนื้อหาของไฟล์เก็บถาวรลงในไดเร็กทอรีบนคอมพิวเตอร์ของคุณ ในกรณีของฉันมันคือไดเร็กทอรี javaxml2 (c:\javaxml2บนคอมพิวเตอร์ Windows ของฉัน /javaxml2บนคอมพิวเตอร์ Mac OS X ของฉัน) เป็นผลให้ไฟล์ถูกแตกไฟล์ออกมา /javaxml2/สบู่-2_2- คุณจะต้องดาวน์โหลดแพ็คเกจ JavaMail จาก Sun http://java.sun.com/products/javamail/ จะต้องรองรับโปรโตคอลการถ่ายโอน SMTP ที่ใช้โดย Apache SOAP จากนั้นดาวน์โหลด Java Beans Activation Framework (JAF) ซึ่งมีอยู่ใน Sun http://java.sun.com/products/beans/glasgow/jaf.html ตามสมมติฐานที่คุณได้ติดตั้ง Xerces หรือตัวแยกวิเคราะห์ XML อื่นและพร้อมใช้งานแล้ว

บันทึก:ตรวจสอบให้แน่ใจว่าตัวแยกวิเคราะห์ XML ของคุณเป็นไปตาม JAXP และใช้เนมสเปซอย่างถูกต้อง parser ของคุณน่าจะตรงตามข้อกำหนดเหล่านี้ หากคุณประสบปัญหา วิธีที่ดีที่สุดคือเปลี่ยนกลับไปใช้ Xerces

บันทึก:ใช้ Xerces เวอร์ชันล่าสุด เวอร์ชัน 1.4 และสูงกว่าจะทำได้ มีข้อบกพร่องหลายประการใน SOAP และ Xerces 1.3(.1) ดังนั้นฉันไม่แนะนำให้ใช้ชุดค่าผสมนี้

คลายซิปแพ็คเกจ JavaMail และ JAF จากนั้นรวมไฟล์ jar ไว้ใน classpath ของคุณรวมถึงไลบรารี สบู่ขวด- ไฟล์ jar แต่ละไฟล์จะต้องอยู่ในไดเร็กทอรีรากของโปรแกรมที่เกี่ยวข้องหรือในไดเร็กทอรีย่อย /lib- เมื่อตัวแปรของคุณเสร็จแล้ว คลาสพาธควรมีลักษณะดังนี้:

$ echo $CLASSPATH /javaxml2/soap-2_2/lib/soap.jar:/javaxml2/lib/xerces.jar: /javaxml2/javamail-1.2/mail.jar:/javaxml2/jaf-1.0.1/activation.jar

สำหรับ Windows จะมีลักษณะดังนี้:

c:\>echo %CLASSPATH% c:\javaxml2\soap-2_2\lib\soap.jar;c:\javaxml2\lib\xerces.jar; c:\javaxml2\javamail-1.2\mail.jar;c:\javaxml2\jaf-1.0.1\activation.jar

และสุดท้ายก็เพิ่มไดเร็กทอรี javaxml2/สบู่-2_2/ในตัวคุณ คลาสพาธเพื่อรันตัวอย่าง SOAP ฉันได้อธิบายการตั้งค่าไว้หลายตัวอย่างในบทนี้

เซิร์ฟเวอร์

หากต้องการสร้างชุดส่วนประกอบเซิร์ฟเวอร์ที่เข้ากันได้กับ SOAP คุณต้องมีเอ็นจิ้นเซิร์ฟเล็ตก่อน เช่นเดียวกับบทที่แล้ว ฉันใช้ Apache Tomcat (มีให้ที่ http://jakarta.apache.org/) เป็นตัวอย่างสำหรับบทนี้ คุณจะต้องเพิ่มทุกสิ่งที่ลูกค้าต้องการ คลาสพาธเซิร์ฟเวอร์ วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการรีเซ็ต สบู่ขวด, การเปิดใช้งาน.jarและ mail.jarเช่นเดียวกับ parser ของคุณ ลงในไดเร็กทอรีไลบรารีของ servlet engine ของคุณ สำหรับ Tomcat นี่คือไดเร็กทอรี /lib ซึ่งมีไลบรารีสำหรับการโหลดอัตโนมัติ หากคุณต้องการให้การสนับสนุนสคริปต์ (ซึ่งไม่ได้กล่าวถึงในบทนี้ แต่อยู่ในตัวอย่าง Apache SOAP) คุณต้องใส่ bsf.ขวด(มีอยู่ที่ http://oss.software.ibm.com/developerworks/projects/bsf) และ js.โถ(มีอยู่ที่ http://www.mozilla.org/rhino/) ไปยังไดเรกทอรีเดียวกัน

บันทึก:หากคุณใช้ Xerces กับ Tomcat คุณจะต้องทำซ้ำเคล็ดลับที่ฉันกล่าวถึงในบทที่ 10 เปลี่ยนชื่อ parser.jarวี z_parser.jar, ก jaxp.jarวี z_jaxp.jarเพื่อให้แน่ใจว่า xerces.jarและเวอร์ชันที่รวมอยู่ของ JAXP จะถูกโหลดก่อนที่จะใช้ parser หรือ JAXP อื่น ๆ

จากนั้นรีสตาร์ทเอ็นจิ้นเซิร์ฟเล็ตของคุณ หลังจากนั้นคุณก็พร้อมที่จะเขียนส่วนประกอบเซิร์ฟเวอร์ SOAP

เราเตอร์ Servlet และไคลเอนต์ผู้ดูแลระบบ

นอกเหนือจากการดำเนินการขั้นพื้นฐานแล้ว Apache SOAP ยังมีเซิร์ฟเล็ตเราเตอร์และไคลเอ็นต์ผู้ดูแลระบบอีกด้วย แม้ว่าคุณจะไม่ได้ตั้งใจที่จะใช้มัน ฉันขอแนะนำให้คุณติดตั้งเพื่อทดสอบว่า SOAP ได้รับการติดตั้งอย่างถูกต้อง กระบวนการนี้ขึ้นอยู่กับเอ็นจิ้นเซิร์ฟเล็ตที่คุณใช้ ดังนั้นฉันจะจำกัดกระบวนการติดตั้งไว้ที่ Tomcat คำแนะนำในการติดตั้งสำหรับเอ็นจิ้นเซิร์ฟเล็ตอื่นๆ สามารถดูได้ที่ http://xml.apache.org/soap/docs/index.html

การติดตั้งภายใต้ Tomcat นั้นง่ายมาก เพียงนำไฟล์มา สบู่.สงครามจากไดเรกทอรี สบู่-2_2/webappsและวางลงในไดเร็กทอรี $TOMCAT_HOME/webapps- และนั่นมัน! หากต้องการตรวจสอบการติดตั้ง ให้ป้อนที่อยู่ในเบราว์เซอร์ของคุณ http://localhost:8080/soap/servlet/rpcrouter- คุณควรได้รับคำตอบคล้ายกับที่แสดงในรูปที่ 12-2

รูปที่ 12-2. เราเตอร์ RPC Servlet

แม้ว่าข้อความดังกล่าวจะปรากฏเป็นข้อความแสดงข้อผิดพลาด แต่ก็บ่งบอกว่าทุกอย่างทำงานได้อย่างถูกต้อง คุณควรได้รับการตอบสนองแบบเดียวกันหากคุณชี้เบราว์เซอร์ของคุณไปยังที่อยู่ไคลเอ็นต์ของผู้ดูแลระบบ: http://localhost:8080/soap/servlet/messagerouter.

เพื่อให้การทดสอบเซิร์ฟเวอร์และไคลเอนต์เสร็จสิ้น ตรวจสอบให้แน่ใจว่าคุณได้ปฏิบัติตามคำแนะนำทั้งหมดอย่างสมบูรณ์ จากนั้นรันคลาส Java ต่อไปนี้ตามที่แสดงด้านล่างเพื่อรองรับ URL เซิร์ฟเล็ตของคุณสำหรับเซิร์ฟเล็ตเราเตอร์ RPC:

C:\>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter รายการบริการที่ปรับใช้:

คุณควรได้รับรายการบริการว่างตามที่แสดงด้านบน หากคุณได้รับข้อความใดๆ โปรดตรวจสอบรายการข้อผิดพลาดที่เป็นไปได้แบบยาวซึ่งมีอยู่ที่ http://xml.apache.org/soap/docs/trouble/index.html นี่คือรายการปัญหาที่ครอบคลุมที่สุดที่คุณอาจพบ หากคุณได้รับรายการว่าง แสดงว่าการตั้งค่าเสร็จสมบูรณ์แล้ว และคุณพร้อมที่จะเริ่มดูตัวอย่างที่ให้ไว้ในบทนี้แล้ว

มาเริ่มกันเลย

มีสามขั้นตอนหลักในการเขียนระบบที่ใช้ SOAP เมื่อระบุรายชื่อแล้ว ผมจะพูดถึงแต่ละรายการโดยย่อ:

  • การเลือกระหว่างข้อความ SOAP-RPC และ SOAP
  • การเขียนหรือการเข้าถึงบริการ SOAP
  • การเขียนหรือการเข้าถึงไคลเอ็นต์ SOAP

ขั้นตอนแรกคือการเลือกว่าคุณจะใช้ SOAP สำหรับการเรียก RPC (ซึ่งมีการดำเนินการขั้นตอนระยะไกลบนเซิร์ฟเวอร์) หรือข้อความ (ซึ่งไคลเอ็นต์เพียงส่งข้อมูลบางส่วนไปยังเซิร์ฟเวอร์) ฉันพูดถึงกระบวนการเหล่านี้โดยละเอียดด้านล่าง เมื่อคุณตัดสินใจแล้ว คุณจะต้องเข้าถึงหรือสร้างบริการของคุณเอง แน่นอนว่า เนื่องจากเราทุกคนเป็นมืออาชีพ Java บทนี้จึงครอบคลุมถึงวิธีการสร้าง Java ของคุณเอง และสุดท้าย คุณต้องเขียนไคลเอนต์สำหรับบริการนี้ แค่นั้นเอง!

RPC หรือการส่งข้อความ?

งานแรกของคุณไม่เกี่ยวข้องกับการเขียนโปรแกรมและเป็นลักษณะการออกแบบมากกว่า คุณต้องเลือกว่าคุณจะใช้บริการ RPC หรือข้อความ เราจะถือว่าคุณคุ้นเคยกับ RPC (เช่น โดยการอ่านหนังสือของฉันบทใดบทหนึ่ง) ไคลเอ็นต์ดำเนินการขั้นตอนระยะไกลบนเซิร์ฟเวอร์แล้วรับการตอบกลับ ในสถานการณ์สมมตินี้ SOAP ทำหน้าที่เป็นระบบ XML-RPC ที่ได้รับการปรับปรุงซึ่งให้การจัดการข้อผิดพลาดและการถ่ายโอนประเภทข้อมูลที่ซับซ้อนผ่านเครือข่ายได้ดีขึ้น คุณคุ้นเคยกับแนวคิดนี้อยู่แล้ว และเนื่องจากระบบ RPC เขียนด้วย SOAP ได้ง่ายกว่า ฉันจะเริ่มด้วยแนวคิดนี้ บทความนี้อธิบายวิธีการสร้างบริการ RPC ไคลเอนต์ RPC และนำระบบไปปฏิบัติ

SOAP อีกวิธีหนึ่งในการทำงานนั้นขึ้นอยู่กับการแลกเปลี่ยนข้อความ แทนที่จะดำเนินการขั้นตอนระยะไกล จะใช้เพื่อการแลกเปลี่ยนข้อมูลเท่านั้น ดังที่คุณสามารถเดาได้ นี่เป็นเครื่องมืออันทรงพลังที่ไม่ต้องการให้ไคลเอ็นต์ทราบวิธีการเฉพาะของเซิร์ฟเวอร์ใดๆ นอกจากนี้ยังทำให้การสร้างแบบจำลองของระบบระยะไกลแยกออกจากกันมากขึ้นโดยการอนุญาตให้ส่งแพ็กเก็ตข้อมูล (แพ็กเก็ตในความหมายเป็นรูปเป็นร่าง ไม่ใช่ในแง่เครือข่าย) เพื่อส่งไปยังระบบอื่น ในเวลาเดียวกัน ระบบอื่นๆ ไม่จำเป็นต้องทราบเกี่ยวกับการดำเนินการที่ดำเนินการกับข้อมูลนี้ สไตล์นี้ซับซ้อนกว่าการเขียนโปรแกรม RPC ดังนั้นฉันจะไม่อธิบายไว้ที่นี่ คุณจะพบสิ่งนี้ได้ในหนังสือของฉัน พร้อมด้วยรายละเอียดอื่นๆ เกี่ยวกับการปฏิสัมพันธ์ระหว่างธุรกิจกับธุรกิจ ขั้นแรก มาทำความรู้จักกับการเขียนโปรแกรม SOAP-RPC

เช่นเดียวกับปัญหาการออกแบบส่วนใหญ่ การตัดสินใจนี้ขึ้นอยู่กับคุณ วิเคราะห์แอปพลิเคชันของคุณและลองพิจารณาว่าเหตุใดคุณจึงต้องใช้ SOAP หากคุณมีเซิร์ฟเวอร์และชุดไคลเอนต์ที่ทำหน้าที่ทางธุรกิจเฉพาะตามความต้องการ RPC จะเหมาะกับคุณมากกว่า ในระบบที่ซับซ้อนซึ่งการแลกเปลี่ยนข้อมูลเป็นมากกว่าการทำหน้าที่ทางธุรกิจเฉพาะตามต้องการ การใช้ข้อความ SOAP จะดีกว่ามาก

บริการอาร์พีซี

เมื่อพิธีการสิ้นสุดลงแล้ว ก็ถึงเวลาดำเนินการ ดังที่คุณทราบใน RPC คุณจะต้องมีคลาสที่วิธีการจะดำเนินการจากระยะไกล

ข้อมูลโค้ด

ฉันจะเริ่มต้นด้วยการดูข้อมูลโค้ดบางส่วนสำหรับเซิร์ฟเวอร์ แฟรกเมนต์เหล่านี้เป็นคลาสที่มีวิธีการที่ดำเนินการสำหรับไคลเอนต์ RPC ฉันใช้โค้ดจากหนังสือของฉันเป็นตัวอย่าง แทนที่จะใช้คลาสธรรมดา ฉันเลือกตัวอย่างที่ซับซ้อนมากขึ้นเพื่อแสดงความสามารถของ SOAP ให้ชัดเจนที่สุด ดังนั้นฉันจึงใช้คลาสซีดีเป็นตัวอย่าง ขั้นแรกเรากำหนดองค์ประกอบ แผนที่สำหรับพารามิเตอร์ที่ไม่ได้มาตรฐานแต่ละประเภท สำหรับคุณลักษณะ การเข้ารหัสสไตล์อย่างน้อยใน Apache SOAP 2.2 คุณต้องระบุค่า http://schemas.xmlsoap.org/soap/encoding/ นี่เป็นการเข้ารหัสเดียวที่รองรับในปัจจุบัน คุณต้องระบุเนมสเปซสำหรับประเภทที่ผู้ใช้กำหนด จากนั้นจึงระบุชื่อคลาสที่นำหน้าด้วยเนมสเปซสำหรับประเภทนั้น ในกรณีของเรา เพื่อจุดประสงค์เหล่านี้ ฉันใช้เนมสเปซสมมติและคำนำหน้าแบบธรรมดา " x" จากนั้นใช้แอตทริบิวต์ javaTypeให้ตั้งชื่อจริงของคลาส Java (สำหรับกรณีนี้ - javaxml2.CD- และสุดท้าย kuralesil พร้อมคุณสมบัติ java2XMLClassNameและ xml2JavaClassName.xml2JavaClassName- ด้วยความช่วยเหลือของพวกเขา คลาสจะถูกระบุซึ่งแปลงจาก Java เป็น XML และในทางกลับกัน ฉันใช้คลาส BeanSerializer ที่มีประโยชน์อย่างเหลือเชื่อ ซึ่งรวมอยู่ใน Apache SOAP ด้วย หากพารามิเตอร์ที่คุณกำหนดเองอยู่ในรูปแบบ JavaBean ตัวซีเรียลไลเซอร์และดีซีเรียลไลเซอร์นี้จะช่วยให้คุณไม่ต้องเขียนเอง คุณต้องมีคลาสที่มีคอนสตรัคเตอร์เริ่มต้น (จำไว้ว่าสำหรับคลาส CD ฉันกำหนดคอนสตรัคเตอร์แบบธรรมดาและไม่มีพารามิเตอร์) และเผยแพร่ข้อมูลทั้งหมดของคลาสนี้โดยใช้วิธีการ setXXXและ รับXXX- เพราะว่าชั้นเรียน ซีดีตอบสนองความต้องการเหล่านี้ได้อย่างสมบูรณ์แบบ BeanSerializerทำงานได้สมบูรณ์แบบ

บันทึก:ชั้นเรียนอะไร ซีดีตรงตามข้อกำหนด BeanSerializer- ไม่สำคัญมาก คลาสส่วนใหญ่จะแปลงเป็นรูปแบบนี้ได้อย่างง่ายดาย ดังนั้น ฉันแนะนำให้หลีกเลี่ยงการเขียนซีเรียลไลเซอร์และดีซีเรียลไลเซอร์ของคุณเอง นี่เป็นเรื่องน่าปวดหัวเป็นพิเศษ (ไม่มีอะไรซับซ้อน แต่ต้องใช้ความอุตสาหะเกินไป) และฉันขอแนะนำให้คุณประหยัดพลังงานและใช้การแปลง bean ในพารามิเตอร์ที่คุณกำหนดเอง ในหลายกรณี การแปลง bean ต้องการเพียงตัวสร้างเริ่มต้น (ไม่มีพารามิเตอร์) ในคลาสของคุณ

ตอนนี้เรามาสร้างใหม่กันดีกว่า ไหไฟล์และติดตั้งบริการของเราใหม่:

(แกนดัล์ฟ)/javaxml2/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter xml/CDCatalogDD.xml

ความสนใจ:หากคุณปล่อยให้กลไกเซิร์ฟเล็ตของคุณทำงานและโฮสต์บริการใหม่พร้อมกัน คุณจะต้องรีสตาร์ทกลไกเซิร์ฟเล็ตเพื่อเปิดใช้งานคลาสใหม่สำหรับบริการ SOAP และโฮสต์บริการอีกครั้ง

ตอนนี้สิ่งที่เหลืออยู่คือการปรับเปลี่ยนไคลเอนต์เพื่อใช้คลาสและวิธีการใหม่ ตัวอย่างที่ 12-10 มีเวอร์ชันที่แก้ไขแล้วของคลาสไคลเอ็นต์ ซีดีแอดเดอร์- การเปลี่ยนแปลงที่ทำกับเวอร์ชันก่อนหน้าจะถูกเน้นไว้

ตัวอย่างที่ 12-10: อัปเดตคลาส CDAdder

แพ็คเกจ javaxml2; นำเข้า java.net.URL; นำเข้า java.util.Vector; นำเข้า org.apache.soap.Constants; นำเข้า org.apache.soap.Fault; นำเข้า org.apache.soap.SOAPException; นำเข้า org.apache.soap.encoding.SOAPMappingRegistry; นำเข้า org.apache.soap.encoding.soapenc.BeanSerializer;นำเข้า org.apache.soap.rpc.Call; นำเข้า org.apache.soap.rpc.Parameter; นำเข้า org.apache.soap.rpc.Response; นำเข้า org.apache.soap.util.xml.QName; CDAdder คลาสสาธารณะ ( การเพิ่มโมฆะสาธารณะ (URL url, ชื่อสตริง, ศิลปินสตริง, ป้ายกำกับสตริง) พ่น SOAPException ( System.out.println("การเพิ่มซีดีชื่อ "" + ชื่อ + "" ศิลปิน "" + ศิลปิน + "" สตูดิโอ " + ป้ายกำกับ); ซีดี cd = ซีดีใหม่ (ชื่อ ศิลปิน ค่ายเพลง); // สร้างวัตถุการโทร Call Call call = new Call(); call.setSOAPMappingRegistry (รีจิสทรี); call.setTargetObjectURI("โกศ:cd-catalog"); call.setMethodName("addCD"); call.setEncodingStyleURI (ค่าคงที่ NS_URI_SOAP_ENC); // การตั้งค่าพารามิเตอร์ Vector params = new Vector(); params.addElement(พารามิเตอร์ใหม่("cd", CD.class, cd, null)); call.setParams(พารามิเตอร์); // การประมวลผลการตอบสนองการเรียกการตอบสนอง; การตอบสนอง = call.inurge(url, ""); if (!response.generatedFault()) ( System.out.println("เพิ่มซีดีเสร็จสมบูรณ์แล้ว"); ) else ( Fault error = response.getFault(); System.out.println(ข้อผิดพลาด: " + error.getFaultString ()); ) ) โมฆะคงที่สาธารณะ main(String args) ( ถ้า (args.length != 4) ( System.out.println("Template: java javaxml2.CDAdder " + "\ "[ชื่อซีดี]\" \ "[ชื่อศิลปิน]\ " \"[สตูดิโอซีดี]\""); กลับ; ) ลอง ( // URL ของเซิร์ฟเวอร์ SOAP ที่ทำการเชื่อมต่อ URL url = new URL(args); // รับค่าสำหรับชื่อสตริงซีดีใหม่ = args; ศิลปินเครื่องสาย = args; ป้ายกำกับสตริง = args; // เพิ่มซีดี CDAdder adder = new CDAdder(); adder.add(url, ชื่อ, ศิลปิน, ป้ายกำกับ); ) catch (ข้อยกเว้น e) ( e.printStackTrace(); ) ) )

การเปลี่ยนแปลงที่น่าสนใจเพียงอย่างเดียวคือในการทำแผนที่ชั้นเรียน ซีดี:

// แมปประเภทนี้เพื่อให้สามารถใช้กับ SOAP SOAPMappingRegistry register = new SOAPMappingRegistry(); BeanSerializer serializer = ใหม่ BeanSerializer(); register.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("urn:cd-catalog-demo", "cd"), CD.class, serializer, serializer);

นี่คือวิธีการเข้ารหัสและส่งพารามิเตอร์ผู้ใช้ผ่านเครือข่าย ฉันได้เล่าให้คุณฟังแล้วว่าชั้นเรียนเป็นอย่างไร BeanSerializerสามารถใช้เพื่อประมวลผลพารามิเตอร์ในรูปแบบ JavaBean เช่นคลาส ซีดี- ฉันใช้ตัวอธิบายตำแหน่งเพื่อระบุสิ่งเหล่านี้ให้เซิร์ฟเวอร์ทราบ แม้ว่าตอนนี้ฉันต้องบอกลูกค้าให้ใช้ซีเรียลไลเซอร์และดีซีเรียลไลเซอร์นี้ก็ตาม ฟังก์ชันนี้ดำเนินการโดยชั้นเรียน SOAPMappingRegistry- วิธี ประเภทแผนที่()รับสตริงที่เข้ารหัส (อีกครั้งจะดีกว่าถ้าใช้ค่าคงที่สำหรับสิ่งนี้ NS_URI_SOAP_ENC) และข้อมูลเกี่ยวกับประเภทพารามิเตอร์ที่ควรใช้การซีเรียลไลซ์แบบพิเศษ มีการระบุ QName ก่อน นี่คือสาเหตุที่มีการใช้เนมสเปซแปลก ๆ ในตัวอธิบายการโฮสต์ คุณต้องระบุ URN เดียวกันที่นี่ รวมถึงชื่อท้องถิ่นขององค์ประกอบ (สำหรับตัวอย่าง "CD") จากนั้นจึงระบุวัตถุ Java ระดับคลาสที่จะซีเรียลไลซ์ ( ซีดี.คลาส) และสุดท้ายคืออินสแตนซ์ของคลาสสำหรับการซีเรียลไลซ์และดีซีเรียลไลซ์ สำหรับตัวอย่างนี้ ทั้งสองกรณีจะเกี่ยวข้องกับอินสแตนซ์ BeanSerializer- เมื่อป้อนการตั้งค่าทั้งหมดเหล่านี้ลงในรีจิสทรีแล้ว ให้แจ้งให้วัตถุทราบ เรียกโดยใช้วิธีการ setSOAPMapping-รีจิสทรี ().

คุณสามารถรันคลาสนี้ได้ตามที่แสดงไว้ก่อนหน้านี้ โดยเพิ่มซีดี และทุกอย่างจะทำงานตามที่คาดไว้:

C:\javaxml2\build>java javaxml2.CDAdder http://localhost:8080/soap/servlet/rpcrouter "Tony Rice" "Manzanita" "Sugar Hill"การเพิ่มซีดีชื่อ "Tony Rice" โดย "Manzanita" ของ Sugar Hill เพิ่มซีดีได้สำเร็จ

ฉันออกจากการปรับเปลี่ยนชั้นเรียน ซีดีลิสเตอร์สำหรับคุณ. ทุกอย่างผลิตขึ้นตามเทมเพลตเดียวกัน หากต้องการทดสอบด้วยตัวเอง คุณสามารถดูไฟล์ตัวอย่างสำหรับหนังสือของฉันซึ่งมีชั้นเรียนที่อัปเดตเหล่านี้อยู่แล้ว

หมายเหตุ: คุณสามารถตัดสินใจได้เพราะว่าชั้นเรียน ซีดีลิสเตอร์ไม่โต้ตอบกับวัตถุโดยตรง ซีดี(ส่งคืนโดยวิธี รายการ()ประเภทมีความสำคัญ แฮชเทเบิล) จากนั้นคุณไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ อย่างไรก็ตามชั้นกลับ แฮชเทเบิลมีอินสแตนซ์ของวัตถุ ซีดี- ถ้า SOAP ไม่ทราบวิธีการดีซีเรียลไลซ์ ไคลเอ็นต์จะเกิดข้อผิดพลาด ในกรณีนี้ ในการแก้ปัญหา คุณต้องระบุในออบเจ็กต์ เรียกสำเนา SOAPMappingRegistry.

การจัดการข้อผิดพลาดที่มีประสิทธิภาพ

ตอนนี้คุณได้เห็นออบเจ็กต์แบบกำหนดเองและทำการเรียก RPC แล้ว ให้ฉันพูดถึงหัวข้อที่น่าตื่นเต้นน้อยลง: การจัดการข้อผิดพลาด การทำธุรกรรมผ่านเครือข่ายใดๆ อาจเกิดความล้มเหลวได้หลายอย่าง บริการไม่เริ่มทำงาน มีข้อผิดพลาดในเซิร์ฟเวอร์ ไม่พบวัตถุ คลาสหายไป และปัญหาอื่นๆ อีกมากมาย จนถึงตอนนี้ฉันเพิ่งใช้วิธีนี้ Fault.getString()เพื่อสร้างข้อความแสดงข้อผิดพลาด แต่วิธีนี้อาจไม่มีประโยชน์เสมอไป หากต้องการดูการทำงาน ให้ยกเลิกหมายเหตุตัวสร้าง ซีดีแค็ตตาล็อก:

CDCatalog สาธารณะ () ( //catalog = new Hashtable(); // สร้างไดเร็กทอรี addCD (ซีดีใหม่ ("Nickel Creek", "Nickel Creek", "Sugar Hill")); addCD(ซีดีใหม่("Let it Fall", "Sean Watkins", "Sugar Hill")); addCD(ซีดีใหม่("ขอบเขตทางอากาศ", "Michael Hedges", "Windham Hill")); addCD(ซีดีใหม่("Taproot", "Michael Hedges", "Windham Hill")); -

คอมไพล์ใหม่ รีสตาร์ทเอ็นจิ้นเซิร์ฟเล็ต และโฮสต์ใหม่ ซึ่งจะส่งผลให้เกิดข้อยกเว้น NullPointerExceptionเมื่อตัวสร้างคลาสพยายามเพิ่มซีดีเพื่อเตรียมใช้งาน แฮชเทเบิล- เมื่อเริ่มต้นไคลเอนต์ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้น แต่จะไม่มีข้อมูลมากนัก:

(แกนดัล์ฟ)/javaxml2/build$ java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcrouter ดูไดเร็กทอรีซีดีปัจจุบัน ข้อผิดพลาด: ไม่สามารถแก้ไขวัตถุเป้าหมาย: null

นี่ไม่ใช่ข้อมูลทั้งหมดที่สามารถช่วยในการระบุและแก้ไขข้อผิดพลาดได้ อย่างไรก็ตาม กรอบงานสามารถรับมือกับการจัดการข้อผิดพลาดได้อย่างเหมาะสม คุณจำได้ไหม DOMFaultListenerซึ่งคุณระบุเป็นค่าขององค์ประกอบ ความผิดListener- ถึงเวลาที่เขาจะต้องเข้าสู่เกมแล้ว วัตถุส่งคืนในกรณีที่เกิดข้อผิดพลาด ความผิดพลาดมี DOM (Document Object Model) org.w3c.dom.องค์ประกอบพร้อมข้อมูลรายละเอียดเกี่ยวกับข้อผิดพลาด ขั้นแรกให้เพิ่มนิพจน์การนำเข้าลงในซอร์สโค้ดของคุณ java.util.ตัววนซ้ำ:

นำเข้า java.net.URL; นำเข้า java.util.Enumeration; นำเข้า java.util.Hashtable; นำเข้า java.util.Iterator;นำเข้า java.util.Vector; นำเข้า org.apache.soap.Constants; นำเข้า org.apache.soap.Fault; นำเข้า org.apache.soap.SOAPException; นำเข้า org.apache.soap.encoding.SOAPMappingRegistry; นำเข้า org.apache.soap.encoding.soapenc.BeanSerializer; นำเข้า org.apache.soap.rpc.Call; นำเข้า org.apache.soap.rpc.Parameter; นำเข้า org.apache.soap.rpc.Response; นำเข้า org.apache.soap.util.xml.QName;

ตอนนี้เรามาทำการเปลี่ยนแปลงเพื่อจัดการกับข้อผิดพลาดใน list() วิธีการ:

if (!response.generatedFault()) ( พารามิเตอร์ returnValue = response.getReturnValue(); Hashtable Catalog = (Hashtable)returnValue.getValue(); การแจงนับ e = Catalog.keys(); ในขณะที่ (e.hasMoreElements()) ( สตริง title = (String)e.nextElement(); CD cd = (CD)catalog.get(title); System.out.println(" "" + cd.getTitle() + "" ศิลปิน " + cd.getArtist() + " studios " + cd.getLabel()); ) ) อื่น ๆ ( Fault Fault = response.getFault(); System.out.println("ข้อผิดพลาด: " + Fault.getFaultString()); รายการเวกเตอร์ = error.getDetailEntries(); สำหรับ (Iterator i = entry.iterator(); i.hasNext();) ( org.w3c.dom.Element entry = (org.w3c.dom.Element)i.next(); System.out.println(entry) .getFirstChild().getNodeValue()); ) )

โดยใช้วิธีการ รับรายละเอียดรายการ()คุณสามารถเข้าถึงบริการ SOAP และเซิร์ฟเวอร์ข้อมูลดิบที่รองรับปัญหาได้ โค้ดจะประมวลผลอีกครั้ง (โดยปกติจะมีองค์ประกอบเดียวเท่านั้น แต่ต้องได้รับการดูแลอย่างใกล้ชิด) และดักจับ DOM องค์ประกอบที่มีอยู่ในแต่ละรายการ โดยพื้นฐานแล้ว นี่คือ XML ที่คุณใช้งานอยู่:

SOAP-ENV:Server.BadTargetObjectURI ไม่สามารถแก้ไขเป้าหมาย: null นี่คือสิ่งที่เราต้องการ!

กล่าวอีกนัยหนึ่ง วัตถุ Fault ช่วยให้คุณเข้าถึงส่วนของซอง SOAP ที่มีข้อผิดพลาด นอกจากนี้ Apache SOAP ยังจัดเตรียมการติดตามสแต็ก Java เมื่อเกิดข้อผิดพลาด โดยให้ข้อมูลโดยละเอียดที่จำเป็นในการแก้ไข การสกัดกั้นองค์ประกอบ สแต็กติดตามและพิมพ์ค่าโหนดออกมา ข้อความจากองค์ประกอบนี้ไคลเอ็นต์ของคุณสามารถพิมพ์การติดตามสแต็กเซิร์ฟเวอร์ได้ โดยการรวบรวมการเปลี่ยนแปลงเหล่านี้และรีสตาร์ทไคลเอนต์ คุณจะได้รับผลลัพธ์ดังต่อไปนี้:

C:\javaxml2\build>java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcr ภายนอก ดูไดเร็กทอรีซีดีปัจจุบัน ข้อผิดพลาด: ไม่สามารถแก้ไขเป้าหมาย: null java.lang.NullPointerException ใน javaxml2.CDCatalog.addCD(CDCatalog.java:24) ใน javaxml2.CDCatalog (CDCatalog.java:14) ใน java.lang.Class.newInstance0(Native Method) ใน java.lang.Class.newInstance(Class.java:237)

แม้จะไม่ได้ดีไปกว่านี้มากนัก แต่อย่างน้อยคุณก็สามารถเห็นข้อมูลชิ้นเล็กๆ น้อยๆ ว่ามีข้อยกเว้นเกิดขึ้น NullPointerExceptionและแม้กระทั่งค้นหาหมายเลขบรรทัดในคลาสเซิร์ฟเวอร์ที่เกิดปัญหานี้ ผลลัพธ์ของการเปลี่ยนแปลงล่าสุดเหล่านี้ทำให้คุณเห็นภาพที่ชัดเจนของปัญหาการจัดการข้อผิดพลาด ตอนนี้คุณควรตรวจสอบคลาสเซิร์ฟเวอร์ของคุณเพื่อหาข้อผิดพลาด ใช่ เกือบลืมไปเลย ก่อนนั้นอย่าลืมเปลี่ยนคลาสกลับด้วย ซีดีแค็ตตาล็อกเพื่อกำจัดข้อผิดพลาดที่เราตั้งใจแนะนำเพื่อความชัดเจน!

  1. มีการพูดคุยกันมากมายเกี่ยวกับการรัน SOAP บนโปรโตคอลอื่นๆ เช่น SMTP (หรือแม้แต่ Jabber) ปัจจุบันมาตรฐาน SOAP ไม่ได้จัดเตรียมไว้ แต่ความสามารถที่คล้ายกันนี้อาจถูกเพิ่มเข้ามาในอนาคต ดังนั้นอย่าแปลกใจหากคุณพบการสนทนาที่กระตือรือร้นในหัวข้อนี้
  • บทช่วยสอน

สวัสดีทุกคน!
มันเกิดขึ้นเมื่อไม่นานมานี้ฉันเริ่มพัฒนาบริการเว็บ แต่วันนี้หัวข้อไม่เกี่ยวกับฉัน แต่เกี่ยวกับวิธีที่เราสามารถเขียน XML Web Service ของเราเองโดยใช้โปรโตคอล SOAP 1.2

ฉันหวังว่าหลังจากอ่านหัวข้อนี้แล้ว คุณจะสามารถ:

  • เขียนการใช้งานเว็บแอปพลิเคชันเซิร์ฟเวอร์ของคุณเอง
  • เขียนการใช้งานเว็บแอปพลิเคชันไคลเอนต์ของคุณเอง
  • เขียนคำอธิบายบริการเว็บของคุณเอง (WSDL)
  • ส่งอาร์เรย์ไคลเอ็นต์ของข้อมูลประเภทเดียวกันไปยังเซิร์ฟเวอร์
ดังที่คุณอาจเดาได้ ความมหัศจรรย์ทั้งหมดจะเสร็จสิ้นโดยใช้ PHP และคลาส SoapClient และ SoapServer ในตัว กระต่ายของเราจะเป็นบริการส่งข้อความ SMS

1 คำชี้แจงปัญหา

1.1 ขอบเขต

ในตอนแรกฉันเสนอให้จัดการกับผลลัพธ์ที่เราจะได้รับในตอนท้ายของหัวข้อ ตามที่ได้ประกาศไว้ข้างต้น เราจะเขียนบริการสำหรับการส่งข้อความ SMS และที่สำคัญกว่านั้นคือ เราจะรับข้อความจากแหล่งต่างๆ ผ่านโปรโตคอล SOAP หลังจากนั้นเราจะมาพิจารณาว่าจะมาเซิฟเวอร์ในรูปแบบไหน น่าเสียดายที่กระบวนการจัดคิวข้อความเพื่อส่งไปยังผู้ให้บริการเพิ่มเติมนั้นอยู่นอกเหนือขอบเขตของโพสต์นี้ด้วยเหตุผลหลายประการ

1.2 เราจะเปลี่ยนแปลงข้อมูลอะไรบ้าง?

เยี่ยมมาก เราตัดสินใจเกี่ยวกับขอบเขตแล้ว! ขั้นตอนต่อไปที่ต้องดำเนินการคือตัดสินใจว่าเราจะแลกเปลี่ยนข้อมูลใดระหว่างเซิร์ฟเวอร์และไคลเอนต์ ในหัวข้อนี้ฉันไม่แนะนำให้แยกผมยาวเกินไปและตอบคำถามหลักสำหรับตัวคุณเองทันที:
  • ข้อมูลขั้นต่ำที่ต้องส่งไปยังเซิร์ฟเวอร์เพื่อส่งข้อความ SMS ไปยังสมาชิก?
  • ข้อมูลขั้นต่ำที่ต้องส่งจากเซิร์ฟเวอร์เพื่อตอบสนองความต้องการของลูกค้าคืออะไร?
มีบางอย่างบอกฉันว่าสำหรับสิ่งนี้คุณต้องส่งสิ่งต่อไปนี้:
  • หมายเลขโทรศัพท์มือถือ และ
  • ข้อความของข้อความ SMS
โดยหลักการแล้วคุณสมบัติทั้งสองนี้เพียงพอสำหรับการส่ง แต่ฉันนึกได้ทันทีว่าจะมี SMS พร้อมคำอวยพรวันเกิดมาถึงคุณตอนตี 3 หรือ 4 โมงเช้า! ในตอนนี้ฉันจะขอบคุณทุกคนมากที่ไม่ลืมฉัน! ดังนั้นเราจะส่งไปยังเซิร์ฟเวอร์และ
  • วันที่ส่งข้อความ SMS
สิ่งต่อไปที่ฉันต้องการส่งไปยังเซิร์ฟเวอร์คือ:
  • ประเภทข้อความ
พารามิเตอร์นี้ไม่บังคับ แต่จะมีประโยชน์มากสำหรับเราหากเราต้องบอกเจ้านายอย่างรวดเร็วว่ามีลูกค้ากี่รายที่เรา "พอใจ" กับข่าวของเรา และยังดึงสถิติที่สวยงามเกี่ยวกับเรื่องนี้ด้วย

แต่ฉันก็ลืมอะไรบางอย่าง! หากเราไตร่ตรองเพิ่มเติมอีกเล็กน้อย เป็นที่น่าสังเกตว่าลูกค้าสามารถส่งข้อความ SMS ทีละข้อความหรือหลายข้อความไปยังเซิร์ฟเวอร์ได้ กล่าวอีกนัยหนึ่ง แพ็กเก็ตข้อมูลหนึ่งสามารถประกอบด้วยข้อความตั้งแต่หนึ่งถึงอนันต์

ด้วยเหตุนี้เราจึงได้รับข้อความ SMS ที่เราต้องการข้อมูลต่อไปนี้:

  • เบอร์โทรศัพท์,
  • ข้อความ SMS,
  • เวลาที่ส่งข้อความ SMS ไปยังสมาชิก
  • ประเภทข้อความ

เราได้ตอบคำถามแรกไปแล้ว ตอนนี้เราต้องตอบคำถามที่สอง และบางทีฉันอาจจะยอมให้ตัวเองยุ่งนิดหน่อย ดังนั้นจากเซิร์ฟเวอร์เราจะส่งเฉพาะข้อมูล Boolean ซึ่งมีความหมายดังนี้

  • TRUE – แพ็กเก็ตเข้าถึงเซิร์ฟเวอร์ได้สำเร็จ ผ่านการรับรองความถูกต้อง และเข้าคิวเพื่อส่งไปยังผู้ให้บริการ SMS
  • FALSE – ในกรณีอื่นๆ ทั้งหมด

นี่เป็นการสรุปคำอธิบายของคำชี้แจงปัญหา! และสุดท้าย เรามาดูส่วนที่สนุกกันดีกว่า มาดูกันว่า SOAP นี้คือสัตว์ประหลาดชนิดไหน!

2 สบู่คืออะไร?

โดยทั่วไป ในตอนแรกฉันไม่ได้วางแผนที่จะเขียนอะไรเกี่ยวกับ SOAP และต้องการจำกัดตัวเองให้ลิงก์ไปยังเว็บไซต์ w3.org พร้อมข้อกำหนดที่จำเป็น รวมถึงลิงก์ไปยัง Wikipedia แต่ท้ายที่สุดแล้ว ฉันตัดสินใจเขียนบันทึกสั้นๆ เกี่ยวกับโปรโตคอลนี้

และฉันจะเริ่มต้นเรื่องราวของฉันด้วยความจริงที่ว่าโปรโตคอลการแลกเปลี่ยนข้อมูลนี้เป็นของกลุ่มย่อยของโปรโตคอลที่อิงตามกระบวนทัศน์ที่เรียกว่า RPC (Remote Procedure Call) ซึ่งตรงกันข้ามกับ REST (Representational State Transfer) คุณสามารถอ่านเพิ่มเติมเกี่ยวกับสิ่งนี้ได้ใน Wikipedia ลิงก์ไปยังบทความอยู่ที่ส่วนท้ายสุดของหัวข้อ จากบทความเหล่านี้ เราต้องเข้าใจสิ่งต่อไปนี้: “แนวทาง RPC อนุญาตให้ใช้ทรัพยากรเครือข่ายจำนวนเล็กน้อยด้วยวิธีการจำนวนมากและโปรโตคอลที่ซับซ้อน ด้วยแนวทาง REST จำนวนวิธีการและความซับซ้อนของโปรโตคอลจะถูกจำกัดอย่างเข้มงวด ซึ่งหมายความว่าจำนวนทรัพยากรแต่ละรายการอาจมีขนาดใหญ่ได้” นั่นคือที่เกี่ยวข้องกับเรา หมายความว่าในกรณีของแนวทาง RPC บนไซต์ จะมีหนึ่งอินพุต (ลิงก์) ไปยังบริการเสมอ และขั้นตอนใดที่จะเรียกใช้เพื่อประมวลผลข้อมูลขาเข้าที่เราถ่ายโอนพร้อมกับข้อมูล ในขณะที่ ด้วยแนวทาง REST ในไซต์ของเรามีอินพุต (ลิงก์) จำนวนมาก ซึ่งแต่ละอินพุตจะยอมรับและประมวลผลเฉพาะข้อมูลบางอย่างเท่านั้น หากใครก็ตามที่อ่านรู้วิธีอธิบายความแตกต่างในแนวทางเหล่านี้ให้ง่ายขึ้น อย่าลืมเขียนความคิดเห็นด้วย!

สิ่งต่อไปที่เราต้องรู้เกี่ยวกับ SOAP คือโปรโตคอลนี้ใช้ XML เดียวกันกับการขนส่ง ซึ่งในอีกด้านหนึ่งก็ดีมาก เพราะ คลังแสงของเรารวมพลังเต็มรูปแบบของเทคโนโลยีที่ใช้ภาษามาร์กอัปนี้ในทันที ซึ่งก็คือ XML-Schema ซึ่งเป็นภาษาสำหรับอธิบายโครงสร้างของเอกสาร XML (ขอบคุณ Wikipedia!) ซึ่งช่วยให้สามารถตรวจสอบความถูกต้องของข้อมูลที่ได้รับจากเซิร์ฟเวอร์ได้โดยอัตโนมัติ จากลูกค้า

ตอนนี้เรารู้แล้วว่า SOAP เป็นโปรโตคอลที่ใช้ในการเรียกใช้ขั้นตอนระยะไกลและใช้ XML เป็นการขนส่ง! หากคุณอ่านบทความใน Wikipedia คุณสามารถเรียนรู้จากที่นั่นว่าสามารถใช้บนโปรโตคอลระดับแอปพลิเคชันใดก็ได้ ไม่ใช่แค่ใช้ร่วมกับ HTTP เท่านั้น (ขออภัยในหัวข้อนี้ เราจะพิจารณาเฉพาะ SOAP ผ่าน HTTP เท่านั้น) และคุณรู้ไหมว่าฉันชอบอะไรมากที่สุดเกี่ยวกับเรื่องทั้งหมดนี้? หากไม่มีการเดาฉันจะให้คำแนะนำ - สบู่!... ยังไม่มีการคาดเดาใช่ไหม... คุณแน่ใจหรือว่าอ่านบทความใน Wikipedia?... โดยทั่วไปแล้วฉันจะไม่ทรมานคุณอีกต่อไป ดังนั้นฉันจะตรงไปที่คำตอบ: “SOAP (จาก English Simple Object Access Protocol - simple มาตรการการเข้าถึงวัตถุ จนถึงข้อกำหนด 1.2- สิ่งที่น่าทึ่งที่สุดเกี่ยวกับบรรทัดนี้คือตัวเอียง! ฉันไม่รู้ว่าคุณได้ข้อสรุปอะไรจากทั้งหมดนี้ แต่ฉันเห็นสิ่งต่อไปนี้ - เนื่องจากโปรโตคอลนี้ไม่สามารถเรียกว่า "เรียบง่าย" ได้ แต่อย่างใด (และเห็นได้ชัดว่าแม้แต่ w3 ก็เห็นด้วยกับสิ่งนี้) จากนั้นจากเวอร์ชัน 1.2 ก็หยุดการถอดรหัสอย่างใด ! และกลายเป็นที่รู้จักในชื่อ SOAP แค่ SOAP เท่านั้น

โอเค ขอโทษที ฉันหลงทางนิดหน่อย ตามที่ฉันเขียนไว้ก่อนหน้านี้ XML ถูกใช้เป็นการขนส่ง และแพ็กเก็ตที่เดินทางระหว่างไคลเอนต์และเซิร์ฟเวอร์เรียกว่าซองจดหมาย SOAP หากพิจารณาถึงโครงสร้างทั่วไปของซองคงจะคุ้นเคยกันดี เพราะ... คล้ายกับโครงสร้างของหน้า HTML มันมีส่วนหลัก - ห่อหุ้มซึ่งรวมถึงส่วนต่างๆ หัวข้อและ ร่างกาย, หรือ ความผิดพลาด- ใน ร่างกายข้อมูลถูกส่งและเป็นส่วนบังคับของซองจดหมายในขณะที่ หัวข้อเป็นทางเลือก ใน หัวข้อการอนุญาตหรือข้อมูลอื่นใดที่ไม่เกี่ยวข้องโดยตรงกับข้อมูลอินพุตของขั้นตอนบริการเว็บอาจถูกถ่ายโอน เกี่ยวกับ ความผิดพลาดไม่มีอะไรพิเศษที่จะบอก ยกเว้นว่ามันมาถึงไคลเอนต์จากเซิร์ฟเวอร์ในกรณีที่เกิดข้อผิดพลาด

นี่คือจุดสิ้นสุดเรื่องราวการรีวิวของฉันเกี่ยวกับโปรโตคอล SOAP (เราจะดูที่ซองจดหมายและโครงสร้างอย่างละเอียดมากขึ้น เมื่อลูกค้าและเซิร์ฟเวอร์ของเราเรียนรู้ที่จะใช้งานร่วมกันในที่สุด) และอันใหม่เริ่มต้นขึ้น - เกี่ยวกับสหาย SOAP ที่เรียกว่า WSDL(ภาษาคำอธิบายบริการเว็บ) ใช่ ใช่ นี่คือสิ่งที่ทำให้เราส่วนใหญ่กลัวจากการพยายามนำ API ของเราไปใช้งานบนโปรโตคอลนี้ ด้วยเหตุนี้ เราจึงมักจะสร้างวงล้อของเราขึ้นมาใหม่โดยมี JSON เป็นพาหนะ แล้ว WSDL คืออะไร? WSDL เป็นภาษาสำหรับอธิบายและเข้าถึงบริการบนเว็บ อิงตามภาษา XML (c) Wikipedia หากคำจำกัดความนี้ไม่ชัดเจนสำหรับคุณถึงความหมายอันศักดิ์สิทธิ์ทั้งหมดของเทคโนโลยีนี้ ฉันจะพยายามอธิบายด้วยคำพูดของฉันเอง!

WSDL ได้รับการออกแบบมาเพื่อให้ลูกค้าของเราสื่อสารกับเซิร์ฟเวอร์ได้ตามปกติ ในการดำเนินการนี้ ไฟล์ที่มีนามสกุล “*.wsdl” จะอธิบายข้อมูลต่อไปนี้:

  • เนมสเปซอะไรถูกใช้?
  • มีการใช้สคีมาข้อมูลอะไรบ้าง
  • บริการเว็บคาดหวังข้อความประเภทใดจากไคลเอนต์
  • ข้อมูลใดเป็นของขั้นตอนการบริการเว็บใด
  • บริการเว็บมีขั้นตอนอะไรบ้าง?
  • ลูกค้าควรเรียกขั้นตอนบริการเว็บอย่างไร
  • ลูกค้าควรส่งการโทรไปยังที่อยู่ใด
อย่างที่คุณเห็น ไฟล์นี้เป็นบริการบนเว็บทั้งหมด ด้วยการระบุที่อยู่ของไฟล์ WSDL ในไคลเอนต์เราจะรู้ทุกอย่างเกี่ยวกับบริการเว็บ! ด้วยเหตุนี้เราจึงไม่จำเป็นต้องรู้อะไรเลยเกี่ยวกับตำแหน่งของบริการบนเว็บ สิ่งที่คุณต้องรู้คือตำแหน่งของไฟล์ WSDL! ในไม่ช้า เราจะพบว่า SOAP ไม่ได้น่ากลัวเท่ากับสุภาษิตรัสเซียที่กล่าวไว้

3 รู้เบื้องต้นเกี่ยวกับ XML-Schema

ตอนนี้เรารู้มากแล้วว่า SOAP คืออะไร มีอะไรอยู่ข้างใน และมีภาพรวมของ Technology Stack ที่ล้อมรอบ SOAP เนื่องจากก่อนอื่น SOAP เป็นวิธีการโต้ตอบระหว่างไคลเอนต์และเซิร์ฟเวอร์ และใช้ภาษามาร์กอัป XML เป็นการขนส่ง ในส่วนนี้เราจะเข้าใจเล็กน้อยเกี่ยวกับวิธีตรวจสอบข้อมูลอัตโนมัติที่เกิดขึ้นโดยใช้สกีมา XML

งานหลักของไดอะแกรมคือการอธิบายโครงสร้างของข้อมูลที่เราจะประมวลผล ข้อมูลทั้งหมดใน XML Schema แบ่งออกเป็น เรียบง่าย(สเกลาร์) และ ซับซ้อน(โครงสร้าง) ประเภท ประเภทง่าย ๆ ได้แก่ประเภทต่อไปนี้:

  • เส้น,
  • ตัวเลข,
  • ค่าบูลีน
  • วันที่ของ
สิ่งที่เรียบง่ายมากซึ่งไม่มีส่วนขยายอยู่ภายใน แอนติบอดีของพวกมันเป็นประเภทที่ซับซ้อนและซับซ้อน ตัวอย่างที่ง่ายที่สุดของประเภทที่ซับซ้อนที่อยู่ในใจของทุกคนคือวัตถุ ตัวอย่างเช่นหนังสือ หนังสือเล่มนี้ประกอบด้วยคุณสมบัติ: ผู้เขียน, ชื่อ, ราคา, หมายเลขไอเอสบีเอ็นฯลฯ และในทางกลับกันคุณสมบัติเหล่านี้อาจเป็นได้ทั้งแบบธรรมดาหรือแบบซับซ้อน และหน้าที่ของสคีมา XML คือการอธิบายสิ่งนี้

ฉันขอแนะนำว่าอย่าไปไกลและเขียนสคีมา XML สำหรับข้อความ SMS ของเรา! ด้านล่างนี้เป็นคำอธิบาย xml ของข้อความ SMS:

71239876543 ข้อความทดสอบ 2013-07-20T12:00:00 12
แผนภาพประเภทที่ซับซ้อนของเราจะมีลักษณะดังนี้:


รายการนี้อ่านดังนี้: เรามีตัวแปร " ข้อความ" พิมพ์ " ข้อความ"และมีประเภทที่ซับซ้อนเรียกว่า" ข้อความ"ซึ่งประกอบด้วยชุดองค์ประกอบตามลำดับ" โทรศัพท์" พิมพ์ เชือก, « ข้อความ" พิมพ์ เชือก, « วันที่" พิมพ์ วันเวลา, « พิมพ์" พิมพ์ ทศนิยม- ประเภทเหล่านี้เป็นแบบเรียบง่ายและได้กำหนดไว้ในคำอธิบายสคีมาแล้ว ยินดีด้วย! เราเพิ่งเขียน XML Schema แรกของเรา!

ฉันคิดว่าความหมายของธาตุ” องค์ประกอบ" และ " ประเภทที่ซับซ้อน"ทุกอย่างชัดเจนสำหรับคุณไม่มากก็น้อย ดังนั้นเราจะไม่เน้นไปที่สิ่งเหล่านั้นอีกต่อไปแล้ว เรามาเปลี่ยนตรงไปที่องค์ประกอบผู้แต่งกันดีกว่า" ลำดับ- เมื่อเราใช้องค์ประกอบผู้แต่ง " ลำดับ“เราขอแจ้งให้คุณทราบว่าองค์ประกอบที่รวมอยู่ในนั้นจะต้องอยู่ในลำดับที่ระบุในแผนภาพเสมอ และองค์ประกอบทั้งหมดนั้นเป็นข้อบังคับ แต่อย่าเพิ่งหมดหวัง! มีองค์ประกอบผู้แต่งอีกสององค์ประกอบในสกีมา XML: " ทางเลือก" และ " ทั้งหมด- นักแต่งเพลง " ทางเลือก"ประกาศว่าจะต้องมีองค์ประกอบอย่างใดอย่างหนึ่งอยู่ในรายการและผู้แต่ง" ทั้งหมด» – การรวมกันขององค์ประกอบที่ระบุไว้

ดังที่คุณจำได้ในส่วนแรกของหัวข้อเราได้ตกลงกันว่าสามารถส่งข้อความ SMS ตั้งแต่หนึ่งถึงอนันต์ได้ในแพ็คเกจ ดังนั้นฉันจึงเสนอให้เข้าใจว่าข้อมูลดังกล่าวถูกประกาศใน XML schema อย่างไร โครงสร้างแพ็คเกจทั่วไปอาจมีลักษณะดังนี้:

71239876543 ข้อความทดสอบ 1 2013-07-20T12:00:00 12 71239876543 ทดสอบข้อความ N 2013-07-20T12:00:00 12
ไดอะแกรมสำหรับประเภทที่ซับซ้อนดังกล่าวจะมีลักษณะดังนี้:


บล็อกแรกประกอบด้วยคำประกาศที่คุ้นเคยของประเภทที่ซับซ้อน “ ข้อความ- หากคุณสังเกตเห็นว่าในแต่ละประเภทง่าย ๆ จะรวมอยู่ใน " ข้อความ" มีการเพิ่มคุณลักษณะการชี้แจงใหม่แล้ว " นาทีเกิดขึ้น" และ " เกิดขึ้นสูงสุด- อย่างที่คุณอาจเดาได้จากชื่ออันแรก ( นาทีเกิดขึ้น) แสดงว่าลำดับนี้ต้องมีองค์ประกอบประเภทอย่างน้อยหนึ่งองค์ประกอบ “ โทรศัพท์», « ข้อความ», « วันที่" และ " พิมพ์"ในขณะที่อันถัดไป ( เกิดขึ้นสูงสุด) คุณลักษณะประกาศให้เราทราบว่ามีองค์ประกอบดังกล่าวมากที่สุดหนึ่งรายการในลำดับของเรา ด้วยเหตุนี้ เมื่อเราเขียนสคีมาของเราเองสำหรับข้อมูลใดๆ เราจะมีตัวเลือกที่หลากหลายที่สุดในการกำหนดค่าข้อมูลเหล่านั้น!

บล็อกที่สองของแผนภาพประกาศองค์ประกอบ " รายการข้อความ" พิมพ์ " รายการข้อความ- ชัดเจนว่า" รายการข้อความ" เป็นประเภทที่ซับซ้อนซึ่งมีองค์ประกอบอย่างน้อยหนึ่งองค์ประกอบ " ข้อความ"แต่จำนวนองค์ประกอบดังกล่าวสูงสุดไม่จำกัด!

4 เขียน WSDL ของคุณ

คุณจำได้ไหมว่า WSDL คือบริการบนเว็บของเรา ฉันหวังว่าคุณจะจำได้! ขณะที่เราเขียน บริการเว็บเล็กๆ ของเราจะทำงานบนนั้น ดังนั้นผมแนะนำว่าอย่าไปยุ่งวุ่นวาย

โดยทั่วไป เพื่อให้ทุกอย่างทำงานได้อย่างถูกต้องสำหรับเรา เราจำเป็นต้องถ่ายโอนไฟล์ WSDL ที่มีประเภท MIME ที่ถูกต้องไปยังไคลเอนต์ ในการดำเนินการนี้ คุณต้องกำหนดค่าเว็บเซิร์ฟเวอร์ของคุณตามลำดับ กล่าวคือ ตั้งค่าประเภท MIME สำหรับไฟล์ที่มีนามสกุล “*.wsdl” เป็นบรรทัดต่อไปนี้:

แอปพลิเคชัน/wsdl+xml
แต่ในทางปฏิบัติฉันมักจะส่งส่วนหัว HTTP ผ่าน PHP " ข้อความ/xml»:

Header("ประเภทเนื้อหา: text/xml; charset=utf-8");
และทุกอย่างทำงานได้ดีมาก!

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

เนื่องจาก WSDL เป็น XML คุณจึงต้องเขียนเกี่ยวกับเรื่องนี้โดยตรงในบรรทัดแรก องค์ประกอบรูทของไฟล์ควรถูกเรียกว่า " คำจำกัดความ»:


โดยทั่วไป WSDL ประกอบด้วยบล็อกหลัก 4-5 บล็อก บล็อกแรกสุดคือคำจำกัดความของบริการบนเว็บหรืออีกนัยหนึ่งคือจุดเริ่มต้น


มันบอกว่าที่นี่มีบริการที่เรียกว่า - “ บริการ SMS- โดยหลักการแล้ว คุณสามารถเปลี่ยนชื่อทั้งหมดในไฟล์ WSDL ตามที่คุณต้องการได้ เพราะ พวกเขาไม่มีบทบาทเลย

หลังจากนี้เราจะประกาศว่าในบริการเว็บของเรา " บริการ SMS" มีจุดเข้า ("พอร์ต") เรียกว่า " SmsServicePort- ถึงจุดเริ่มต้นนี้เองที่คำขอทั้งหมดจากไคลเอนต์ไปยังเซิร์ฟเวอร์จะถูกส่งไป และระบุในองค์ประกอบ “ ที่อยู่» ลิงก์ไปยังไฟล์ตัวจัดการที่จะยอมรับคำขอ

เมื่อเรากำหนดเว็บเซอร์วิสและระบุจุดเริ่มต้นแล้ว เราจำเป็นต้องผูกขั้นตอนที่รองรับเข้ากับบริการนั้น:


โดยจะแสดงรายการการดำเนินการใดและจะถูกเรียกในรูปแบบใด เหล่านั้น. สำหรับพอร์ต " SmsServicePort"การผูกมัดถูกกำหนดไว้ภายใต้ชื่อ" SmsServiceBinding"ซึ่งมีรูปแบบการโทร" รพีซี"และ HTTP ถูกใช้เป็นโปรโตคอลการส่งข้อมูล ดังนั้นเราจึงระบุไว้ที่นี่ว่าเราจะทำการเรียก RPC ผ่าน HTTP หลังจากนี้เราจะอธิบายว่าขั้นตอนใด ( การดำเนินการ) ได้รับการสนับสนุนในบริการบนเว็บ เราจะสนับสนุนเพียงขั้นตอนเดียวเท่านั้น – “ sendSms- ด้วยขั้นตอนนี้ ข้อความอันแสนวิเศษของเราจะถูกส่งไปยังเซิร์ฟเวอร์! หลังจากประกาศขั้นตอนแล้ว จำเป็นต้องระบุว่าข้อมูลจะถูกส่งในรูปแบบใด ในกรณีนี้ มีการระบุว่าจะใช้ซอง SOAP มาตรฐาน

หลังจากนั้นเราจำเป็นต้องผูกขั้นตอนกับข้อความ:


ในการดำเนินการนี้ เราระบุว่าการเชื่อมโยงของเราเป็นประเภท " SmsServicePortType"และในองค์ประกอบ" ประเภทพอร์ต"ด้วยชื่อประเภทเดียวกันเราระบุการเชื่อมโยงขั้นตอนกับข้อความ ดังนั้นข้อความขาเข้า (จากไคลเอนต์ไปยังเซิร์ฟเวอร์) จะถูกเรียกว่า “ sendSmsRequest" และขาออก (จากเซิร์ฟเวอร์ไปยังไคลเอนต์) " sendSmsResponse- เช่นเดียวกับชื่อทั้งหมดใน WSDL ชื่อของข้อความขาเข้าและขาออกนั้นเป็นไปตามอำเภอใจ

ตอนนี้เราต้องอธิบายข้อความด้วยตนเองเช่น ขาเข้าและขาออก:


ในการทำเช่นนี้เราเพิ่มองค์ประกอบ " ข้อความ“มีชื่อ” sendSmsRequest" และ " sendSmsResponse" ตามลำดับ ในนั้นเราระบุว่าอินพุตควรเป็นซองจดหมายที่มีโครงสร้างสอดคล้องกับประเภทข้อมูล " ขอ- หลังจากนั้นซองจดหมายจะถูกส่งกลับจากเซิร์ฟเวอร์ที่มีประเภทข้อมูล - “ การตอบสนอง».

ตอนนี้เราต้องดำเนินการเพียงเล็กน้อย - เพิ่มคำอธิบายประเภทเหล่านี้ลงในไฟล์ WSDL ของเรา! และคุณคิดว่า WSDL อธิบายข้อมูลขาเข้าและขาออกอย่างไร ฉันคิดว่าคุณเข้าใจทุกอย่างมานานแล้วและบอกตัวเองว่าใช้ XML schema! และคุณจะพูดถูกอย่างแน่นอน!


คุณสามารถแสดงความยินดีกับเราได้! WSDL แรกของเราถูกเขียนแล้ว! และเราเข้าใกล้การบรรลุเป้าหมายไปอีกก้าวหนึ่งแล้ว
ต่อไป เราจะดูว่า PHP มอบอะไรให้เราในการพัฒนาแอปพลิเคชันแบบกระจายของเราเอง

5 เซิร์ฟเวอร์ SOAP แรกของเรา

ก่อนหน้านี้ฉันเขียนว่าในการสร้างเซิร์ฟเวอร์ SOAP ใน PHP เราจะใช้คลาส SoapServer ในตัว เพื่อให้การดำเนินการเพิ่มเติมทั้งหมดเกิดขึ้นในลักษณะเดียวกับฉัน คุณจะต้องปรับแต่ง PHP เล็กน้อย เพื่อให้แม่นยำยิ่งขึ้น คุณต้องแน่ใจว่าคุณได้ติดตั้งส่วนขยาย “php-soap” แล้ว วิธีที่ดีที่สุดคืออ่านวิธีการติดตั้งบนเว็บเซิร์ฟเวอร์ของคุณบนเว็บไซต์ PHP อย่างเป็นทางการ (ดูรายการข้อมูลอ้างอิง)

หลังจากติดตั้งและกำหนดค่าทุกอย่างแล้ว เราจะต้องสร้างไฟล์ในโฟลเดอร์รูทของโฮสติ้งของคุณ “ smsservice.php» โดยมีเนื้อหาดังนี้

setClass("SoapSmsGateWay"); //เริ่มเซิร์ฟเวอร์ $server->handle();
ฉันหวังว่าจะไม่จำเป็นต้องอธิบายสิ่งที่อยู่เหนือบรรทัดด้วยฟังก์ชัน “ini_set” เพราะ ที่นั่นจะมีการกำหนดว่าส่วนหัว HTTP ใดที่เราจะส่งจากเซิร์ฟเวอร์ไปยังไคลเอนต์และมีการกำหนดค่าสภาพแวดล้อม เพื่อให้สอดคล้องกับ “ini_set” เราจะปิดการใช้งานการแคชของไฟล์ WSDL เพื่อให้การเปลี่ยนแปลงของเรามีผลกับไคลเอนต์ทันที

ตอนนี้เรามาถึงเซิร์ฟเวอร์แล้ว! อย่างที่คุณเห็น เซิร์ฟเวอร์ SOAP ทั้งหมดใช้เวลาเพียงสามบรรทัดเท่านั้น! ในบรรทัดแรก เราสร้างอินสแตนซ์ใหม่ของออบเจ็กต์ SoapServer และส่งที่อยู่ของคำอธิบาย WSDL ของบริการเว็บไปยังตัวสร้าง ตอนนี้เรารู้แล้วว่ามันจะอยู่ในรูทของโฮสติ้งในไฟล์ที่มีชื่อที่อธิบายตนเองได้ “ smsservice.wsdl.php- ในบรรทัดที่สอง เราบอกเซิร์ฟเวอร์ SOAP ว่าคลาสใดที่ต้องถูกดึงเพื่อประมวลผลซองจดหมายที่ได้รับจากไคลเอนต์ และส่งคืนซองจดหมายพร้อมกับการตอบกลับ ดังที่คุณอาจเดาได้ ในชั้นเรียนนี้จะมีการอธิบายวิธีการเดียวของเรา sendSms- ในบรรทัดที่สามเราเริ่มเซิร์ฟเวอร์! เพียงเท่านี้เซิร์ฟเวอร์ของเราก็พร้อมแล้ว! ซึ่งฉันขอแสดงความยินดีกับพวกเราทุกคน!

ตอนนี้เราต้องสร้างไฟล์ WSDL ในการทำเช่นนี้คุณสามารถคัดลอกเนื้อหาจากส่วนก่อนหน้าหรือใช้เสรีภาพและ "เทมเพลต" เพียงเล็กน้อย:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />
ในขั้นตอนนี้เราควรพอใจกับผลลัพธ์ของเซิร์ฟเวอร์อย่างสมบูรณ์เพราะว่า เราสามารถบันทึกซองจดหมายที่เข้ามา จากนั้นวิเคราะห์ข้อมูลที่เข้ามาอย่างใจเย็น เพื่อให้เราได้รับสิ่งใด ๆ บนเซิร์ฟเวอร์ เราต้องการไคลเอนต์ เรามาเริ่มกันเลย!

ไคลเอนต์ SOAP 6 ตัวอยู่ระหว่างทาง

ก่อนอื่นเราต้องสร้างไฟล์ที่เราจะเขียนไคลเอนต์ ตามปกติเราจะสร้างมันขึ้นมาในรูทของโฮสต์แล้วเรียกมันว่า " ลูกค้า.php"และภายในเราจะเขียนสิ่งต่อไปนี้:

messageList = รายการข้อความใหม่(); $req->messageList->message = ข้อความใหม่(); $req->messageList->ข้อความ->โทรศัพท์ = "79871234567"; $req->messageList->message->text = "ทดสอบข้อความที่ 1"; $req->messageList->ข้อความ->date = "2013-07-21T15:00:00.26"; $req->messageList->ข้อความ->type = 15; $client = ใหม่ SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($client->sendSms($req));
มาอธิบายวัตถุของเรากันดีกว่า เมื่อเราเขียน WSDL มันอธิบายเอนทิตีสามรายการสำหรับเอนเวโลปที่เข้ามายังเซิร์ฟเวอร์: ขอ, รายการข้อความและ ข้อความ- ตามชั้นเรียน ขอ, รายการข้อความและ ข้อความเป็นการสะท้อนถึงเอนทิตีเหล่านี้ในสคริปต์ PHP ของเรา

เมื่อเรากำหนดวัตถุแล้ว เราจำเป็นต้องสร้างวัตถุ ( $req) ซึ่งเราจะส่งไปยังเซิร์ฟเวอร์ หลังจากนั้นก็มาถึงสองบรรทัดที่เรารักที่สุด! ลูกค้าสบู่ของเรา! เชื่อหรือไม่ นี่ก็เพียงพอแล้วสำหรับเซิร์ฟเวอร์ของเราในการเริ่มรับข้อความจากไคลเอนต์ รวมถึงเซิร์ฟเวอร์ของเราในการรับและประมวลผลข้อความเหล่านั้นได้สำเร็จ! ในตอนแรก เราสร้างอินสแตนซ์ของคลาส SoapClient และส่งที่อยู่ตำแหน่งของไฟล์ WSDL ไปยังตัวสร้าง และในพารามิเตอร์เราระบุอย่างชัดเจนว่าเราจะทำงานโดยใช้โปรโตคอล SOAP เวอร์ชัน 1.2 บรรทัดถัดไปเราเรียกเมธอด sendSmsวัตถุ $ลูกค้าและแสดงผลในเบราว์เซอร์ทันที
มาเริ่มกันเลยและดูว่าในที่สุดเราก็ได้อะไรมา!

วัตถุต่อไปนี้ถูกส่งคืนให้ฉันจากเซิร์ฟเวอร์:

วัตถุ (stdClass) สาธารณะ "สถานะ" => บูลีนจริง
และนี่ก็เยี่ยมมากเพราะว่า... ตอนนี้เรารู้แล้วว่าเซิร์ฟเวอร์ของเราใช้งานได้และไม่เพียงแต่ใช้งานได้ แต่ยังสามารถคืนค่าบางอย่างให้กับลูกค้าได้อีกด้วย!

ตอนนี้เรามาดูบันทึกที่เราเก็บไว้อย่างระมัดระวังบนฝั่งเซิร์ฟเวอร์กันดีกว่า! ในส่วนแรกเราจะเห็นข้อมูลดิบที่มาถึงเซิร์ฟเวอร์:

79871234567 ข้อความทดสอบ 1 2013-07-21T15:00:00.26 15
นี่คือซองจดหมาย ตอนนี้คุณรู้แล้วว่าหน้าตาเป็นอย่างไร! แต่ไม่น่าเป็นไปได้ที่เราจะสนใจที่จะดูมันตลอดเวลา ดังนั้นลองดีซีเรียลไลซ์อ็อบเจ็กต์จากไฟล์บันทึกและดูว่าทุกอย่างเรียบร้อยดีหรือไม่:

Object (stdClass) public "messageList" => object (stdClass) public "message" => object (stdClass) public "phone" => string "79871234567" (ความยาว = 11) public "text" => string "ข้อความทดสอบ 1 " (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2)
อย่างที่คุณเห็น วัตถุถูกดีซีเรียลไลซ์อย่างถูกต้อง ซึ่งฉันอยากจะแสดงความยินดีกับพวกเราทุกคน! สิ่งที่น่าสนใจรอเราอยู่ต่อไป! กล่าวคือ เราจะส่งไคลเอนต์ไปยังเซิร์ฟเวอร์ ไม่ใช่แค่ข้อความ SMS เดียว แต่เป็นทั้งแพ็ก (ให้แม่นยำยิ่งขึ้นสาม)!

7 การส่งวัตถุที่ซับซ้อน

ลองคิดดูว่าเราจะถ่ายโอนข้อความจำนวนมากไปยังเซิร์ฟเวอร์ในแพ็กเก็ตเดียวได้อย่างไร วิธีที่ง่ายที่สุดน่าจะเป็นการจัดระเบียบอาร์เรย์ภายในองค์ประกอบ messageList! ลงมือทำกันเถอะ:

// สร้างวัตถุเพื่อส่งไปยังเซิร์ฟเวอร์ $req = new Request(); $req->messageList = รายการข้อความใหม่(); $msg1 = ข้อความใหม่(); $msg1->โทรศัพท์ = "79871234567"; $msg1->text = "ทดสอบข้อความ 1"; $msg1->วันที่ = "2013-07-21T15:00:00.26"; $msg1->ประเภท = 15; $msg2 = ข้อความใหม่(); $msg2->โทรศัพท์ = "79871234567"; $msg2->text = "ทดสอบข้อความ 2"; $msg2->วันที่ = "2014-08-22T16:01:10"; $msg2->ประเภท = 16; $msg3 = ข้อความใหม่(); $msg3->โทรศัพท์ = "79871234567"; $msg3->text = "ทดสอบข้อความ 3"; $msg3->วันที่ = "2014-08-22T16:01:10"; $msg3->ประเภท = 17; $req->messageList->message = $msg1; $req->messageList->ข้อความ = $msg2; $req->messageList->ข้อความ = $msg3;
บันทึกของเราระบุว่าได้รับแพ็กเก็ตต่อไปนี้จากไคลเอนต์:

79871234567 ข้อความทดสอบ 1 2013-07-21T15:00:00.26 15 79871234567 ทดสอบข้อความ 2 2014-08-22T16:01:10 16 79871234567 ทดสอบข้อความที่ 3 2014-08-22T16:01:10 17
คุณพูดอะไรไร้สาระ? และคุณจะคิดถูกเพราะ... ทันทีที่เรารู้ว่ามีวัตถุออกจากไคลเอนต์ มันก็มาถึงเซิร์ฟเวอร์ของเราในรูปแบบเดียวกันโดยสิ้นเชิงในรูปแบบของซองจดหมาย จริงอยู่ ข้อความ SMS ไม่ได้ถูกทำให้เป็นอนุกรมในรูปแบบ XML อย่างที่เราต้องการ - ข้อความเหล่านั้นจะต้องถูกรวมไว้ในองค์ประกอบ ข้อความไม่เข้า โครงสร้าง- ตอนนี้เรามาดูกันว่าวัตถุดังกล่าวมาในรูปแบบใด sendSms:

Object (stdClass) สาธารณะ "messageList" => object (stdClass) สาธารณะ "ข้อความ" => object (stdClass) สาธารณะ "โครงสร้าง" => อาร์เรย์ (ขนาด = 3) 0 => วัตถุ (stdClass) สาธารณะ "โทรศัพท์" => สตริง "79871234567" (length=11) public "text" => string "ทดสอบข้อความ 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "ทดสอบข้อความ 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "โทรศัพท์ " => string "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) สาธารณะ "type" => สตริง "17" (ความยาว = 2)
ความรู้นี้ให้อะไรเราบ้าง? เพียงแต่ว่าเส้นทางที่เราเลือกนั้นไม่ถูกต้องและเราไม่ได้รับคำตอบสำหรับคำถาม - “เราจะรับโครงสร้างข้อมูลที่ถูกต้องบนเซิร์ฟเวอร์ได้อย่างไร” แต่ฉันแนะนำว่าอย่าสิ้นหวังและพยายามแปลงอาเรย์ของเราให้เป็นประเภท วัตถุ:

$req->messageList->message = (วัตถุ)$req->messageList->ข้อความ;
ในกรณีนี้เราจะได้รับซองจดหมายอีกฉบับ:

79871234567 ข้อความทดสอบ 1 2013-07-21T15:00:00.26 15 79871234567 ทดสอบข้อความ 2 2014-08-22T16:01:10 16 79871234567 ทดสอบข้อความที่ 3 2014-08-22T16:01:10 17
เข้ามาเป็นแนวทาง sendSmsวัตถุมีโครงสร้างดังต่อไปนี้:

Object (stdClass) สาธารณะ "messageList" => object (stdClass) สาธารณะ "ข้อความ" => object (stdClass) สาธารณะ "BOGUS" => อาร์เรย์ (ขนาด = 3) 0 => วัตถุ (stdClass) สาธารณะ "โทรศัพท์" => สตริง "79871234567" (length=11) public "text" => string "ทดสอบข้อความ 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "ทดสอบข้อความ 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "โทรศัพท์ " => string "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) สาธารณะ "type" => สตริง "17" (ความยาว = 2)
สำหรับฉัน “ผลรวมไม่เปลี่ยนแปลงจากการเปลี่ยนตำแหน่งของข้อกำหนด” (ค) อะไร ปลอม, อะไร โครงสร้าง– เรายังไม่บรรลุเป้าหมายของเรา! และเพื่อให้บรรลุเป้าหมาย เราต้องแน่ใจว่าแทนที่จะแสดงชื่อที่เข้าใจยากเหล่านี้แทนชื่อพื้นเมืองของเรา ข้อความ- แต่ผู้เขียนยังไม่รู้ว่าจะทำสิ่งนี้ได้อย่างไร ดังนั้นสิ่งเดียวที่เราทำได้คือกำจัดภาชนะส่วนเกินออก กล่าวอีกนัยหนึ่ง ตอนนี้เราจะตรวจสอบให้แน่ใจแทน ข้อความกลายเป็น ปลอม- เมื่อต้องการทำเช่นนี้ เปลี่ยนวัตถุดังนี้:

// สร้างวัตถุเพื่อส่งไปยังเซิร์ฟเวอร์ $req = new Request(); $msg1 = ข้อความใหม่(); $msg1->โทรศัพท์ = "79871234567"; $msg1->text = "ทดสอบข้อความ 1"; $msg1->วันที่ = "2013-07-21T15:00:00.26"; $msg1->ประเภท = 15; $msg2 = ข้อความใหม่(); $msg2->โทรศัพท์ = "79871234567"; $msg2->text = "ทดสอบข้อความ 2"; $msg2->วันที่ = "2014-08-22T16:01:10"; $msg2->ประเภท = 16; $msg3 = ข้อความใหม่(); $msg3->โทรศัพท์ = "79871234567"; $msg3->text = "ทดสอบข้อความ 3"; $msg3->วันที่ = "2014-08-22T16:01:10"; $msg3->ประเภท = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (วัตถุ)$req->messageList;
จะเป็นอย่างไรถ้าเราโชคดีและชื่อที่ถูกต้องปรากฏขึ้นจากแผนภาพล่ะ? เมื่อต้องการทำสิ่งนี้ ลองดูที่ซองจดหมายที่มาถึง:

79871234567 ข้อความทดสอบ 1 2013-07-21T15:00:00.26 15 79871234567 ทดสอบข้อความ 2 2014-08-22T16:01:10 16 79871234567 ทดสอบข้อความที่ 3 2014-08-22T16:01:10 17
ใช่ ปาฏิหาริย์ไม่ได้เกิดขึ้น! ปลอม– เราจะไม่ชนะ! มาถึง sendSmsวัตถุในกรณีนี้จะมีลักษณะดังนี้:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public " text" => string "ข้อความทดสอบ 1" (ความยาว = 37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length =2) 1 => object(stdClass) สาธารณะ "โทรศัพท์" => สตริง "79871234567" (ความยาว = 11) สาธารณะ "ข้อความ" => สตริง "ข้อความทดสอบ 2" (ความยาว = 37) สาธารณะ "วันที่" => สตริง " 2014-08-22T16:01:10" (length=19) สาธารณะ "type" => string "16" (length=2) 2 => object(stdClass) สาธารณะ "phone" => string "79871234567" (length= 11) public "text" => string "ข้อความทดสอบ 3" (ความยาว=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string " 17" (ความยาว=2)
อย่างที่พวกเขาพูด - “เกือบ”! ในบันทึกนี้ (เศร้าเล็กน้อย) ฉันขอเสนอให้ค่อยๆ สรุปและหาข้อสรุปสำหรับตัวเราเอง

8 บทสรุป

ในที่สุดเราก็มาถึงที่นี่! มาดูกันว่าตอนนี้คุณทำอะไรได้บ้าง:
  • คุณสามารถเขียนไฟล์ WSDL ที่จำเป็นสำหรับบริการเว็บของคุณ
  • คุณสามารถเขียนไคลเอนต์ของคุณเองที่สามารถสื่อสารกับเซิร์ฟเวอร์ผ่าน SOAP ได้อย่างง่ายดาย
  • คุณสามารถเขียนเซิร์ฟเวอร์ของคุณเองที่สื่อสารกับโลกภายนอกผ่าน SOAP
  • คุณสามารถส่งอาร์เรย์ของออบเจ็กต์ประเภทเดียวกันไปยังเซิร์ฟเวอร์จากไคลเอ็นต์ของคุณ (โดยมีข้อจำกัดบางประการ)
นอกจากนี้เรายังได้ค้นพบบางอย่างระหว่างการวิจัยเล็กๆ น้อยๆ ของเรา:
  • คลาส SoapClient ดั้งเดิมไม่ถูกต้องทำให้โครงสร้างข้อมูลประเภทเดียวกันใน XML ถูกต้อง
  • เมื่อซีเรียลไลซ์อาร์เรย์เป็น XML มันจะสร้างองค์ประกอบพิเศษที่เรียกว่า โครงสร้าง;
  • เมื่อทำให้วัตถุเป็นอนุกรมเป็น XML มันจะสร้างองค์ประกอบพิเศษที่เรียกว่า ปลอม;
  • ปลอมชั่วร้ายน้อยกว่า โครงสร้างเนื่องจากซองจดหมายมีขนาดกะทัดรัดกว่า (ไม่ได้เพิ่มเนมสเปซเพิ่มเติมในส่วนหัว XML ของซองจดหมาย)
  • ขออภัย คลาส SoapServer ไม่ตรวจสอบข้อมูลเอนเวโลปโดยอัตโนมัติด้วยสคีมา XML ของเรา (บางทีเซิร์ฟเวอร์อื่นอาจไม่ทำเช่นนี้)

ฉันจะไม่อยู่กับคำถามว่ามันคืออะไร บริการเว็บและเหตุใดจึงมีความจำเป็น มีบทความมากมายในหัวข้อนี้บนอินเทอร์เน็ต ฉันจะพยายามแสดงสั้นๆ ว่าการสร้างไคลเอนต์สำหรับบริการเว็บใดๆ ใน PHP นั้นง่ายแค่ไหน

การตั้งค่า

สำหรับการใช้งาน สบู่ใน php คุณต้องเชื่อมต่อโมดูล SOAP (รวมอยู่ในการแจกแจง php5) ใน Windows สิ่งนี้ทำได้ง่ายๆ - คุณต้องเพิ่ม (กล่าวคือ เพิ่ม เนื่องจากบรรทัดนี้ไม่ได้เพิ่งใส่ความคิดเห็นไว้ที่นั่น แต่หายไปทั้งหมด) ใน php.ini:
ส่วนขยาย=php_soap.dll

อย่าลืมรีสตาร์ทเซิร์ฟเวอร์หากคุณติดตั้ง php เป็นโมดูล


การสร้างไคลเอ็นต์ SOAP จากเอกสาร WSDL

การสร้างไคลเอนต์ SOAP มักจะเกิดขึ้นโดย เอกสาร WSDLซึ่งเป็นเอกสาร XML ในรูปแบบเฉพาะที่อธิบายบริการเว็บเฉพาะอย่างครบถ้วน สำหรับรายละเอียดเกี่ยวกับ WSDL ฉันแนะนำให้คุณไปที่เว็บไซต์สมาคม W3C - http://www.w3.org/TR/2005/WD-wsdl20-soap11-binding-20050510/

สิ่งสำคัญที่คุณต้องรู้เพื่อสร้างไคลเอนต์สำหรับบริการเว็บคือการรู้ URL ของเอกสาร WSDL
ตัวอย่างเช่น ใช้บริการเว็บ "อัตราแลกเปลี่ยนสกุลเงิน" จาก xmethods.com ที่อยู่ของบริการบนเว็บนี้ ซึ่งช่วยให้คุณรับอัตราแลกเปลี่ยนออนไลน์คือ http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl

จุดสำคัญที่สองคือจากคำอธิบายของบริการเว็บจำเป็นต้องได้รับข้อมูลเกี่ยวกับวิธีการที่บริการนี้มีให้และพารามิเตอร์ใดที่เราควรส่งไปเป็นค่าอินพุต (คล้ายกับการเรียกใช้ฟังก์ชันหรือคลาส PHP ปกติมาก วิธี). โดยทั่วไปข้อมูลนี้จะอยู่ในคำอธิบายของบริการบนเว็บไซต์ บริการบนเว็บของเราสำหรับการรับอัตราแลกเปลี่ยนมีเมธอด getRate() ซึ่งรหัสสกุลเงินจะถูกส่งผ่านเป็นอาร์กิวเมนต์

และสุดท้าย สิ่งสำคัญคือต้องรู้ว่าจะต้องคาดหวังอะไรเป็นคำตอบ เช่น มีค่าเท่าใด ประเภทใด ฯลฯ นอกจากนี้ยังสามารถหาได้จากคำอธิบาย
และด้วยเหตุนี้ โค้ดจึงดูเรียบง่ายและกะทัดรัด เกือบจะเป็นขั้นพื้นฐาน:

// การใช้บริการเว็บ
// "อัตราแลกเปลี่ยนสกุลเงิน" จาก xmethods.com

// การสร้างไคลเอ็นต์ SOAP จากเอกสาร WSDL
$client = SoapClient ใหม่ ("http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl");

// ส่งคำขอ SOAP และรับผลลัพธ์
$result = $client->getRate("พวกเรา", "รัสเซีย");

Echo 'อัตราแลกเปลี่ยนเงินดอลลาร์ปัจจุบัน: ', $result, ' รูเบิล';
?>

ดังที่คุณเห็นจากโค้ด คุณจะต้องส่ง URL ของเอกสาร WSDL ไปยังตัวสร้างคลาส SoapClient และรับออบเจ็กต์เพื่อทำงานกับบริการเว็บที่ต้องการ จากนั้นจะมีการเรียกเมธอดของออบเจ็กต์นี้ซึ่งมีชื่อเหมือนกับชื่อของวิธีการบริการเว็บนั่นเอง วิธีนี้จะส่งกลับผลลัพธ์ที่เราต้องการ

ตัวอย่างง่ายๆ นี้แสดงให้เห็นถึงหลักการของการสร้างไคลเอ็นต์ SOAP สำหรับบริการเว็บใน PHP อย่างไรก็ตาม ในแอปพลิเคชันจริง ยังมีสิ่งที่ต้องดูแลอีกมาก โดยเฉพาะอย่างยิ่งเมื่อเรียกใช้บริการบนเว็บ อาจไม่พร้อมใช้งานชั่วคราวหรือส่งคืนข้อผิดพลาด แสดงให้เห็นอย่างชัดเจนถึงการใช้บล็อก ลอง/จับ/โยน :)

ที่ LeaseWeb เราทำงานอย่างหนักกับบริการเว็บ SOAP เพื่อรวมแอปพลิเคชันภายในของเราเข้าด้วยกัน โดยเฉพาะอย่างยิ่งในระหว่างการพัฒนาและการทดสอบแอปพลิเคชันของเรา เนื่องจากเราต้องการความสามารถในการฝึกฝนกับ SOAP API

$ curl -sS http://leaseweb.github.io/php-soap-client/installer | PHP

สิ่งนี้จะดาวน์โหลดไฟล์ phar ไปยังไดเร็กทอรีการทำงานปัจจุบันและทำให้สามารถเรียกใช้งานได้เพื่อให้คุณสามารถใช้งานได้ทันทีโดยเรียกใช้:

$ ./soap_client

หากต้องการติดตั้งเวอร์ชันหลักล่าสุด คุณสามารถรับซอร์สโค้ดได้โดยตรงจาก GitHub ทำแพ็กเกจไฟล์ .phar ของคุณเอง และติดตั้งโดยใช้ GNU Make
เพื่อให้สามารถสร้างไฟล์ .phar ได้ คุณต้องติดตั้งผู้แต่งเพลงก่อน หากต้องการอ่านเพิ่มเติมเกี่ยวกับผู้แต่ง โปรดดูเอกสารประกอบที่ยอดเยี่ยมของพวกเขา

# ติดตั้งไคลเอ็นต์ php soap $ git clone https://github.com/LeaseWeb/php-soap-client.git $ cd php-soap-client $ composer.phar ติดตั้ง $ make $ sudo ทำการติดตั้ง

หากคุณได้รับ Failed to Compiled phar ข้อยกเว้นขณะทำงาน make คุณต้องตั้งค่า phar.readonly = Off ใน php.ini ของคุณ บนเครื่องที่กำลังพัฒนา สามารถทำได้ แต่โปรดคำนึงถึงความเสี่ยงด้านความปลอดภัยเมื่อตั้งค่า phar.readonly เป็น Off

คำสั่ง make install ข้างต้นจะติดตั้งแอปพลิเคชัน soap_client ไปที่ /usr/local/bin และทำให้สามารถเรียกใช้งานได้ ดังนั้นคุณจึงสามารถเรียกมันได้อย่างง่ายดายดังนี้:

$ soap_client php-soap-client เวอร์ชัน 2.1.3 การใช้งาน: คำสั่ง ตัวเลือก: ... คำสั่งที่ใช้ได้: โทร เรียกบริการระยะไกลโดยระบุ 'วิธีการ' และส่งเอาต์พุตการตอบสนองต่อ stdout วิธีใช้ แสดงวิธีใช้สำหรับรายการคำสั่ง รายการคำสั่ง รายการ-วิธีการ รับรายการวิธีการที่ใช้ได้เพื่อโทรบนรีโมท request สร้างคำขอ SOAP ที่จัดรูปแบบ xml สำหรับวิธีการที่กำหนดและส่งออกไปยัง stdout wsdl รับ WSDL ของบริการสบู่

จากจุดนี้เป็นต้นไป เราถือว่าคุณได้ติดตั้ง soap_client.phar บนระบบของคุณใน /usr/local/bin/soap_client และไดเร็กทอรี /urs/local/bin อยู่ใน $PATH ของคุณ

สมมติว่าเราต้องการดูว่ามีวิธีการใดบ้างบนบริการระยะไกล http://www.webservicex.net/ConvertTemperature.asmx เราสามารถออกคำสั่งต่อไปนี้:

$ soap_client --endpoint = "http://www.webservicex.net/ConvertTemperature.asmx?WSDL" รายการวิธีการ

ซึ่งจะส่งออกดังต่อไปนี้:

แปลงอุณหภูมิ

หากคุณรันคำสั่งด้านบนด้วยตัวเลือก -vvv คุณจะได้รับเอาต์พุตแบบละเอียดมากขึ้น
ในกรณีนี้ วิธีเดียวที่ใช้ได้คือ ConvertTemp มาดูกันว่าคำขอ SOAP XML มีลักษณะอย่างไรสำหรับวิธีนี้:

$ soap_client --endpoint = "http://www.webservicex.net/ConvertTemperature.asmx?WSDL" ร้องขอ ConvertTemp 0

หากคุณต้องการส่งคำขอ SOAP ไปยังวิธี ConvertTemp บนบริการระยะไกล ให้ใช้คำสั่งย่อย call:

$ soap_client --endpoint = "http://www.webservicex.net/ConvertTemperature.asmx?WSDL" โทร --editor ConvertTemp

สังเกตตัวเลือก --editor หลังคำสั่งย่อย call หากคุณใช้แฟล็ก --editor soap_client จะเปิดตัวแก้ไขที่ระบุในตัวแปรสภาพแวดล้อมของคุณ $EDITOR เพื่อให้คุณสามารถแก้ไข XML คำขอก่อนส่งได้

หากคุณออกคำขอเดียวกันหลายครั้ง คุณสามารถบันทึกคำขอ Soap เป็นไฟล์ XML ในเครื่องและส่งผ่านไปยัง /dev/stdin ของคำสั่งโทร soap_client:

# รับคำขอ xml และเก็บไว้ในเครื่อง $ soap_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" คำขอ ConvertTemp > my_sample_request.xml # ตอนนี้แก้ไข my_sample_request.xml # ตอนนี้คุณสามารถเรียก วิธีการ ConvertTemp พร้อมคำขอที่เตรียมไว้ล่วงหน้านี้ $ soap_client --endpoint="http://www.webservicex.net/ConvertTemperature.asmx?WSDL" เรียก ConvertTemp< my_sample_request.xml

เนื่องจากคุณจะทำซ้ำคำสั่ง soap_client บ่อยครั้งในช่วงเวลาสั้นๆ ในขณะที่สำรวจบริการเว็บระยะไกล คุณจึงประหยัดเวลาได้ด้วยการตั้งค่าตัวแปรสภาพแวดล้อม SOAPCLIENT_ENDPOINT ที่มี URL ไปยัง WSDL เมื่อตั้งค่าตัวแปรสภาพแวดล้อมนี้ คุณสามารถละเว้นตัวเลือกบรรทัดคำสั่ง --endpoint ได้ มาทำตอนนี้แล้วเรียกวิธี ConvertTemp:

$ ส่งออก SOAPCLIENT_ENDPOINT = "http://www.webservicex.net/ConvertTemperature.asmx?WSDL" $ soap_client โทร ConvertTemp< my_sample_request.xml

ฉันอยากรู้ว่า 107.6 องศาฟาเรนไฮต์มีหน่วยเป็นเซลเซียสเท่าใด ดังนั้น my_sample_request.xml ของฉันจึงมี:

$ แมว my_sample_request.xml 107.6 องศาฟาเรนไฮต์ องศาเซลเซียส

$ soap_client โทร ConvertTemp< my_sample_request.xml stdClass Object ( => 42)

คำตอบคือ 42

หากคุณต้องการเห็นการตอบกลับในรูปแบบ XML คุณสามารถใช้ตัวเลือกบรรทัดคำสั่ง --xml:

$ soap_client โทร --xml ConvertTemp< my_sample_request.xml 42

บทช่วยสอนนี้ควรให้ข้อมูลที่เพียงพอแก่คุณเพื่อเริ่มต้นการสำรวจ ทดสอบ และ/หรือพัฒนา SOAP API
ในโพสต์บล็อกในอนาคต ฉันจะดำเนินการต่อในหัวข้อไคลเอนต์ php soap ขณะนี้เรากำลังดำเนินการบรรจุไฟล์เก็บถาวร .phar สำหรับเว็บ

ส่วนที่เป็นโคลงสั้น ๆ

ลองนึกภาพว่าคุณได้ดำเนินการหรือกำลังใช้ระบบบางอย่างที่ควรสามารถเข้าถึงได้จากภายนอก เหล่านั้น. มีเซิร์ฟเวอร์บางตัวที่คุณต้องสื่อสารด้วย ยกตัวอย่างเว็บเซิร์ฟเวอร์

เซิร์ฟเวอร์นี้สามารถดำเนินการได้หลายอย่าง ทำงานกับฐานข้อมูล ดำเนินการคำขอของบุคคลที่สามไปยังเซิร์ฟเวอร์อื่น ทำการคำนวณบางอย่าง ฯลฯ มีชีวิตอยู่และอาจพัฒนาตามสถานการณ์ที่เขารู้จัก (เช่น ตามสถานการณ์ของนักพัฒนา) มันไม่น่าสนใจสำหรับบุคคลที่จะสื่อสารกับเซิร์ฟเวอร์ดังกล่าว เพราะเขาอาจไม่สามารถ/ต้องการให้เพจที่สวยงามพร้อมรูปภาพและเนื้อหาที่เป็นมิตรต่อผู้ใช้อื่นๆ มันถูกเขียนขึ้นและทำงานและให้ข้อมูลเมื่อถูกถาม โดยไม่ต้องกังวลว่ามนุษย์จะอ่านได้ ลูกค้าจะจัดการกับมันเอง

ระบบอื่นที่เข้าถึงเซิร์ฟเวอร์นี้สามารถกำจัดข้อมูลที่ได้รับจากเซิร์ฟเวอร์นี้ได้ตามดุลยพินิจของตนเอง - ดำเนินการ สะสม ออกให้กับลูกค้า ฯลฯ

หนึ่งในตัวเลือกสำหรับการสื่อสารกับเซิร์ฟเวอร์ดังกล่าวคือ SOAP โปรโตคอลการแลกเปลี่ยนข้อความ SOAP xml

ส่วนการปฏิบัติ

บริการเว็บ (นี่คือชื่อของสิ่งที่เซิร์ฟเวอร์ให้และสิ่งที่ลูกค้าใช้) ทำให้สามารถสื่อสารกับเซิร์ฟเวอร์ด้วยข้อความที่มีโครงสร้างชัดเจน ความจริงก็คือบริการเว็บไม่ยอมรับข้อมูลใดๆ บริการเว็บจะตอบกลับพร้อมข้อผิดพลาดต่อข้อความใด ๆ ที่ไม่เป็นไปตามกฎ ข้อผิดพลาดจะอยู่ในรูปแบบ xml พร้อมโครงสร้างที่ชัดเจน (ซึ่งไม่เป็นความจริงเกี่ยวกับข้อความ)

WSDL (ภาษาคำอธิบายบริการเว็บ) กฎที่ใช้ประกอบข้อความสำหรับบริการเว็บนั้นอธิบายโดยใช้ xml และมีโครงสร้างที่ชัดเจนด้วย เหล่านั้น. หากบริการเว็บมีความสามารถในการเรียกใช้เมธอด จะต้องอนุญาตให้ไคลเอ็นต์ทราบว่าพารามิเตอร์ใดที่ใช้สำหรับเมธอดนี้ ถ้าบริการเว็บคาดหวังสตริงสำหรับ Method1 เป็นพารามิเตอร์ และสตริงควรตั้งชื่อ Param1 จากนั้นกฎเหล่านี้จะถูกระบุในคำอธิบายบริการเว็บ

ไม่เพียงแต่ประเภทธรรมดาเท่านั้น แต่ยังสามารถส่งอ็อบเจ็กต์และคอลเลกชันของอ็อบเจ็กต์เป็นพารามิเตอร์ได้อีกด้วย คำอธิบายของออบเจ็กต์ลงมาจนถึงคำอธิบายของแต่ละองค์ประกอบของออบเจ็กต์ หากวัตถุประกอบด้วยหลายฟิลด์ แต่ละฟิลด์จะถูกอธิบาย ประเภท ชื่อ (ค่าที่เป็นไปได้คืออะไร) ฟิลด์อาจเป็นประเภทที่ซับซ้อนได้และต่อ ๆ ไปจนกว่าคำอธิบายของประเภทจะลงท้ายด้วยรายการแบบง่าย - สตริง, บูลีน, ตัวเลข, วันที่... อย่างไรก็ตาม บางประเภทอาจกลายเป็นเรื่องง่าย สิ่งสำคัญคือลูกค้า สามารถเข้าใจคุณค่าที่อาจมีได้

สำหรับลูกค้าก็เพียงพอที่จะทราบ URL ของบริการบนเว็บแล้ว wsdl จะอยู่ใกล้เคียงเสมอซึ่งคุณสามารถทราบวิธีการและพารามิเตอร์ที่บริการบนเว็บนี้มีให้

ข้อดีของระฆังและนกหวีดเหล่านี้คืออะไร:

  • ในระบบส่วนใหญ่ คำอธิบายของวิธีการและประเภทจะเกิดขึ้นโดยอัตโนมัติ เหล่านั้น. โปรแกรมเมอร์บนเซิร์ฟเวอร์เพียงแค่ต้องบอกว่าวิธีนี้สามารถเรียกผ่านบริการเว็บได้ และคำอธิบาย wsdl จะถูกสร้างขึ้นโดยอัตโนมัติ
  • คำอธิบายซึ่งมีโครงสร้างที่ชัดเจน ลูกค้าสบู่ทุกคนสามารถอ่านได้ เหล่านั้น. ไม่ว่าจะเป็นบริการเว็บใดก็ตาม ลูกค้าจะเข้าใจว่าบริการเว็บได้รับข้อมูลใดบ้าง การใช้คำอธิบายนี้ ไคลเอ็นต์สามารถสร้างโครงสร้างภายในของคลาสอ็อบเจ็กต์ของตนเอง ที่เรียกว่า การผูกมัด" และด้วยเหตุนี้โปรแกรมเมอร์ที่ใช้บริการเว็บจึงต้องเขียนอะไรประมาณนี้ (pseudocode):

    ผู้ใช้ใหม่:=TSoapUser.Create("Vasya", "Pupkin", "ผู้ดูแลระบบ"); soap.AddUser(ผู้ใช้ใหม่);

  • การตรวจสอบอัตโนมัติ

    • การตรวจสอบ xml xml ต้องมีรูปแบบที่ถูกต้อง xml ไม่ถูกต้อง - เกิดข้อผิดพลาดกับไคลเอนต์ทันที ให้เขาจัดการมัน
    • การตรวจสอบสคีมา xml ต้องมีโครงสร้างที่แน่นอน xml ไม่ตรงกับสคีมา - เกิดข้อผิดพลาดกับไคลเอนต์ทันที ให้เขาจัดการมันซะ
    • การตรวจสอบข้อมูลดำเนินการโดยเซิร์ฟเวอร์สบู่เพื่อให้ประเภทข้อมูลและข้อจำกัดตรงกับคำอธิบาย
  • การอนุญาตและการรับรองความถูกต้องสามารถทำได้โดยใช้วิธีการแยกต่างหาก โดยกำเนิด หรือใช้การอนุญาต http
  • บริการเว็บสามารถทำงานได้ทั้งผ่านโปรโตคอลสบู่และผ่าน http นั่นคือผ่านการร้องขอ นั่นคือหากพารามิเตอร์เป็นข้อมูลธรรมดา (ไม่มีโครงสร้าง) คุณสามารถเรียกตามปกติได้ www.site.com/users.asmx/GetUser?Name=Vasia หรือโพสต์ อย่างไรก็ตาม นี่ไม่ใช่ทุกที่และไม่เสมอไป
  • ... ดูในวิกิพีเดีย

นอกจากนี้ยังมีข้อเสียมากมาย:

  • ขนาดข้อความใหญ่เกินสมควร ตรงนี้ธรรมชาติของ xml คือรูปแบบที่ซ้ำซ้อน ยิ่งมีแท็กมาก ข้อมูลก็ยิ่งไร้ประโยชน์ พลัสสบู่เพิ่มความซ้ำซ้อน สำหรับระบบอินทราเน็ต ปัญหาการรับส่งข้อมูลจะรุนแรงน้อยกว่าอินเทอร์เน็ต ดังนั้นสบู่สำหรับเครือข่ายท้องถิ่นจึงเป็นที่ต้องการมากกว่า โดยเฉพาะ Sharepoint มีบริการเว็บสบู่ที่คุณสามารถสื่อสารได้อย่างประสบความสำเร็จ (และข้อจำกัดบางประการ)
  • การเปลี่ยนคำอธิบายของบริการเว็บโดยอัตโนมัติอาจทำให้ไคลเอนต์ทั้งหมดเสียหายได้ มันก็เป็นเช่นนี้สำหรับระบบใดๆ ก็ตาม หากไม่รองรับความเข้ากันได้แบบย้อนหลังกับวิธีการแบบเก่า ทุกอย่างจะล้มเหลว...
  • ไม่ใช่ข้อเสีย แต่เป็นข้อเสียเปรียบ การเรียกเมธอดทั้งหมดต้องเป็นอะตอมมิก ตัวอย่างเช่น เมื่อทำงานกับฐานข้อมูล เราสามารถเริ่มธุรกรรม ดำเนินการหลาย ๆ คำสั่ง จากนั้นย้อนกลับหรือคอมมิต ไม่มีธุรกรรมในสบู่ หนึ่งคำขอ หนึ่งคำตอบ บทสนทนาจบลง
  • การจัดการกับคำอธิบายของสิ่งที่อยู่บนฝั่งเซิร์ฟเวอร์ (ทุกอย่างอธิบายถูกต้องหรือไม่) และสิ่งที่อยู่บนไคลเอนต์ (สิ่งที่อธิบายให้ฉันฟังที่นี่) อาจเป็นเรื่องยาก มีหลายครั้งที่ฉันต้องจัดการกับฝั่งไคลเอ็นต์และโน้มน้าวโปรแกรมเมอร์เซิร์ฟเวอร์ว่าข้อมูลของเขาอธิบายไม่ถูกต้อง แต่เขาไม่เข้าใจอะไรเลยเกี่ยวกับเรื่องนี้เลย เพราะการสร้างอัตโนมัติและเขาไม่ควรทำเช่นนั้น มันเป็นเรื่องของ ซอฟต์แวร์. และแน่นอนว่าข้อผิดพลาดนั้นอยู่ในโค้ดวิธีการโปรแกรมเมอร์ก็ไม่เห็นมัน
  • การปฏิบัติแสดงให้เห็นว่านักพัฒนาบริการเว็บอยู่ห่างไกลจากผู้ที่ใช้บริการเว็บเหล่านี้อย่างมาก เพื่อตอบสนองต่อคำขอใด ๆ (ถูกต้องจากภายนอก) อาจเกิดข้อผิดพลาดที่ไม่สามารถเข้าใจได้ "ข้อผิดพลาด 5 ทุกอย่างไม่ดี" ทุกอย่างขึ้นอยู่กับจิตสำนึกของนักพัฒนา :)
  • ฉันแน่ใจว่าฉันยังจำอะไรบางอย่างไม่ได้ ...

ตัวอย่างเช่น มีบริการเว็บแบบเปิด belvia:

  • http://86.57.245.235/TimeTable/Service.asmx - จุดเริ่มต้น นอกจากนี้ยังมีข้อความคำอธิบายวิธีการสำหรับนักพัฒนาบุคคลที่สาม
  • http://86.57.245.235/TimeTable/Service.asmx?WSDL - คำอธิบาย wsdl ของวิธีการและประเภทของข้อมูลที่ได้รับและส่งคืน
  • http://86.57.245.235/TimeTable/Service.asmx?op=GetAirportsList - คำอธิบายวิธีการเฉพาะพร้อมตัวอย่างประเภทคำขอ xml และการตอบสนอง xml

คุณสามารถสร้างและส่งคำขอได้ด้วยตนเอง เช่น:

POST /TimeTable/Service.asmx โฮสต์ HTTP/1.1: 86.57.245.235 ประเภทเนื้อหา: ข้อความ/xml; charset=utf-8 ความยาวเนื้อหา: ความยาว SOAPAction: "http://webservices.belavia.by/GetAirportsList" รุ

คำตอบจะมา:

HTTP/1.1 200 ตกลง วันที่: จันทร์ 30 กันยายน 2556 00:06:44 GMT เซิร์ฟเวอร์: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 การควบคุมแคช: ส่วนตัว สูงสุด -age=0 ประเภทเนื้อหา: text/xml; charset=utf-8 ความยาวเนื้อหา: 2940

ป.ล. ก่อนหน้านี้บริการเว็บของ Aeroflot ได้เปิดขึ้นแล้ว แต่หลังจาก 1C เพิ่มการรองรับสบู่ให้กับ 8ku ผู้ทดสอบเบต้า 1C กลุ่มหนึ่งก็ติดตั้งได้สำเร็จ ตอนนี้มีบางอย่างเปลี่ยนแปลงไปที่นั่น (ฉันไม่ทราบที่อยู่ คุณสามารถดูได้หากคุณสนใจ)
ข้อจำกัดความรับผิดชอบ ZZY เขาพูดในระดับชีวิตประจำวัน คุณสามารถเตะได้

มุมมอง