ส่วนเนื้อเพลง.

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

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

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

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

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

  • 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

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

สวัสดีทุกคน!
มันเกิดขึ้นเมื่อเมื่อเร็ว ๆ นี้ฉันได้มีส่วนร่วมในการพัฒนาบริการเว็บ แต่วันนี้หัวข้อไม่เกี่ยวกับฉัน แต่เกี่ยวกับวิธีที่เราสามารถเขียน 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 ถึงสมาชิก
  • ประเภทข้อความ

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

  • 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 เท่านั้น) และคุณรู้ไหมว่าฉันชอบอะไรมากที่สุดเกี่ยวกับเรื่องทั้งหมดนี้? หากไม่มีการคาดเดาฉันจะให้คำแนะนำแก่คุณ - SOAP!… ไม่มีการเดาอีกต่อไป… คุณอ่านบทความใน Wikipedia แน่นอนหรือไม่… โดยทั่วไปแล้วฉันจะไม่ทรมานคุณอีกต่อไป ดังนั้นฉันจะไปที่คำตอบทันที: “ SOAP (จากภาษาอังกฤษ Simple Object Access Protocol - แบบง่าย มาตรการการเข้าถึงวัตถุ จนถึงข้อกำหนด 1.2)". จุดเด่นของบรรทัดนี้คือตัวเอียง! ฉันไม่รู้ว่าคุณได้ข้อสรุปอะไรจากทั้งหมดนี้ แต่ฉันเห็นสิ่งต่อไปนี้ - เนื่องจากโปรโตคอลนี้ไม่สามารถเรียกว่า "เรียบง่าย" ได้ด้วยวิธีใด (และเห็นได้ชัดว่าแม้แต่ w3 ก็เห็นด้วยกับสิ่งนี้) ดังนั้นตั้งแต่เวอร์ชัน 1.2 ก็หยุดเป็น ถอดรหัสเลย! และกลายเป็นที่รู้จักในชื่อ SOAP เพียง SOAP และระยะเวลา

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

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

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 Schemas: ทางเลือก" และ " ทั้งหมด". นักแต่งเพลง ทางเลือก" บ่งบอกว่าควรมีองค์ประกอบอย่างใดอย่างหนึ่งอยู่ในรายการและผู้แต่ง " ทั้งหมด» – การรวมกันขององค์ประกอบที่ระบุไว้

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

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

เมื่อต้องการทำเช่นนี้ จะแสดงรายการการดำเนินการใดและในรูปแบบใดที่ y จะถูกเรียกว่า เหล่านั้น. สำหรับท่าเรือ 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) สาธารณะ "messageList" => object (stdClass) สาธารณะ "BOGUS" => อาร์เรย์ (ขนาด = 3) 0 => object (stdClass) สาธารณะ "โทรศัพท์" => สตริง "79871234567" (ความยาว = 11) สาธารณะ " 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 ของเรา (เซิร์ฟเวอร์อื่นอาจไม่ตรวจสอบเช่นกัน)

ที่ 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 client ขณะนี้เรากำลังดำเนินการบรรจุไฟล์เก็บถาวร .phar สำหรับเว็บ

ฉันจะไม่จมอยู่กับคำถามว่าอะไร บริการเว็บและเหตุใดจึงมีความจำเป็น มีบทความมากมายบนเว็บในหัวข้อนี้ ฉันจะพยายามแสดงสั้น ๆ ว่าการสร้างไคลเอนต์ไปยังบริการเว็บใด ๆ ใน 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 อย่างไรก็ตามในการใช้งานจริงยังมีหลายสิ่งที่ต้องดูแล โดยเฉพาะอย่างยิ่งในขณะที่เข้าถึงบริการบนเว็บอาจไม่สามารถใช้งานได้ชั่วคราวหรือส่งคืนข้อผิดพลาด การใช้บล็อกแสดงให้เห็นอย่างชัดเจน ลอง/จับ/โยน :)

การแปลของ 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 2nd Edition" เต็มไปด้วยช่องว่างมากมาย คุณจะพบคำตอบสำหรับคำถามมากมายที่เกิดขึ้นหลังจากอ่านบทความนี้ในหนังสือ

การแนะนำ

ก่อนอื่นคุณต้องเข้าใจว่า 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 หลัก รวมถึงข้อมูลเกี่ยวกับผู้รับและผู้ส่ง ตลอดจนข้อมูลเกี่ยวกับตัวข้อความเอง ตัวอย่างเช่น ส่วนหัวของเอนเวโลป 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 เพื่อระบุประเภทข้อมูลใหม่ได้อย่างง่ายดาย (โดยใช้ struct ประเภทที่ซับซ้อนตามที่กล่าวไว้ในบทที่ 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 = 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 = new Call(); call.setTargetObjectURI("โกศ:xmltoday-airline-tickets"); call.setMethodName("ซื้อตั๋ว"); call.setEncodingStyleURI (ค่าคงที่ NS_URI_SOAP_ENC); โทร 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) ใช้ codebase เดียวกัน

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 จากนั้นรวม jars ไว้ใน 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 จะถูกโหลดก่อนตัวแยกวิเคราะห์หรือการใช้งาน 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). และสุดท้ายคือ curalesil พร้อมคุณสมบัติ java2XMLClassNameและ xml2JavaClassName.xml2JavaClassName. พวกเขากำหนดคลาสที่แปลงจาก Java เป็น XML และในทางกลับกัน ฉันใช้คลาส BeanSerializer ที่มีประโยชน์อย่างเหลือเชื่อ ซึ่งรวมอยู่ใน Apache SOAP ด้วย หากพารามิเตอร์ที่คุณกำหนดเองอยู่ในรูปแบบ JavaBean ตัวซีเรียลไลเซอร์และดีซีเรียลไลเซอร์นี้จะช่วยคุณประหยัดเวลาในการเขียนของคุณเอง คุณต้องมีคลาสที่มีคอนสตรัคเตอร์เริ่มต้น (จำไว้ว่าฉันให้คลาสซีดีเป็นคอนสตรัคเตอร์แบบไม่มีพารามิเตอร์) และเผยแพร่ข้อมูลทั้งหมดของคลาสนั้นโดยใช้วิธีการ 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));โทร 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 Studio การเพิ่มซีดีสำเร็จ

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

หมายเหตุ: คุณสามารถตัดสินใจได้เพราะว่าชั้นเรียน ซีดีลิสเตอร์ไม่โต้ตอบกับวัตถุโดยตรง ซีดี(ส่งคืนโดยวิธี รายการ()ประเภทมีความสำคัญ แฮชเทเบิล) คุณไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ อย่างไรก็ตามชั้นกลับ แฮชเทเบิลมีอินสแตนซ์ของวัตถุ ซีดี. ถ้า 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 (โมเดลวัตถุเอกสาร) 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(วิธีการดั้งเดิม) ถึง java.lang.Class.newInstance(Class.java:237)

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

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