Hiểu biết về Đặc tả các dịch vụ Web, Phần 1: SOAP

Tầm quan trọng hiện tại đối với SOA (Service-Oriented Architectures - Các kiến trúc hướng dịch vụ) đã diễn tả địa vị nổi bật về các dịch vụ Web, nhưng thật dễ dàng đi lạc trên tất cả thông tin đang được bàn tán đó. Loạt bài này mang đến cho bạn câu chuyện trung thực về tất cả các đặc tả dịch vụ Web chủ yếu, bắt đầu với SOAP (Simple Object Access Protocol – Giao thức truy cập đối tượng đơn giản) và xuống tới WS-BPEL (WS Business Process Execution Language - Ngôn ngữ thực thi qui trình nghiệp vụ WS). Hướng dẫn này giải thích các khái niệm cơ bản về các dịch vụ Web và SOAP và giải thích cách xây dựng một máy chủ và ứng dụng khách SOAP.

Nicholas Chase, Tác giả tự do, Site Dynamics Interactive Communications

Nicholas Chase đã phát triển trang web cho các công ty lớn như Lucent Technologies, Sun Microsystems, Oracle, và Tampa Bay Buccaneers. Nick đã từng là một giáo viên vật lý ở trường phổ thông, một nhà quản lý thiết bị phóng xạ mức thấp, một nhà biên tập tạp chí khoa học viễn tưởng trực tuyến, một kỹ sư đa phương tiện, một hướng dẫn của Oracle, và một trưởng phòng công nghệ của một công ty tương tác truyền thông. Nick là tác giả của một số sách



08 10 2010

Trước khi bạn bắt đầu

Loạt bài hướng dẫn này ghi lại việc xây dựng một hệ thống tiến trình công việc dựa trên các dịch vụ Web cho một tờ báo hư cấu nhỏ, có tên là Daily Moon (Mặt Trăng hàng ngày). Loạt bài này dành cho các nhà phát triển, những người muốn tìm hiểu thêm về những khái niệm làm cơ sở cho các dịch vụ Web, để họ có thể tạo ra các ứng dụng cho các dịch vụ Web hiệu quả hơn. Những người sử dụng không phải làm kỹ thuật cũng sẽ tìm thấy tác dụng trong các hướng dẫn này, vì các hướng dẫn này giải thích các khái niệm trước khi tiến vào lập trình.

Bạn cần có một sự hiểu biết cơ bản về lập trình và nếu bạn muốn theo cùng với các ví dụ lập trình thực tế, cần hiểu rõ Java. Chúng tôi sẽ nói về XML, ngoài sự cần thiết, nhưng chúng tôi sẽ không khai thác sâu vào nó và bất cứ các khái niệm cần thiết nào sẽ được trình bày.

Về loạt bài này

Loạt bài hướng dẫn này dạy các khái niệm cơ bản về các dịch vụ Web bằng cách tiếp tục khai thác về tờ báo hư cấu Daily Moon, khi các nhân viên sử dụng các dịch vụ Web để tạo ra một hệ thống tiến trình công việc để tăng năng suất trong những thời điểm có nhiều thay đổi này.

Phần đầu tiên này bắt đầu đơn giản, khi giải thích các khái niệm cơ bản đằng sau các dịch vụ Web và hiển thị cho bạn cách sử dụng SOAP, đặc tả làm cơ sở cho hầu hết những gì đang đến, kết nối phòng chuyên mục rao vặt với Hệ thống quản lý nội dung.

Các bài đăng tương lai trong loạt bài này sẽ xây dựng theo các khái niệm cơ bản:

  • Phần 2 đưa mọi thứ đi xa hơn một bước, khi giải thích cách sử dụng WSDL (Web Services Description Language - Ngôn ngữ mô tả dịch vụ Web) để định nghĩa các thông báo được các dịch vụ Web tạo ra như mong đợi, cho phép nhóm làm việc tạo ra các dịch vụ và các ứng dụng khách kết nối với chúng dễ dàng hơn.
  • Phần 3 tìm nhóm làm việc với một số dịch vụ tại chỗ và một mong muốn để định vị các dịch vụ dễ dàng. Đáp lại, UDDI (Universal Description, Discovery and Integration - Tích hợp, khám phá và mô tả đa năng) cung cấp một đăng ký tìm kiếm của các dịch vụ có sẵn như là một cách đưa ra công khai các dịch vụ riêng của chúng cho những người khác.
  • Phần 4 và 5, Các dịch vụ Web-An ninh (WS-Security) và Các dịch vụ Web-Chính sách (WS-Policy), ghi lại an ninh của các dịch vụ của tờ báo và những thay đổi mà các nhóm làm việc cần thực hiện để truy cập các dịch vụ mới được bảo vệ đó.
  • Tính tương thích là từ khóa trong phần 6, do các dịch vụ từ các sự hiện thực khác nhau phải được truy cập từ một hệ thống duy nhất. Phần 6 trình bày các yêu cầu và các thử nghiệm liên quan đến việc cấp chứng chỉ Các dịch vụ Web-Tính tương thích (WS-I).
  • Cuối cùng, phần 7 dạy cách sử dụng WS-BPEL để tạo các ứng dụng phức tạp từ các dịch vụ riêng biệt.

Bây giờ hãy xem xét hướng dẫn này trình bày những gì cụ thể hơn một chút.

Về hướng dẫn này

Hướng dẫn này giới thiệu cho bạn khái niệm về các dịch vụ Web và nhóm làm việc tại Phòng chuyên mục rao vặt của tờ báo hư cấu Daily Moon của chúng ta. Bạn sẽ làm theo cùng khi nhóm làm việc kết hợp với một hệ thống các dịch vụ Web hiện có và chứng kiến việc tạo ra một dịch vụ. Tập trung vào SOAP (Giao thức truy cập đối tượng đơn giản).

Trong tiến trình của hướng dẫn này, bạn sẽ học như sau:

  • Các khái niệm cơ bản về các dịch vụ Web.
  • Những vấn đề cơ bản của XML.
  • Cấu trúc và mục đích của một thông báo SOAP.
  • Cách cài đặt một máy chủ ứng dụng trên đó chạy các ứng dụng dịch vụ Web của bạn.
  • Cách cài đặt một bản thực hiện dịch vụ Web vào trong một máy chủ ứng dụng.
  • Cách tạo một thông báo SOAP bằng lập trình.
  • Cách tạo một ứng dụng khách cho một dịch vụ web dựa trên SOAP bằng cách sử dụng Java và Apache Axis2.
  • Cách tạo một Java và Apache Axis2 của dịch vụ web dựa trên SOAP.

Trong hướng dẫn này, Phòng chuyên mục rao vặt sẽ tích hợp với hệ thống quản lý nội dung, tạo một ứng dụng khách. Ngoài ra bạn sẽ xem xét quá trình tạo một trong các dịch vụ mà phòng này có tương tác với dịch vụ đó. Các ví dụ lập trình được hiển thị bằng Java khi sử dụng dự án Axis2 của Apache, nhưng các khái niệm này áp dụng một cách chính thức cho ngôn ngữ và môi trường khác bất kỳ.

Điều kiện cần trước

Để làm theo cùng với mã trong hướng dẫn này, bạn sẽ cần có sẵn phần mềm sau đây:

  • Máy chủ Apache Geronimo hoặc máy chủ ứng dụng khác. Bạn sẽ tạo nhiều dịch vụ Web trong suốt tiến trình của hướng dẫn này và bạn sẽ cần một ứng dụng để chạy chúng trên đó. Tất nhiên, do các dịch vụ Web được hỗ trợ để có khả năng tương thích với nhau, nên việc bạn sử dụng một dịch vụ nào là không thực sự quan trọng. Trong hướng dẫn này, chúng tôi sẽ giải thích cách cài đặt và sử dụng máy chủ Apache Geronimo, cũng là ấn bản cộng đồng WebSphere của IBM (IBM® WebSphere® Community Edition). Bạn cũng có thể sử dụng các máy chủ ứng dụng khác như Máy chủ ứng dụng WebSphere (WebSphere Application Server). Bạn có thể tải Apache Geronimo từ trang web Tải Apache Geronimo.
  • Việc thực hiện Apache Axis2 hoặc SOAP. Bạn có thể tạo các thông báo SOAP bằng tay và bạn có thể giải thích chúng bằng tay, nhưng để có một sự thực hiện tiện dụng thì dễ dàng hơn nhiều. Bạn sẽ sử dụng Apache Axis2, bao gồm các việc thực hiện của các API có liên quan đến SOAP khác nhau để làm cho cuộc sống của bạn dễ dàng hơn đáng kể. Bạn có thể tải Apache Axis2 tại: Apache.org. Hướng dẫn này sử dụng phiên bản 0.94, nhưng các phiên bản sau này cũng sẽ dùng được.
  • Java™ 2 Standard Edition (Ấn bản tiêu chuẩn Java 2) phiên bản 1.4 hoặc cao hơn. Cả hai trong số những công cụ này dựa trên Java, như là các dịch vụ và các ứng dụng khách mà bạn sẽ xây dựng trong hướng dẫn này. Bạn có thể tải J2SE SDK từ đây.
  • Bạn cũng sẽ cần một trình duyệt Web và một trình soạn thảo văn bản, nhưng tôi chắc chắn rằng bạn đã có chúng rồi. Nếu bạn muốn, bạn cũng có thể sử dụng một IDE như Eclipse, nhưng do tập trung vào các công nghệ hơn là các công cụ, nên tôi sẽ chỉ sử dụng một trình soạn thảo văn bản và dòng lệnh để chỉnh sửa các tệp và biên dịch chúng.

Các dịch vụ Web là gì?

Hãy bắt đầu bằng cách xem xét toàn cảnh về các dịch vụ Web thực sự là gì và tại sao chúng lại quan trọng cho sự phát triển phần mềm.

Vậy thì chuyện lớn là gì?

Nếu bạn vẫn chưa nghe nhiều và rất nhiều thông tin về SOA (kiến trúc định hướng dịch vụ) và các dịch vụ Web, thì bạn sẽ không ở đây, vì vậy câu hỏi là, tại sao SOA là một chuyện lớn như vậy? Câu trả lời là SOA là một chuyện lớn vì nó là một sự chuyển đổi mô hình theo cách mà các ứng dụng truyền thông với nhau. Các SOA đã nổi lên lâu lắm rồi. Ban đầu chúng gồm hầu hết các ứng dụng phần mềm trung gian (middleware), một loại phần mềm trung gian duy nhất sở hữu các ứng dụng đó, ít nhất, trên cả hai đầu của đường dây. Mặt khác, các dịch vụ Web gồm một nhóm các tiêu chuẩn có ý định làm cho nhóm đó có thể dùng để truyền thông cho nhiều hệ thống khác nhau, mà không đòi hỏi một loại phần mềm trung gian, ngôn ngữ lập trình hoặc thậm chí là hệ điều hành cụ thể. Hãy xem xét sự phát triển từ nơi mà chúng ta đã bắt đầu đến nơi mà chúng ta có bây giờ.

Các ứng dụng truyền thống

Lúc bắt đầu, đã có các máy tính. Và nó đã hoạt động rất tốt. Các máy tính có vẻ đã thực hiện các nhiệm vụ phi thường, tự động hoá rất nhiều thứ mà mọi người đã phải làm bằng tay, bắt đầu với các tính toán phức tạp và chuyển sang tài chính và nhiều nhiệm vụ khác.

Nhưng các ứng dụng truyền thống là "các tháp cao". Ứng dụng nguồn nhân lực có thể không thực sự nói về ứng dụng tài chính, mà ứng dụng tài chính có thể không thực sự nói về ứng dụng phân phối. Tất cả các ứng dụng này đã có nhà riêng của mình, trên máy tính của riêng mình và trong khi chúng đã rất có ích, nhưng vẫn chưa có một cách hay để chia sẻ dữ liệu giữa chúng. Bạn đã có tùy chọn để viết các quy trình bó (batch) để chuyển dữ liệu từ một hệ thống này đến một hệ thống khác, nhưng điều đó không thay thế cho việc tích hợp thời gian thực.

Tính toán phân tán

Bước tiếp theo trong chuỗi tiến hóa của chúng ta là tính toán phân tán. Tính toán phân tán đã cho phép các ứng dụng khác nhau nói chuyện với nhau, ngay cả khi chúng không ở trên cùng một máy tính. Các công nghệ như CORBA, MTS và EJB (Enterprise Java Beans), đã cung cấp một hệ thống bao gồm một đăng ký về các loại để cho các ứng dụng có thể tìm thấy các thành phần mà chúng muốn tương tác và sau đó gọi các thành phần này như thể chúng đang nằm trên máy cục bộ.

Các hệ thống này đã được phần mềm trung gian hỗ trợ, hoặc cụ thể hơn, phần mềm trung gian hướng-thông báo, cung cấp cả hai yêu cầu này. Các ứng dụng bây giờ có thể được xây dựng theo cách mà chúng có thể truy cập tài nguyên trên các hệ thống khác, ngay cả khi chúng đang ở các vị trí địa lý khác nhau.

Nhưng vẫn còn có một vấn đề. Trong khi các ứng dụng tự do truyền thông bất cứ nơi nào trong hệ thống, thì hệ thống vẫn còn là hệ thống khép kín. Ít nhất, ứng dụng khách của bạn đã phải sử dụng cùng một công nghệ như là ứng dụng máy chủ. Ngoài ra, các hệ thống không được thiết kế, theo một quy tắc, để truy cập từ bên ngoài tổ chức riêng lẻ đã tạo ra chúng.

Các dịch vụ Web

Tiếp theo, liên kết hầu như không tránh khỏi trong chuỗi tiến hóa này là các dịch vụ Web. Dựa trên XML và, trong nhiều trường hợp, trên HTTP, "các dịch vụ Web" vẫn còn có nghĩa là nhiều thứ cho nhiều người, nhưng trong trường hợp này, chúng ta sẽ nói về các dịch vụ Web như là sự trao đổi các thông báo dựa trên SOAP giữa các hệ thống.

Các thông báo này bao gồm XML, là một tiêu chuẩn mã nguồn mở dựa trên văn bản, bất cứ ai có thể truy cập được từ bất kỳ ứng dụng nào (ứng dụng bất kỳ là ứng dụng được thiết kế để chấp nhận nó). Điều này mở rộng thế giới cho ứng dụng của bạn để bao gồm bất cứ ai có thể tiếp cận nó trên mạng của bạn. (Nếu điều đó làm nổi các chuông bảo mật lên cho bạn, điều đó là tốt, bạn sẽ học cách giải quyết điều đó trong phần 4 của loạt bài này).

Một dịch vụ Web dựa trên SOAP liên quan đến việc gửi thông báo XML như được hiển thị trong Liệt kê 1.

Liệt kê 1. Một dịch vụ Web dựa trên SOAP
<SOAPenv:Envelope
 xmlns:SOAPenv="http://schemas.xmlSOAP.org/SOAP/envelope/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

 <SOAPenv:Body>
   <req:getNumberOfArticles xmlns:req="http://daily-moon.com/CMS/">
     <req:category>classifieds</req:category>
   </req:getNumberOfArticles> 
 </SOAPenv:Body> 
</SOAPenv:Envelope>

Các thông báo này chuyển từ một hệ thống này sang hệ thống khác, thường là thông qua HTTP. Hệ thống thu nhận dịch các thông báo, làm những gì mà nó được hỗ trợ để làm và gửi trả lại một đáp ứng dưới dạng thông báo SOAP khác.

Đây là một hệ thống đơn giản và như vậy, có nhiều khía cạnh về tính toán mức doanh nghiệp mà hệ thống đơn giản không có. May mắn thay, nhiều trong số các khía cạnh này đã được tính đến và có các đặc tả riêng của mình để xác định giao dịch này sẽ diễn ra như thế nào để kết hợp nhiều về an ninh và các khía cạnh khác của phần mềm trung gian hướng-thông báo.

Các loại dịch vụ Web khác

Sẽ là tắc trách nếu tôi đề cập đến là SOAP là cách duy nhất để thực hiện các dịch vụ Web. Còn có các phương tiện khác dựa trên XML để gửi thông báo giữa các hệ thống, một số trong đó có thể áp dụng cho môi trường doanh nghiệp và một số khác trong đó thì không. Ví dụ, Amazon đã là một trong những công ty dựa trên Web đầu tiên cung cấp quyền truy cập các dịch vụ Web vào hệ thống của mình cho công chúng. Amazon bao gồm một dịch vụ dựa trên SOAP, nhưng nó cũng cung cấp một dịch vụ dựa trên REST (Representational State Transfer – Chuyển tải trạng thái đại diện).

REST là một loại dịch vụ Web trong đó người sử dụng chỉ cần truy cập vào một URL và đáp ứng là một tài liệu XML đơn giản như một tài liệu hiển thị trong Liệt kê 2.

Liệt kê 2. Một đáp ứng của REST
<currentArticles> 
    <category>classifieds</category>
    <subcategory>forsale</subcategory> 

    <article id="888204">
       <articleHeadline></articleHeadline> 
       <articleText>30 ft ladder, only used once. Willing to let go for half it's 
           worth. Has slight dent near the middle. Harder than a human head. $150 OBO.
       </articleText> 
    </article>

    <article id="888242"> 
         <articleHeadline></articleHeadline>
         <articleText>Vintage 1963 T-Bird. Less than 300 miles. Driven by my
           daughter until I took it away. Serious inquires only. 555-3264 after 7PM.
         </articleText> 
     </article> 
</currentArticles>

Không có định dạng cụ thể nào cho các thông báo này. Nó chỉ là bất cứ thứ gì mà dữ liệu tình cờ có thôi.

Một loại dịch vụ Web khác liên quan đến việc sử dụng một chuẩn như XML-RPC. Trong trường hợp này, các lệnh được gửi đến một hệ thống thông qua XML chẳng hạn như trong Liệt kê 3.

Liệt kê 3. XML-RPC
<?xml version="1.0"?> 
<methodCall>
   <methodName>CMS.getNumberOfArticles</methodName> 
   <params>
     <param>
       <value><string>classifieds</string></value>
     </param> 
     <param>
       <value><string>forsale</string></value> 
     </param>
   </params> 
</methodCall>

Đáp ứng theo một định dạng tương tự.

Khi bạn đang học sử dụng SOAP, trong tâm trí của bạn, bạn có thể nghĩ rằng REST và XML-RPC là đơn giản hơn nhiều so với một hệ thống dựa trên SOAP. Và bạn đúng. Theo một số cách, chúng đúng là như vậy. Tuy nhiên, chúng ta không nói về một ứng dụng đơn giản để hiển thị thời tiết trên trang Web của bạn. Ở đây chúng ta đang nói về các ứng dụng mức doanh nghiệp và các ứng dụng mức doanh nghiệp cần có các thuộc tính mức doanh nghiệp như an ninh, tính tương thích và v.v.. Những khả năng này được bao bọc bởi các đặc tả bổ sung nổi lên xung quanh các dịch vụ Web dựa trên SOAP, làm cho SOAP trở thành một sự lựa chọn tốt hơn cho các ứng dụng mức doanh nghiệp về lâu dài.

Hãy xem xét một số các đặc tả này.

Các đặc tả của các dịch vụ Web cơ bản

Các đặc tả của các dịch vụ Web thường được chia thành hai loại: các đặc tả của các dịch vụ Web và các đặc tả của các dịch vụ Web mở rộng. Các đặc tả cơ bản là:

  • SOAP: Nền tảng của tất cả các dịch vụ Web dựa trên SOAP, đặc tả SOAP trình bày chi tiết định dạng của các thông báo thực tế. Nó cũng trình bày chi tiết các ứng dụng đường đi (way application) cần xử lý các khía cạnh nhất định của thông báo đó, chẳng hạn như các phần tử trong "tiêu đề" (header), cho phép bạn tạo ra các ứng dụng trong đó một thông báo được chuyển qua giữa nhiều trung gian trước khi đến điểm cuối cùng của nó. Hướng dẫn này sẽ trình bày đặc tả của SOAP.
  • WDSL: Ngôn ngữ mô tả dịch vụ Web là một đặc tả trình bày chi tiết một cách tiêu chuẩn để mô tả một dịch vụ Web dựa trên SOAP, kể cả biểu mẫu mà các thông báo cần có và nơi các thông báo cần được gửi đi. Nó cũng mô tả chi tiết đáp ứng cho một thông báo như vậy. WSDL, khi được kết hợp với những công cụ thích hợp, cho phép bạn tạo một cuộc gọi đến một dịch vụ web theo chương trình mà không bao giờ thực sự biết dịch vụ Web đang tìm kiếm những gì; ứng dụng này có thể trích xuất những chi tiết đó từ tệp WSDL và cung cấp cho bạn giao diện chương trình để sử dụng. Chúng tôi sẽ trình bày WSDL trong phần 2 của loạt bài này.
  • UDDI: Tích hợp, khám phá và mô tả đa năng là một tiêu chuẩn đã trải qua một số thay đổi kể từ lúc bắt đầu phát triển của nó. Ý tưởng là cung cấp một cách để các công ty đăng ký các dịch vụ của họ trong một đăng ký toàn cầu và tìm kiếm đăng ký toàn cầu đó cho các dịch vụ mà các công ty có thể quan tâm đến đang sử dụng. Tuy nhiên, do nhiều công ty đang kín đáo về việc mở hệ thống của mình cho những người bên ngoài là điều có thể hiểu được, mục tiêu này không hoàn toàn trở thành hiện thực. Tuy nhiên, UDDI đã duy trì như là một việc đăng ký nội bộ của các dịch vụ và thông tin dịch vụ; phần 3 của loạt bài này trình bày chi tiết việc sử dụng của nó.

Đó là những vấn đề cơ bản. Ngoài ra đúng là còn có hàng chục tiêu chuẩn mở rộng để thực hiện dịch vụ dựa trên SOAP có ích hơn.

Các đặc tả dịch vụ Web mở rộng

Trong số tất cả hàng chục các đặc tả Các dịch vụ Web-* (WS-*) nổi lên xung quanh, một số đặc tả gây chú ý do đang có ích cho doanh nghiệp. Đó là:

  • Các dịch vụ Web-An ninh (WS-Security): Đặc tả này xử lý mã hóa và chữ ký số, cho phép bạn tạo một ứng dụng trong đó các thông báo không thể bị nghe trộm và trong đó không thể từ chối thực hiện. Phần 4 của loạt bài này trình bày Các dịch vụ Web -An ninh.
  • Các dịch vụ Web-Chính sách (WS-Policy): Đặc tả này phát triển triển trên Các dịch vụ Web-An ninh, cho phép bạn mô tả chi tiết rõ ràng hơn một dịch vụ có thể được sử dụng như thế nào và do ai sử dụng. Phần 5 của loạt bài này trình bày Các dịch vụ Web-Chính sách.
  • Các dịch vụ Web-Tương thích (WS-I): Mặc dù các dịch vụ Web được hỗ trợ để được thiết kế cho tính tương thích, trong thực tế có đủ tính linh hoạt trong các đặc tả mà các cách giải thích giữa các sự hiện thực khác nhau có thể gây ra các vấn đề. Các dịch vụ Web-Tương thích cung cấp một bộ các tiêu chuẩn và các thực tiễn để ngăn chặn các loại vấn đề, cũng như các bài thử nghiệm được tiêu chuẩn hóa để kiểm tra các vấn đề. WS-I là chủ đề của phần 6 của loạt bài này.
  • Các dịch vụ Web-Ngôn ngữ thực thi qui trình nghiệp vụ (WS-BPEL): một dịch vụ duy nhất tốt đẹp, nhưng trong đa số các trường hợp nó hầu như không phải là một ứng dụng. Ít nhất, việc tính toán ở mức doanh nghiệp yêu cầu bạn kết hợp nhiều dịch vụ thành một hệ thống tổng thể và WS-BPEL cung cấp một cách để xác định các tương tác như là phân nhánh và xử lý đồng qui cần thiết cho việc tạo các hệ thống như vậy. Phần 7 của loạt bài này trình bày WS-BPEL.

Các đặc tả khác đóng một vai trò quan trọng trong các dịch vụ Web không được trình bày trong loạt bài này bao gồm WS-ReliableMessaging, cho phép bạn bảo đảm rằng đã nhận một và chỉ một bản sao của một thông báo và chắc chắn đã nhận được thông báo đó; WSRF, Khung công tác tài nguyên các dịch vụ Web (Web Services Resource Framework), cho phép bạn sử dụng trạng thái trong đó về cơ bản là một môi trường không trạng thái; và WSDM (Web Services Distributed Management – Quản lý phân phối các dịch vụ Web), bàn về vấn đề quản lý và sử dụng các dịch vụ Web. Bạn có thể tìm thêm thông tin về các đặc tả này và khác trong phần Tài nguyên của hướng dẫn này.

Chúng ta sẽ thực hiện cái gì

Trong hướng dẫn này, bạn sẽ theo dõi phòng chuyên mục rao vặt của tờ báo Daily Moon khi họ điều tra việc tích hợp hệ thống riêng của họ với giao diện dựa trên các dịch vụ Web do hệ thống quản lý nội dung sử dụng. Bạn sẽ tạo ra một ứng dụng để tạo một thông báo dựa trên SOAP, gửi nó đến dịch vụ đó và nhận được một đáp ứng. Khi làm điều đó, bạn sẽ thấy cách tạo ra một dịch vụ để đáp ứng các yêu cầu và gửi một đáp ứng của riêng của nó. Bạn sẽ làm điều này bằng cách tạo ra các ứng dụng Java, có và không có một máy chủ ứng dụng.


Thiết lập

Bây giờ bạn hiểu những nguyên tắc cơ bản có liên quan, chúng ta hãy bắt đầu xem xét việc tạo một ứng dụng trên thực tế. Bước đầu tiên là phải có phần mềm tại chỗ.

Thiết lập máy chủ Geronimo Apache

Đoạn đầu tiên của phần mềm mà bạn sẽ cần là một máy chủ ứng dụng Web. Tại sao bạn cần một máy chủ ứng dụng Web? Vâng, bởi vì bạn thực sự sẽ khó tìm đoạn phần mềm đáp ứng các dịch vụ web mà không có một máy chủ ứng dụng Web. Một máy chủ ứng dụng Web nghe các yêu cầu, dịch những yêu cầu đó thành một cái gì đó mà dịch vụ thực tế có thể hiểu được và sau đó thực hiện bất kỳ việc xử lý cần thiết nào.

Trên thực tế bạn có thể sử dụng hầu như bất kỳ máy chủ Web nào cho quá trình này, nhưng trong phần lớn các trường hợp bạn sẽ cài đặt phần mềm làm cho quá trình dễ dàng hơn và thường yêu cầu một trong số các loại máy chủ ứng dụng thực tế. Cụ thể, hướng dẫn này giả định bạn sẽ sử dụng một máy chủ ứng dụng Java. (Trên thực tế, hướng dẫn này giả định một máy chủ ứng dụng J2EE).

Bạn có nhiều sự lựa chọn khi nói đến các máy chủ J2EE và trong trường hợp này, bạn sẽ sử dụng máy chủ Apache Geronimo. Geronimo là máy chủ ứng dụng mã nguồn mở làm cơ sở của Ấn bản cộng đồng của máy chủ ứng dụng WebSphere của IBM (IBM WebSphere Application Server Community Edition). Geronimo là một phần mềm nhỏ, dễ cài đặt và dễ quản lý. Nó cũng hoạt động tốt với các dự án Apache khác, chẳng hạn như Axis2, mà bạn sẽ cài đặt lần tới.

Tải phần mềm (xem Các điều kiện cần trước) và trích các tệp vào một thư mục đích. Bạn sẽ thấy rằng các tệp đã trích xuất có thư mục riêng của chúng, do đó bạn chỉ cần giải nén chúng và chuyển chúng tới bất cứ nơi nào bạn muốn. Bất kỳ thư mục nào cũng có thể chấp nhận được, nhưng bạn cần tránh các thư mục có một khoảng trống trong tên của thư mục, chẳng hạn như "Program Files", "Documents and Settings" hoặc các thư mục con cháu của chúng. Ví dụ, việc cài đặt thử nghiệm cho hướng dẫn này sử dụng e:\Geronimo-1.0.

Ở đây. Bạn đã cài đặt Geronimo. Không dễ dàng phải không?

Để khởi động máy chủ, hãy mở một cửa sổ nhắc lệnh và thực hiện các lệnh sau:

cd <GERONIMO_HOME>java -jar server.jar

Để chắc chắn máy chủ đang chạy, hãy mở một trình duyệt và trỏ nó vào URL được hiển thị trong Liệt kê 4:

Liệt kê 4. URL của máy chủ
http://localhost:8080

Bạn sẽ thấy một trang như Hình 1.

Hình 1. Máy chủ đang làm việc
Máy chủ đang làm việc

Bây giờ chúng ta hãy cài đặt phần mềm các dịch vụ Web.

Cài đặt Apache Axis2

Hoàn toàn có thể đáp ứng các dịch vụ Web từ một máy chủ HTTP đơn giản. Tuy nhiên, nó không thích hợp. Có rất nhiều việc để xử lý các thông báo SOAP và không có lý do nào để bạn có thể xử dụng lại bánh xe đó. Bây giờ dự án Apache Axis đã làm cho nhiệm vụ này đơn giản hơn trong nhiều năm, tạo một môi trường trong đó rất dễ dàng tạo và xử lý các dịch vụ Web. Phần mềm này bao gồm các ứng dụng giúp bạn tạo ra một dịch vụ Web từ một đối tượng đơn giản, tạo một đối tượng Java từ dịch vụ Web và xử lý cả hai. Nhóm Apache đã tạo một phiên bản mới của Axis, Axis2, nhận lấy tất cả công việc được thực hiện trên Axis và lắp bánh xe công việc lên một mức bằng cách thay đổi kiến trúc để cho phép Axis2 có một mức có thể mở rộng lớn hơn. Điều này quan trọng, vì các đặc tả dịch vụ Web đang nổi lên trong mọi thời gian. Việc xây dựng Axis2 cho phép nó tích hợp dễ dàng hơn với các dự án như việc thực hiện các dịch vụ Web-An ninh của Apache, WSS4J. Vì chúng ta sẽ sử dụng những dự án này sau, nên bây giờ hãy tiếp tục và cài đặt Axis2 (xem Các điều kiện cần trước với thông tin tải về).

Hãy chắc chắn tải về cả hai bản phân phối nhị phân và bản phân phối War (Web archive – Kho lưu trữ Web). Bản trước sẽ trợ giúp trong việc xây dựng các ứng dụng khách, bản sau trợ giúp trong việc xây dựng các dịch vụ.

Để cài đặt Axis2 vào máy chủ Web, hãy sao chép tệp axis2.war vào thư mục triển khai của Geronimo. (Bạn sẽ cần chắc chắn rằng bạn đã khởi động Geronimo ít nhất một lần để thư mục này có mặt). Geronimo phát hiện sự có mặt của mình tự động, do đó bạn không phải tự triển khai bất cứ điều gì bằng tay.

Kiểm tra phần mềm Axis cho việc lắp đặt

Để chắc chắn rằng tất cả mọi thứ đã được cài đặt đúng, hãy trỏ trình duyệt của bạn tới http://localhost:8080/axis2/index.jsp và nhấn vào Validate (xác nhận hợp lệ).

Bạn sẽ thấy một trang như thể hiện trong Hình 2.

Hình 2. Trình Axis thích hợp
Trình Axis thích hợp

Hãy chắc chắn rằng trình Axis là phù hợp trước khi tiếp tục với phần còn lại của hướng dẫn.

Cài đặt một dịch vụ ví dụ

Ứng dụng đầu tiên mà bạn sẽ viết là một ứng dụng khách, vì vậy bạn sẽ cần một dịch vụ cho nó để truy cập. May mắn thay, bản phân phối Axis2 đi kèm với một vài dịch vụ. Để bắt đầu, bạn sẽ cài đặt dịch vụ MyService như sau:

  1. Tự xác thực cho ứng dụng Axis2 bằng cách trỏ vào trình duyệt của bạn vào http://localhost:8080/axis2/Login.jsp và đăng nhập. Tên người dùng và mật khẩu mặc định tương ứng là adminAxis2.
  2. Nhấn Upload service>Browse.
  3. Chuyển hướng đến tệp MyService.aar. Bạn có thể tìm thấy nó trong thư mục samples\userguide của bản phân phối Axis2 tiêu chuẩn. Nhấn OK.
  4. Nhấn Upload.

Bạn sẽ thấy một thông báo rằng dịch vụ đó đã được thêm vào (xem Hình 3). Theo mặc định, Axis2 bao gồm "việc triển khai nóng", do đó bạn không cần làm bất cứ điều gì để kích hoạt nó.

Hình 3. MyService.aar đã được tải lên
MyService.aar đã được tải lên

Bây giờ, hãy xem bạn sắp xây dựng cái gì.


Hiểu biết về SOAP

Bây giờ bạn đã cài đặt phần mềm, bạn có thể bắt đầu xem xét dịch vụ Web thực sự. Như tôi đã đề cập trong phần Các loại các dịch vụ Web khác, bạn có một số định dạng để lựa chọn. Trong loạt bài này, bạn sẽ sử dụng SOAP.

Một nhận xét nhanh về XML

Tất cả những thông báo bay qua và bay lại là dựa vào XML hay Extensible Markup Language (Ngôn ngữ đánh dấu mở rộng). Nếu bạn chưa hiểu rõ về XML một chút nào, bạn thực sự cần nghiên cứu chút ít trước khi đi sâu vào chủ đề các dịch vụ Web. Tuy nhiên, đây là những vấn đề cơ bản mà bạn cần biết trước khi bạn tiếp tục thực hiện hướng dẫn này.

XML là một "ngôn ngữ đánh dấu", có nghĩa là nó cung cấp một cách để cung cấp thông tin bổ sung về nội dung thực tế. Thông tin này đi kèm theo dạng "các thẻ", biểu thị "các phần tử". Ví dụ, hãy xem xét tài liệu XML đơn giản này được hiển thị trong Liệt kê 5:

Liệt kê 5. Một tệp XML hiển thị những điều căn bản
<article articleId="88271" categoryId="classifieds" subcategoryId="forsale"> 
  <articleHeadline>Fun, fun, fun</articleHeadline> 
  <articleText>Vintage 1963 T-Bird. Less than 300 miles. Driven by my daughter 
     until I took it away. Serious inquires only. 555-3264 after 7 PM.
  </articleText> 
</article>

Lưu ý một vài điều về tài liệu này. Trước hết, đó là văn bản. Điều đó làm cho nó có thể trở nên dễ đọc cho hầu hết mọi người hay cho hầu hết mọi thứ. Thứ hai, các thẻ được biểu thị bằng dấu > và <, với một thẻ "mở" có một tên và có thể có các thuộc tính như article ID và một thẻ kết thúc bắt đầu với một dấu gạch chéo (/). Các phần tử phải được khép kín và được lồng đúng. Nói cách khác, bạn không thể có một tài liệu XML trông giống như một tài liệu được hiển thị trong Liệt kê 6.

Liệt kê 6. Một tài liệu XML ví dụ không hợp lệ
<article articleId="88271" categoryId="classifieds" subcategoryId="forsale"> 
  <articleHeadline>Fun, fun, fun 
  <articleText>
  </articleHeadline>Vintage 1963 T-Bird. Less than 300 miles. Driven by my daughter 
      until I took it away. Serious inquires only. 555-3264 after 7 PM.
  </articleText> 
</article>

XML cũng cung cấp một cách để phân tách nội dung thành "các vùng tên" (namespaces) khác nhau, do đó một ứng dụng có thể xử lý nội dung khác nhau. Ví dụ, một thông báo SOAP có thể trông giống như sau trong Liệt kê 7.

Liệt kê 7. Một thông báo SOAP ví dụ
<?xml version='1.0' ?> 
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
   <env:Header> </env:Header> 
   <env:Body> 
      <cms:getNumberOfArticles xmlns:cms="http://www.daily-moon.com/cms">
        <cms:category>classifieds</cms:category>
        <cms:subcategory>forsale</cms:subcategory>
      </cms:getNumberOfArticles> 
   </env:Body> 
</env:Envelope>

Đừng lo lắng về cấu trúc thực tế của thông báo, nhưng lưu ý rằng có hai "tiền tố" khác nhau, mỗi tiền tố tương ứng với một vùng tên cụ thể. Trong trường hợp này, chúng ta phân biệt "phong bì" (envelope) SOAP với tải trọng thực tế.

Một lần nữa, có rất nhiều thứ để tìm hiểu về XML, nhưng đó là những vấn đề cơ bản mà bạn cần biết với hướng dẫn này.

Phong bì SOAP

Đơn vị cơ bản của thông báo dịch vụ web là phong bì thực tế của SOAP. Đây là một tài liệu XML trong đó bao gồm tất cả thông tin cần thiết để xử lý thông báo (xem Liệt kê 8).

Liệt kê 8. Một phong bì SOAP ví dụ
<?xml version='1.0' ?> 
<env:Envelope
   xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
   <env:Header></env:Header> 
   <env:Body></env:Body> 
</env:Envelope>

Trong trường hợp này, bạn có một Envelope (phong bì) đơn giản, với vùng tên được quy định theo phiên bản 1.2 của SOAP. Nó bao gồm hai phần tử con, một Header (Phần tiêu đề) và một Body (Phần thân). Hãy xem mỗi phần trong chúng làm gì..

Phần tiêu đề SOAP

Header trong một thông báo SOAP được dùng để cung cấp thông tin về chính thông báo đó, trái với những thông tin dành cho ứng dụng. Ví dụ, Header có thể bao gồm việc định tuyến thông tin, giống như việc định tuyến thông tin trong ví dụ này được thể hiện trong Liệt kê 9.

Liệt kê 9. Định tuyến thông tin trong Header
<?xml version='1.0' ?> 
<env:Envelope
  xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">

  <env:Header>
      <wsa:ReplyTo xmlns:wsa="http://schemas.xmlSOAP.org/ws/2004/08/addressing"> 
         <wsa:Address>
              http://schemas.xmlSOAP.org/ws/2004/08/addressing/role/anonymous
         </wsa:Address> 
      </wsa:ReplyTo> 
      <wsa:From>
             <wsa:Address>http://localhost:8080/axis2/services/MyService</wsa:Address>
      </wsa:From>
      <wsa:MessageID>ECE5B3F187F29D28BC11433905662036</wsa:MessageID>
  </env:Header> 

  <env:Body></env:Body>
</env:Envelope>

Trong trường hợp này bạn thấy một phần tử WS-Addressing (Các ứng dụng Web-Đánh địa chỉ), bao gồm thông tin về nơi gửi thông báo đến và các câu trả lời sẽ trả về đâu. Header (tiêu đề) có thể bao gồm tất cả các loại thông tin về chính thông báo đó. Trong thực tế, đặc tả SOAP dành nhiều thời gian cho các phần tử có thể đưa vào Header, và "các phương tiện trung gian SOAP" cần xử lý các phần tử đó như thế nào. Nói cách khác, đặc tả SOAP không giả định rằng thông báo là đi thẳng từ một điểm này tới điểm khác, từ ứng dụng khách đến máy chủ. Nó dành chỗ cho ý tưởng là một thông báo SOAP thực sự có thể được xử lý bởi một vài phương tiện trung gian, trên đường đi của nó tới điểm đến cuối cùng của nó và đặc tả này là rất rõ ràng về cách các phương tiện trung gian đó xử lý thông tin mà chúng tìm thấy trong phần Header. Tuy nhiên, cuộc thảo luận đó nằm ngoài phạm vi của hướng dẫn này. Vì vậy, bây giờ, chỉ cần hiểu rằng Header có thể cung cấp cho bạn nhiều chức năng hơn nữa nếu bạn cần.

Bây giờ hãy xem xét tải trọng thực tế.

Phần thân của SOAP

Khi bạn đang gửi một thông báo SOAP, bạn đang thực hiện nó với một lý do trong suy nghĩ. Bạn đang cố gắng để nói cho người nhận làm một cái gì đó hoặc bạn đang cố gắng để truyền đạt thông tin đến máy chủ. Thông tin này được gọi là "tải trọng" (payload). Tải trọng đưa vào Body (phần thân) của Envelope đó. Tải trọng cũng có vùng tên riêng của mình, trong trường hợp này tương ứng với hệ thống quản lý nội dung. Trong trường hợp này, việc lựa chọn vùng tên là hoàn toàn tùy ý. Vùng tên chỉ cần khác với vùng tên của SOAP (Xem Liệt kê 10).

Liệt kê 10. Một ví dụ tải trọng
<?xml version='1.0' ?> 
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
  <env:Header> ... </env:Header> 

  <env:Body> 
     <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">
          <cms:category>classifieds</category>
          <cms:subcategory>forsale</cms:subcategory>
          <cms:articleHeadline></cms:articleHeadline>
          <cms:articleText>Vintage 1963 T-Bird. Less than 300 miles. Driven by
            my daughter until I took it away. Serious inquires only. 555-3264 after 7 PM.
          </cms:articleText> 
     </cms:addArticle> 
  </env:Body>
</env:Envelope>

Trong trường hợp này, bạn có một tải trọng đơn giản bao gồm các hướng dẫn để thêm một bài viết tới hệ thống quản lý nội dung cho tờ báo Daily Moon.

Việc lựa chọn cách cấu trúc tải trọng liên quan đến phong cách và việc mã hóa.

Phong cách và việc mã hóa

Bạn sẽ đi sâu hơn vào chủ đề này trong phần 2, nói về WSDL (Ngôn ngữ mô tả dịch vụ Web), nhưng khi bạn tạo ứng dụng của bạn, bạn sẽ cần quyết định về cấu trúc của tải trọng thực tế bạn đang gửi đi gửi lại. Cuối cùng, chúng ta hãy dành một chút thời gian để thảo luận về phong cách lập trình và việc mã hóa.

Chỉ cần đặt, hai phong cách lập trình khác nhau cho các thông báo SOAP chiếm ưu thế. Đầu tiên là phong cách RPC, dựa trên khái niệm của việc sử dụng các thông báo SOAP để tạo Các cuộc gọi giao thức từ xa (Remote Procedure Calls). Theo phong cách này, ý tưởng là bạn sẽ gửi một lệnh tới máy chủ, chẳng hạn như "thêm một bài viết" và bạn sẽ có các tham số cho lệnh đó, chẳng hạn như bài viết để thêm vào và thể loại cần thêm vào bài viết đó, như là các phần tử con của phương thức tổng thể, như trong Liệt kê 11.

Liệt kê 11. Phong cách RPC
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">
    <env:Header>

Sự thay thế cho phong cách RPC liên quan đến việc chỉ cần có dữ liệu của bạn làm nội dung của phần thân của SOAP và có thông tin như về sự thay thế đó gắn liền với trong việc định tuyến thông báo bằng máy chủ ứng dụng (xem Liệt kê 12).

Liệt kê 12. Dữ liệu làm nội dung trong phần thân của SOAP
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
   <env:Header></env:Header> 
   <env:Body> 
      <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">
      <cms:category>classifieds</category>
      <cms:subcategory>forsale</cms:subcategory>
      <cms:articleHeadline></cms:articleHeadline>
      <cms:articleText>Vintage 1963 T-Bird. Less than 300 miles. Driven by
          my daughter until I took it away. Serious inquires only. 555-3264 after 7
          PM.</cms:articleText> 
      </cms:addArticle> 
   </env:Body>
</env:Envelope>

Một sự thay đổi về phong cách RPC là RPC/được mã hóa, trái với RPC/bằng chữ, như chúng ta thấy ở trên. Trong trường hợp đó, thông báo này bao gồm thông tin kiểu, như thông tin được thể hiện trong Liệt kê 13.

Liệt kê 13. Ví dụ RPC/được mã hóa
<?xml version='1.0' ?> 
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
   <env:Header></env:Header> 
   <env:Body> 
      <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms"> 
         <cms:category xsi:type="xsd:string">classifieds</category>
         <cms:subcategory xsi:type="xsd:string">forsale</cms:subcategory> 
         <cms:articleHeadline xsi:type="xsd:string"/> 
         <cms:articleText xsi:type="xsd:string">Vintage 1963 T-Bird.
            Less than 300 miles. Driven by my daughter until I took it away. Serious
            inquires only. 555-3264 after 7 PM.
         </cms:articleText>
      </cms:addArticle> 
   </env:Body> 
</env:Envelope>

Phong cách thứ hai được gọi là phong cách tài liệu/bằng chữ, bao gồm việc chỉ cần bổ sung thêm dữ liệu thích hợp cho thông báo đó, như ví dụ được hiển thị trong Liệt kê 14.

Liệt kê 14. Ví dụ về phong cách tài liệu/bằng chữ
<?xml version='1.0' ?> 
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
  <env:Header></env:Header> 
  <env:Body>
      <category>classifieds</category>
      <subcategory>forsale</subcategory>
      <articleHeadline></articleHeadline> 
      <articleText>Vintage 1963 T-Bird. Less than 300 miles. Driven by my daughter 
          until I took it away. Serious inquires only. 555-3264 after 7 PM.
      </articleText>
  </env:Body> 
</env:Envelope>

Trong trường hợp này, thông báo tự nó không bao gồm thông tin về quá trình theo đó dữ liệu được đệ trình lên; nghĩa là được phần mềm định tuyến xử lý. Ví dụ, tất cả các cuộc gọi tới một URL hoặc điểm cuối cụ thể có thể trỏ đến một hoạt động cụ thể. Ngoài ra, về kỹ thuật bạn có thể sử dụng phong cách tài liệu/được mã hóa, nhưng chẳng ai sử dụng cả, vì vậy bây giờ, hãy bỏ qua phong cách đó.

Các sự thỏa hiệp khác nhau có liên quan đến mỗi một trong các phong cách này và một lần nữa, phần 2 của loạt bài này sẽ đi vào chúng cụ thể hơn nữa. Tuy nhiên, điều quan trọng là phải biết rằng còn có một phong cách thứ ba, "tài liệu được bao bọc", phong cách này chưa được quy định chính thức ở bất cứ đâu, nhưng đã trở nên phổ biến vì nhiều lý do tương thích khác nhau. Trong trường hợp này, nội dung của tải trọng được bao bọc trong một phần tử duy nhất, nhưng phần tử đó có thể không được đặt tên sau khi dữ liệu thuộc về thủ tục hoặc hàm đó. Bằng mắt thường, các thông báo này hầu như giống hệt với các thông báo RPC/bằng chữ.

Các mô hình trao đổi thông báo

Khi nói đến việc gửi thông báo, bạn có nhiều lựa chọn, từ gửi một yêu cầu và chờ đợi một đáp ứng để gửi yêu cầu và quên nó, đến gửi yêu cầu và yêu cầu đó được chuyển qua nhiều phương tiện trung gian trước khi nó được đưa đến đích cuối cùng của nó. Tuy thế, cuối cùng bạn thực sự chỉ có hai lựa chọn:

  • Yêu cầu/đáp ứng (Request/Response): Trong mô hình yêu cầu/đáp ứng, bạn gửi một yêu cầu dưới dạng một thông báo SOAP và bạn chỉ cần chờ đợi một đáp ứng trả về. Yêu cầu đó có thể được đồng bộ hoặc không đồng bộ.
  • Gửi thông báo một chiều: Trường hợp này, còn được gọi là phương thức "thực hiện và quên", bao gồm việc gửi yêu cầu và sau đó chỉ cần quên nó. Bạn có thể sử dụng trường hợp này trong các tình huống trong đó bạn chỉ cần truyền đạt thông tin hay bất kỳ tình huống khác nào ở đó bạn không thực sự quan tâm xem người nhận phải nói gì về nó.

Bây giờ, lưu ý việc thiếu các thuật ngữ "ứng dụng khách" (client) và "máy chủ" (server). Lý do của sự thiếu thuật ngữ này là ở chỗ các mô hình trao đổi thông báo này về cơ bản có thể được sử dụng để tạo ra bất kỳ số lượng nào trong số các thay đổi khác nhau chẳng hạn như những thứ đã đề cập ở trên. Ví dụ, bạn có thể tạo ra một tình huống trong đó bạn gửi một yêu cầu và hy vọng người nhận tiếp tục thực hiện nó, gửi một thông báo tại một số điểm trong tương lai khi nó đã làm những gì nó được hỗ trợ để làm. Để thực hiện điều đó, bạn sẽ sử dụng một sự kết hợp của các thông báo một chiều, do đó, nó không có ý nghĩa để nói về "ứng dụng khách" và "máy chủ", bởi vì mỗi thông báo có một người gửi và người nhận và cái được gọi là các vị trí chuyển đổi ứng dụng khách và máy chủ.


Xây dựng một ứng dụng khách SOAP

Dĩ nhiên, bạn đã thấy lý thuyết, bây giờ là lúc để xây dựng các ứng dụng thực tế. Hãy bắt đầu với ứng dụng khách.

Theo cách cũ

Khi các API của Java lần đầu đã xuất hiện để làm việc với các thông báo SOAP, chúng đã rất rõ ràng về các điều cần làm. Chân thành mà nói, các API này để tạo các thông báo SOAP. Bạn đã yêu cầu tạo ra thông báo Envelope, Header, Body, và v.v. Ví dụ, bạn có thể xây dựng một ứng dụng khách theo "phong cách cũ" để truy cập hàm echo của dịch vụ MyService mà bạn cài đặt trước đó (xem Liệt kê 15).

Lưu ý: Để biên dịch và chạy ứng dụng khách này, bạn sẽ cần một sự thực hiện SAAJ như là phần mềm Axis gốc. Bạn có thể tải Axis từ http://ws.apache.org/axis/. Theo thông báo, Axis2 0.95 cũng có sự thực hiện này, nhưng nó vẫn chưa được thử nghiệm cho hướng dẫn này.

Liệt kê 15. Một ứng dụng khách theo phong cách cũ
import javax.xml.SOAP.*; 
import javax.xml.transform.*; 
import java.io.FileInputStream; 
import javax.xml.transform.stream.*; 
import org.w3c.dom.*; 

public class SendSOAP { 
  public static void main(String args[]) {
    try { 
      MessageFactory messageFactory = MessageFactory.newInstance(); 
      SOAPMessage message = messageFactory.createMessage(); 
//Create objects for the message parts
      SOAPPart SOAPPart = message.getSOAPPart(); 
      SOAPEnvelope envelope = SOAPPart.getEnvelope(); 
      SOAPBody body = envelope.getBody(); SOAPElement
      bodyElement = body.addChildElement(envelope.createName("echo", "req",
                    "http://localhost:8080/axis2/services/MyService/"));
      bodyElement.addChildElement("category") .addTextNode("classifieds");
      message.saveChanges(); SOAPPart SOAPpartbefore = message.getSOAPPart();
      SOAPEnvelope reqenv = SOAPpartbefore.getEnvelope();
      System.out.println("REQUEST:"); 
      System.out.println(reqenv.toString()); 
//Now create the connection SOAPConnectionFactory 
      SOAPConnFactory = SOAPConnectionFactory.newInstance(); 
      SOAPConnection connection = SOAPConnFactory.createConnection(); 
      SOAPMessage reply = connection.call(message, 
                          "http://localhost:8080/axis2/services/MyService"); 
      SOAPPart SOAPpart = reply.getSOAPPart(); 
      SOAPEnvelope replyenv = SOAPpart.getEnvelope();
      System.out.println("\nRESPONSE:"); 
      System.out.println(replyenv.toString());
      connection.close(); 
    } catch (Exception e){ 
         System.out.println(e.getMessage()); 
      }
  } 
}

Lưu ý rằng bạn đang trực tiếp tạo SOAPEnvelope, SOAPBody, và v.v. Bạn có thể thêm các phần tử như phần tử echocategory cho phần thân đó. Từ đó, bạn tạo kết nối, thực hiện cuộc gọi và một lần nữa bạn có thể làm việc theo cách của mình thông qua cấu trúc của thông báo SOAP để bắt đầu nội dung thực tế. Nếu bạn đang chạy ứng dụng khách này, bạn sẽ thấy một đáp ứng nào đó giống đáp ứng được hiển thị trong Liệt kê 16.

Liệt kê 16. Ứng dụng khách cho đến nay
REQUEST: 
<SOAPenv:Envelope xmlns:SOAPenv= "http://schemas.xmlSOAP.org/SOAP/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

    <SOAPenv:Body>
       <req:echo xmlns:req= "http://localhost:8080/axis2/services/MyService/">
           <req:category>classifieds</req:category> 
       </req:echo>
    </SOAPenv:Body> 
</SOAPenv:Envelope> 

RESPONSE: 
<SOAPenv:Envelope xmlns:SOAPenv= "http://schemas.xmlSOAP.org/SOAP/envelope/" 
   xmlns:wsa= "http://schemas.xmlSOAP.org/ws/2004/08/addressing"> 
   <SOAPenv:Header>
      <wsa:ReplyTo> <wsa:Address>
                    http://schemas.xmlSOAP.org/ws/2004/08/addressing/role/anonymous
                    </wsa:Address> 
      </wsa:ReplyTo> 
      <wsa:From> 
         <wsa:Address>http://localhost:8080/axis2/services/MyService</wsa:Address>
      </wsa:From>
      <wsa:MessageID>ECE5B3F187F29D28BC11433905662036</wsa:MessageID>
    </SOAPenv:Header> 

    <SOAPenv:Body> 
        <req:echo xmlns:req= "http://localhost:8080/axis2/services/MyService/">
            <req:category>classifieds</req:category> 
        </req:echo>
    </SOAPenv:Body> 
</SOAPenv:Envelope>

Tất cả mọi thứ mà dịch vụ echo thực sự làm là áp dụng ngược lại với yêu cầu mà nó đã nhận được, là một cơ hội tốt để thấy sự khác biệt giữa việc xử lý theo phong cách cũ và phong cách mới. Hãy nói về sự khác biệt đó.

Theo cách mới

Hiện nay, có một phong trào đang phát triển để ẩn giấu sự phức tạp khi làm việc với các thông báo của các dịch vụ Web dựa trên XML từ lập trình viên. Tất cả các loại sáng kiến nổi lên, hầu hết trong số đó có mục đích để thực hiện lập trình cho các dịch vụ Web càng giống như việc lập trình với kiến trúc khác bất kỳ càng tốt.

Trong Axis2, nó thực sự có nghĩa là nhiều hơn thế. Axis2 giới thiệu một cách làm việc hoàn toàn mới với XML để biểu thị một thông báo SOAP, mặc dù trên bề mặt nó trông giống như việc sử dụng DOM (Document Object Model – Mô hình đối tượng tài liệu). Các mô hình đối tượng AXI hay AXIOM (AXIs Object Model - Mô hình đối tượng của các AXI) tạo ra một số thay đổi, nhưng vào lúc này tôi sẽ chỉ đề cập đến là AXIOM tập trung vào Infoset của thông báo đó, đây là thông tin thực sự chứa trong các phần tử và các thuộc tính, thay cho phiên bản phát hành nhiều kỳ của các thẻ (tag) mà chúng ta thường nhìn thấy. Tuy nhiên, quan trọng hơn, Axis2 quan tâm đến phong bì SOAP cho bạn, cho phép bạn tập trung vào chỉ xây dựng tải trọng hoặc trong trường hợp của các dịch vụ thực tế, phân tích tải trọng và tạo ra một đáp ứng. Hãy xem cách Axis2 hoạt động.

Tạo yêu cầu

Để bắt đầu tạo ứng dụng khách, hãy đảm bảo rằng tất cả tệp *. jar trong thư mục lib Axis2 -- đây sẽ là bản phân phối chuẩn, chứ không phải là bản phân phối War - đang có trên CLASSPATH (đường dẫn lớp) của bạn và tạo một lớp mới gọi là ClassifiedClient. Hãy tạo tải trọng như trong Liệt kê 17.

Liệt kê 17. Tải trọng
import org.apache.axis2.addressing.EndpointReference; 
import org.apache.axis2.client.Options; 
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.om.OMElement; 
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException; 
import java.io.StringWriter; 
import org.apache.axis2.om.OMAbstractFactory; 
import org.apache.axis2.SOAP.SOAPFactory;
import org.apache.axis2.om.OMFactory; 
import org.apache.axis2.om.OMNamespace;
                    
public class ClassifiedClient { 

   public static OMElement getEchoOMElement() {
        SOAPFactory fac = OMAbstractFactory.getSOAP12Factory(); 
        OMNamespace omNs = fac.createOMNamespace( 
                "http://daily-moon.com/cms", "cms"); 
        OMElement method = fac.createOMElement("echo", omNs); 
        OMElement value = fac.createOMElement("category", omNs); 
        value.addChild(fac.createText(value, "classifieds")); 
        method.addChild(value); 

        return method; 
    } 

    public static void main(String[] args) { 
        try { 
            OMElement payload = ClassifiedClient.getEchoOMElement(); 
        } catch (Exception e) { //(XMLStreamException e) { 
            System.out.println(e.toString()); 
        } 
    } 
}

Trước tiên, bạn tạo ra một nhà máy và một vùng tên và bạn sử dụng chúng để tạo ra các phần tử. Trong trường hợp này, bạn sẽ tạo ra các phần tử giống như các phần tử mà bạn đã tạo ra trong ví dụ trước, khi một lần nữa bạn sẽ sử dụng ứng dụng khách này để truy cập hàm echo. (Sau đó, bạn sẽ thay đổi nó để truy cập vào dịch vụ thực tế).

Tiếp theo, bạn sẽ tạo yêu cầu.

Tạo yêu cầu

Bước tiếp theo là tạo yêu cầu thực tế. Ở đây bạn lại thấy thời gian trôi đi. Thay vì chỉ cần gửi yêu cầu đến một URL, bạn sẽ thiết lập một "tham chiếu điểm đầu cuối", như trong Liệt kê 18.

Liệt kê 18. Tham chiếu điểm đầu cuối trong yêu cầu
... 
public class ClassifiedClient { 
    private static EndpointReference targetEPR = new 
         EndpointReference(
            "http://localhost:8080/axis2/services/MyService"); 
    public static OMElement getEchoOMElement() { 
      ... 
    } 

    public static void main(String[] args) {
        try { 
            OMElement payload = ClassifiedClient.getEchoOMElement(); 
            Options options = new Options(); 
            options.setTo(targetEPR);
            options.setTransportInProtocol(Constants.TRANSPORT_HTTP); 
        } catch (Exception e) { //(XMLStreamException e) { 
             System.out.println(e.toString()); 
        } 
     }
}

Một cuộc thảo luận đầy đủ về Các ứng dụng Web-Đánh địa chỉ (WS-Addressing) nằm ngoài phạm vi của hướng dẫn này, nhưng chỉ cần nói rằng một tham chiếu điểm đầu cuối bao gồm URL trong đó một thông báo được hướng tới, nhưng theo tùy chọn có thể bao gồm thông tin khác như một thư trả lời đến địa chỉ và các đặc tính tài nguyên khác.

Trước tiên, bạn tạo ra các Tùy chọn (Options) cho yêu cầu, cho phép bạn thiết lập EPR cho yêu cầu này, cũng như thông tin khác như là việc vận chuyển mà bạn có ý định sử dụng. Một khi bạn có trước tất cả các thông tin đó, bạn có thể gửi yêu cầu.

Gửi yêu cầu

Một khi bạn đã thiết lập mọi thứ, đây là lúc để gửi yêu cầu. Kể từ Axis, tới phiên bản 0.94, cách ưa thích để gửi một thông báo là thông qua lớp ServiceClient, được thể hiện trong Liệt kê 19.

Liệt kê 19. Gửi yêu cầu
... 
 public static void main(String[] args) { 
   try { 
         OMElement payload = ClassifiedClient.getEchoOMElement(); 
         Options options = new Options();
         options.setTo(targetEPR);
         options.setTransportInProtocol(Constants.TRANSPORT_HTTP); 
         ServiceClient sender = new ServiceClient(); 
         sender.setOptions(options); 
         OMElement result = sender.sendReceive(payload); 
   } catch (Exception e) { //(XMLStreamException e) { 
           System.out.println(e.toString()); 
   } 
 } 
}

Bạn tạo một đối tượng ServiceClient và thiết lập Options (các tùy chọn) mà bạn tạo ra ở trên cho nó. Từ đó, bạn có thể chỉ cần gửi thông báo. Bởi vì bạn muốn có một đáp ứng, bạn sẽ sử dụng phương thức sendReceive(), đó là một thông báo vào/ra. Bạn sẽ thấy việc gửi thông báo một chiều trong phần Dịch vụ một chiều của hướng dẫn này. Phương thức sendReceive() trả về đáp ứng thực sự vì nó đã được ứng dụng khách nhận.

Xuất ra kết quả

Trên thực tế, sendReceive() không trả lại toàn bộ đáp ứng, nó chỉ trả về tải trọng. Nếu bạn xuất kết quả vào dòng lệnh, bạn có thể thấy rõ điều này trong Liệt kê 20.

Liệt kê 20. Xuất ra sendReceive
...
       sender.setOptions(options); 
       OMElement result = sender.sendReceive(payload);
                    
       System.out.println(result.toString()); 
    } catch (Exception e) { //(XMLStreamException e) { 
        System.out.println(e.toString()); 
    } 
  } 
}

Việc chạy ứng dụng khách này sẽ cung cấp cho bạn đáp ứng được hiển thị trong Liệt kê 21.

Liệt kê 21. Đáp ứng sendReceive
<cms:echo xmlns:cms="http://daily-moon.com/cms"><cms:catego
ry>classifieds</cms:category></cms:echo>

Tất nhiên, bạn có thể làm được nhiều thứ với dữ liệu này một khi bạn nhận nó. Đến lúc này, chúng ta hãy xây dựng dịch vụ getNumberofArticles() thực tế.


Xây dựng một dịch vụ SOAP

Nếu quá trình xây dựng một ứng dụng khách của dịch vụ web có vẻ hơi đơn giản với bạn, thì bạn suy nghĩ đúng đấy. Và việc xây dựng một dịch vụ hiện có, bằng nhiều cách, đúng là đơn giản thật.

Toàn bộ quá trình

Toàn bộ quá trình tạo một dịch vụ Web Axis2 liên quan đến các bước sau:

  1. Tạo bảng kê dịch vụ.
  2. Tạo lớp.
  3. Gói chúng vào thành một tệp lưu trữ Axis.
  4. Tải tệp lưu trữ Axis lên cho ứng dụng web Axis2.
  5. Khởi động lại máy chủ, nếu cần thiết.

Đó là tất cả quá trình để tạo một dịch vụ. Hãy bắt đầu với bảng kê dịch vụ.

Tạo bảng kê

Bảng kê dịch vụ cho ứng dụng Axis2 (và mở rộng ra là, máy chủ ứng dụng) biết các yêu cầu nào tương ứng với các lớp nào. Ví dụ, bạn có thể xác định hai hàm dịch vụ, như trong Liệt kê 22.

Liệt kê 22. Chỉ rõ hai hàm dịch vụ trong bảng kê
<service name="CMSService"> 
    <description> 
         This is a sample Web Service for the newspaper's 
         Content Managment System.
    </description> 

    <parameter name="ServiceClass" locked="false">CMSService</parameter> 
 
    <operation name="getNumberOfArticles">
       <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/> 
    </operation>
                    
    <operation name="addArticle"> 
       <messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/> 
    </operation>
                    
</service>

Trước tiên, bạn định nghĩa toàn bộ dịch vụ, cung cấp cho nó một tên và một sự mô tả và xác định lớp để thực sự dùng cho yêu cầu đó. Tiếp theo, bạn định nghĩa các hoạt động thực tế. Lưu ý rằng ví dụ này chỉ rõ hai loại hoạt động messageReceiver khác nhau. Hoạt động đầu tiên, RawXMLINOutMessageReceiver, là dịch vụ yêu cầu/đáp ứng truyền thống. Hoạt động thứ hai, RawXMLINOnlyMessageReceiver dành cho các thông báo một chiều. Tên của hoạt động tương ứng với phần tử gốc của tải trọng, cũng như phương thức để thực hiện.

Lưu tệp này là services.xml.

Bây giờ hãy tạo ra ứng dụng thực tế.

Tạo ứng dụng

Hãy bắt đầu bằng cách tạo một lớp bắt chước hàm echo mà chúng ta đã thấy ở trên, chỉ cần trả về một bản sao của tải trọng ban đầu, được thể hiện trong Liệt kê 23.

Liệt kê 23. Lớp CMSService
import org.apache.axis2.om.OMElement; 
import javax.xml.stream.XMLStreamException;
                    
public class CMSService { 
      public OMElement getNumberOfArticles(OMElement element) 
            throws XMLStreamException { 
                element.build(); 
                element.detach(); 
                return element; 
      } 
}

Để biên dịch ứng dụng này, hãy chắc chắn rằng tất cả các tệp *. jar trong <axis2_home>/lib đang có trên đường dẫn lớp (CLASSPATH) của bạn.

Ứng dụng này khá đơn giản, chỉ có đúng một hàm tương ứng với hoạt động getNumbereOfArticles. Hàm này và bất kỳ hàm nào được dự kiến là một hoạt động, nhận một OMElement, duy nhất, biểu thị cho tải trọng. Ở đây đầu tiên bạn sử dụng phương thức build() để đảm bảo đã nhận được tất cả dữ liệu - AXIOM sử dụng một phương thức kéo truy cập dữ liệu - và sau đó tách phần tử đó khỏi cây hiện tại của nó để bạn có thể trả về nó.

Nếu bạn cảm thấy mạo hiểm, hãy tới phần Triển khai dịch vụTruy cập dịch vụ để truy cập vào dịch vụ và xem kết quả. Bạn sẽ thấy một số thứ trên các dòng được hiển thị trong Liệt kê 24.

Liệt kê 24. Đáp ứng lớp CMSService
<cms:getNumberOfArticles>
    <cms:category>classifieds</cms:category>
</cms:getNumberOfArticles>

Bây giờ hãy xem xét việc xử lý dữ liệu trên thực tế.

Trích xuất tải trọng

Việc trích xuất thông tin từ tải trọng là một vấn đề của việc thao tác phần tử tải trọng đã nhận bằng cách sử dụng các kỹ thuật rất giống với DOM (xem Liệt kê 25).

Liệt kê 25. Trích xuất thông tin tải trọng
... 
import javax.xml.stream.XMLStreamException; 

public class CMSService { 
    public OMElement getNumberOfArticles(OMElement element) 
              throws XMLStreamException { 
        element.build(); 
        element.detach(); 

        String rootName = element.getLocalName(); 
        OMElement categoryElement = element.getFirstElement(); 
        String categoryElementName = categoryElement.getLocalName(); 
        String categoryValue = childElement.getText(); 

        return element; 
    } 
}

Hãy nhớ rằng, gốc của tải trọng là phần tử do hàm getNumberOfArticles nhận. Trong trường hợp này, bạn sẽ trích xuất tên của phần tử đó và sau đó chuyển nó tới phần tử con của phần tử đầu tiên của nó (trái ngược với phần tử con đầu tiên của nó, có thể là một nút văn bản rỗng) và trích ra tên và giá trị của nó. Lưu ý rằng bạn đang sử dụng phương thức getText() để kéo những thứ về cơ bản là giá trị của một phần tử con nút văn bản của phần tử thể loại (category). Đó chắc chắn là một phím tắt tiện dụng!

Tạo và trả về đáp ứng

Cuối cùng, bạn sẽ cần sử dụng dữ liệu mà bạn đã kéo từ tải trọng của yêu cầu đó để tạo ra một đáp ứng. Trong trường hợp này, bạn sẽ cung cấp cho nó một hàm thứ hai, trong một ứng dụng thực tế, hàm đó có thể thực hiện công việc khác (xem Liệt kê 26).

Liệt kê 26. Tạo một đáp ứng
... 
import javax.xml.stream.XMLStreamException; 

public class CMSService { 
      public OMElement getNumberOfArticles(OMElement element) 
                   throws XMLStreamException {
          element.build(); 
          element.detach(); 
          String rootName = element.getLocalName();
          OMElement childElement = element.getFirstElement(); 
          String childName = childElement.getLocalName(); 
          String categoryValue = childElement.getText();
          SOAPFactory factory = OMAbstractFactory.getSOAP12Factory(); 
          OMNamespace namespace = factory.createOMNamespace( 
                    "http://daily-moon.com/cms/", "resp"); 
          OMElement resultElem = factory.createOMElement(
                        "numberOfArticles",namespace); 
          String actualValue = (articleCount(categoryValue)).toString(); 
          resultElem.setText(actualValue);

          return resultElem; 
      } 

      private Integer articleCount(String catId){ 
              //Perform some function such as searching the CMS 
              //database, and return the actual value. For our 
              //purposes, you'll hardcode it. 
          return new Integer(42); 
      }
}

Trước hết, tạo nhà máy mà bạn sẽ sử dụng để tạo ra tất cả các đối tượng khác và sau đó tạo vùng tên mà bạn sẽ thêm vào tải trọng của đáp ứng. Tiếp theo, trong trường hợp này, tạo ra các phần tử kết quả thực tế và phần tử có tên là numberOfArticles.

Các nội dung của phần tử numberOfArticles sẽ là một số được hàm articleCount() trả về, số đó hoàn toàn tùy ý trong trường hợp này. Trong một ứng dụng thực, bạn sẽ làm bất cứ điều gì mà bạn cần làm để có được dữ liệu này. Một khi bạn có dữ liệu đó, bạn sẽ thiết lập nó làm nội dung của phần tử numberOfArticles và chỉ cần trả về phần tử đó.

Tất cả những gì còn lại bây giờ là triển khai dịch vụ.

Triển khai dịch vụ

Để triển khai dịch vụ này, bạn cần tạo một tệp lưu trữ Axis. Tệp này giống như một tệp *.jar hoặc một tệp *.war, trong đó nó chỉ đơn giản là một tệp nén (zip) với phần mở rộng tệp cụ thể, trong trường hợp này. aar. Thực hiện theo các bước sau để tạo tệp này:

  1. Thêm tất cả các tệp trong thư mục <AXIS2_HOME>/lib tới đường dẫn lớp (CLASSPATH) của bạn và biên dịch tệp CMSService.java.
  2. Tạo một thư mục mới có tên là META-INF trong cùng thư mục với tệp CMSService.class.
  3. Từ thư mục chứa tệp CMSService.class, hãy đưa ra lệnh này: <code type="section" width="100"> jar cvf CMSService.aar ./* </code> Bạn sẽ thấy kết quả như sau: <code type="section" width="100"> added manifest adding: CMSService.class(in = 513) (out= 330)(deflated 35%) adding: CMSService.java(in = 328) (out= 182)(deflated 44%) ignoring entry META-INF/ adding: META-INF/services.xml(in = 391) (out= 229)(deflated 41%) </code>
  4. Thêm dịch vụ cho máy chủ bằng cách sử dụng các bước được phác thảo trong phần Cài đặt một dịch vụ mẫu. (Nếu bạn thấy các lỗi servlet trên giao diện web, hãy bảo đảm rằng bạn đăng nhập vào ứng dụng Axis2. Nếu phiên làm việc của bạn đã kết thúc, ứng dụng sẽ không nhất thiết phải báo cho bạn biết, nhưng có thể hiển thị một lỗi).
  5. Nếu cần thiết, khởi động lại Geronimo. (Bạn có khả năng sẽ không phải làm điều này sau khi thêm dịch vụ, nhưng bạn có thể có phải làm điều đó sau khi thực hiện các thay đổi).

Nếu bạn nhấn vào liên kết Xem các dịch vụ, bạn sẽ thấy một thứ gì đó tương tự như thứ được thể hiện trong Hình 4.

Hình 4. Các dịch vụ sẵn có
Các dịch vụ sẵn có

Truy cập vào dịch vụ

Bây giờ bạn đã xây dựng dịch vụ, đây là lúc truy cập dịch vụ thông qua một ứng dụng khách. Hãy thực hiện những thay đổi sau đây cho tệp ClassifiedClient.java mà bạn đã tạo ra trước đó (xem Liệt kê 27).

Liệt kê 27. Sửa đổi ClassifiedClient
... 
public class ClassifiedClient { 
    private static EndpointReference targetEPR =
                   new EndpointReference(
                      "http://localhost:8080/axis2/services/CMSService");
 
    public static OMElement getEchoOMElement() { 
        SOAPFactory fac = OMAbstractFactory.getSOAP12Factory(); 
        OMNamespace omNs = fac.createOMNamespace(
                    "http://daily-moon.com/cms", "cms"); 
        OMElement method = fac.createOMElement("getNumberOfArticles", omNs); 
        OMElement value = fac.createOMElement("category", omNs); 
        value.addChild(fac.createText(value, "classifieds")); 
        method.addChild(value); return method; 
    } 
   
    public static void main(String[] args) { 
        try { 
            OMElement payload = ClassifiedClient.getEchoOMElement(); 
            Options options = new Options();
            options.setTo(targetEPR);
            options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
 
            ServiceClient sender = new ServiceClient(); 
            sender.setOptions(options); 
            OMElement result = sender.sendReceive(payload); 
            String response = result.getText();
            System.out.println("There are "+response+" classifieds at the moment."); 
        } catch (Exception e) { //(XMLStreamException e) {
              System.out.println(e.toString()); 
        } 
    } 
}

Khi bạn biên dịch và chạy ứng dụng này, bạn sẽ thấy đáp ứng đó được hiển thị trong Liệt kê 28.

Liệt kê 28. Đáp ứng ClassifiedClient
There are 42 classifieds at the moment.

Dịch vụ một chiều

Trước khi tiếp tục, chúng ta hãy xem xét các sự khác biệt có liên quan khi bạn xử lý dịch vụ một chiều chứ không phải là một dịch vụ yêu cầu/đáp ứng.

Dịch vụ

Việc tạo một dịch vụ một chiều khá đơn giản. Quá trình này là giống hệt như việc tạo ra một dịch vụ yêu cầu/đáp ứng, trừ việc bạn không thực sự trả về bất cứ thứ gì. Ví dụ, bạn có thể tạo ra hoạt động addArticle cho lớp CMSService, như trong Liệt kê 29.

Liệt kê 29. Hoạt động addArticle trong CMSServiceclass
...
    private Integer articleCount(String catId){ 
... 
    } 

    public void addArticle(OMElement element) throws XMLStreamException{ 
         element.build(); 
         System.out.println(element);
    } 
}

Trong tệp services.xml, bạn chỉ rõ hoạt động addArticle là một hoạt động "chỉ nhập vào", do đó, dù sao đi nữa người ta sẽ không dự kiến hoạt động đó trả về bất cứ điều gì, nhưng chỉ để cho bạn có thể thấy rằng một số thứ thực sự sắp xảy ra, xuất ra tải trọng đã nhận tới dòng lệnh. Bạn sẽ thấy nó trong cửa sổ Geronimo.

Trong một ứng dụng thực tế, phương thức này sẽ trích xuất thông tin từ tải trọng và thực sự thêm vào một số loại cơ sở dữ liệu hoặc kho lưu trữ khác.

Ứng dụng khách

Ứng dụng khách cho dịch vụ này cũng tương tự như những gì bạn sẽ sử dụng cho một dịch vụ yêu cầu/đáp ứng (xem Liệt kê 30).

Liệt kê 30. Tạo ứng dụng khách
import org.apache.axis2.addressing.EndpointReference; 
import org.apache.axis2.client.Options; 
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.om.OMElement; 
import org.apache.axis2.SOAP.SOAPFactory;
import org.apache.axis2.om.OMAbstractFactory; 
import org.apache.axis2.om.OMNamespace; 

public class AddArticleClient { 
    private static EndpointReference targetEPR = 
              new EndpointReference(
                    "http://localhost:8080/axis2/services/CMSService"); 

    private static OMElement getOMElement(){ 
        SOAPFactory fac = OMAbstractFactory.getSOAP12Factory();
        OMNamespace omNs = fac.createOMNamespace( 
                                  "http://daily-moon.com", "cms");
        OMElement method = fac.createOMElement("addArticle", omNs); 

        OMElement category = fac.createOMElement("category", omNs); 
        category.setText("classifieds");
        OMElement subcategory = fac.createOMElement("subcategory", omNs);
        category.setText("wantads"); 

        OMElement adtext = fac.createOMElement("article", omNs); 
        adtext.setText("Do you have good head for numbers"+ 
              " and a great deal of patience? Do you like"+ 
              " to sit for hours sorting objects by their"+ 
              " size? If so, then you could be the"+ 
              " next goober counter in the world famous"+ 
              " Murphy Brothers peanut factory. "+ 
              " Willingness to dress up as our mascot"+ 
              " helpful, but not required."); 

         method.addChild(category); 
         method.addChild(subcategory);
         method.addChild(adtext); 

         return method; 
    } 

    public static void main(String[] args){ 
        try { 
            OMElement payload = AddArticleClient.getOMElement(); 
            ServiceClient serviceClient = new ServiceClient(); 
            Options options = new Options();
            serviceClient.setOptions(options); 
            options.setTo(targetEPR);
            serviceClient.fireAndForget(payload); 
        } catch (AxisFault axisFault) {
            axisFault.printStackTrace(); 
        } 
    } 
}

Mặc dù tải trọng khác nhau, như bạn có thể thấy trong phương thức getOMElement(), sự thay đổi thực duy nhất về phần lập trình là việc sử dụng phương thức fireAndForget() chứ không phải phương thức sendReceive(). Phương thức này không trả về một đáp ứng.

Nếu bạn chạy ứng dụng khách này bạn sẽ thấy đầu ra trong cửa sổ Geronimo tương tự như kết quả được thể hiện trong Hình 5.

Hình 5. Đầu ra dòng lệnh
Đầu ra dòng lệnh

Truy cập dịch vụ qua GET

Trước phiên bản 1.2 của SOAP, cách duy nhất để truy cập một dịch vụ Web dựa trên SOAP khi sử dụng HTTP là thông qua việc sử dụng một yêu cầu POST. Bạn sẽ cần tạo một ứng dụng khách để tạo một yêu cầu POST với thông báo SOAP làm nội dung của yêu cầu đó. Tuy nhiên, phiên bản SOAP 1.2 định nghĩa các phương tiện để truy cập một dịch vụ web dựa trên SOAP bằng cách sử dụng một yêu cầu GET.

GET so với POST

Trước khi tiếp tục, điều quan trọng là hiểu được sự khác biệt giữa các yêu cầu GETPOST trên HTTP. Mặc dù nhiều lập trình viên web hành động như thể hai yêu cầu này có thể thay thế cho nhau được, nhưng trên thực tế có một mục đích đằng sau từng yêu cầu đó. GET, trong đó tất cả thông tin về nguồn lực bạn đang yêu cầu được chứa trong URL, thường là các tham số, có nghĩa là được sử dụng chỉ cho yêu cầu không thay đổi giá trị. Các tham số đó là những yêu cầu mà với chúng không có "tác dụng phụ". Nói cách khác, bạn có thể gọi yêu cầu đó một chục lần, một trăm lần, một ngàn lần và nó không cần thay đổi bất cứ điều gì. Ví dụ, một yêu cầu web để biết nhiệt độ hiện có tại Albuquerque là không thay đổi giá trị. Không có một yêu cầu web để chèn một ý kiến vào một cơ sở dữ liệu blog.

Lý do cho việc này là các yêu cầu GET có thể được thêm vào các đánh dấu của một người dùng và được truy cập mà không có cảnh báo. Các yêu cầu GET cũng có thể được làm mới mà không có cảnh báo. Mặt khác, một yêu cầu POST có thông tin của nó trong phần thân của yêu cầu và vì vậy rất khó để vô tình lặp lại.

Đối với SOAP, điều này có nghĩa là bạn sẽ có thể sử dụng GET cho các yêu cầu SOAP chỉ cần lấy ra thông tin mà không tạo ra các thay đổi. Bạn vẫn nên sử dụng POST cho bất kỳ hoạt động nào tạo ra các thay đổi.

Truy cập dịch vụ

Trong Axis2, bạn có thể tạo một yêu cầu GET và máy chủ sẽ dịch nó thành một thông báo SOAP và trả về tải trọng làm kết quả. Ví dụ, trỏ trình duyệt của bạn tới vị trí được hiển thị trong Liệt kê 31.

Liệt kê 31. Truy cập dịch vụ
http://localhost:8080/axis2/services/CMSService/getNumberOfArticles?category=classifieds

Theo như phiên bản 0.94, bạn sẽ thấy một đáp ứng được hiển thị trong Liệt kê 32.

Liệt kê 32. Đáp ứng tải trọng SOAP
<resp:numberOfArcticles>42</resp:numberOfArcticles>

Tuy nhiên, điều này không hoàn toàn chính xác. Theo Khuyến nghị của phiên bản SOAP 1.2, bạn sẽ thấy toàn bộ đáp ứng SOAP. Điều này có thể sẽ thay đổi trong các phiên bản tương lai của Axis2.


Xử lý tệp đính kèm

Một sự thay đổi trên thông báo SOAP đơn giản là tệp đính kèm. Các tệp đính kèm đã làm cho mọi người phải chú ý trong nhiều năm qua, nhưng vì hiện nay chúng được các đặc tả mở rộng nào đó yêu cầu, nên bạn đã bắt đầu xử lý chúng.

Dữ liệu nhị phân và XML

Mặc dù XML là một định dạng dựa trên văn bản, đúng là bạn không thể bỏ qua thực tế rằng XML là một thế giới nhị phân ở ngoài định dạng đó. Như vậy, sẽ có lúc khi người ta yêu cầu bạn chuyển thông tin nhị phân đến hoặc từ một dịch vụ web.

Bạn có thể xử lý tình huống này theo một trong hai cách. Tùy chọn đầu tiên thực sự bao gồm dữ liệu nhị phân bên trong tài liệu của bạn. Một ví dụ về tình huống này xảy ra khi bạn lưu một tài liệu Microsoft Word như là một tệp XML. Nếu bạn có bất kỳ hình ảnh nào được nhúng trong tài liệu đó, Word sẽ nhúng các hình ảnh đó trong tài liệu XML như là dữ liệu nhị phân, được mã hóa theo Base64. Tùy chọn thứ hai là chỉ cần tham chiếu dữ liệu sao cho ứng dụng xử lý tài liệu có thể tìm thấy dữ liệu đó. Một ví dụ rất phổ biến về tình huống này là một trình duyệt Web và cách nó xử lý các hình ảnh được tham chiếu từ một tệp XHTML. Tệp XHTML bao gồm một phần tử img (hoặc một phần tử object, nếu bạn được nâng cao một cách thích hợp) và phần tử đó bao gồm một thuộc tính src chứa URL trỏ đến dữ liệu thực tế. Sau đó ứng dụng này có thể tải dữ liệu từ vị trí đó và sử dụng nó một cách thích hợp.

Tình huống tương tự áp dụng với các tài liệu SOAP. Nếu bạn đã, ít nhất, gửi một hình ảnh tới một dịch vụ dựa trên SOAP, bạn có hai tùy chọn. Bạn có thể nhúng dữ liệu nhị phân đó trong tải trọng hoặc bạn có thể tìm một cách để tham chiếu nó. Trước đây, nó đã được tham chiếu, do các vấn đề liên quan đến băng thông.

Các gói tối ưu hóa dữ liệu nhị phân-XML

Như bạn thấy, XML đã có nhiều dữ liệu dài dòng hơn các dữ liệu nhị phân mong muốn. Và như vậy, nó sử dụng rất nhiều băng thông. Do đó, khi bạn xem xét thực tế là phương thức ưa thích để thêm dữ liệu nhị phân tới một tài liệu văn bản XML - mã hóa nó như là Base64 - có xu hướng làm tăng kích thước của nó gấp hai hoặc nhiều lần hơn, bạn gặp một vấn đề thực sự.

Trong thực tế, trong vài năm gần đây, có một sự phản ứng như vậy về việc thiếu hỗ trợ cho dữ liệu nhị phân trong bất kỳ cách thức thực sự nào, gần như có một cuộc nổi dậy và W3C đã bàn đến vấn đề này. Kết quả là XOP (Các gói tối ưu hóa dữ liệu nhị phân-XML - XML-binary Optimized Packages). Giao thức này cung cấp một cách để bạn tham chiếu tin cậy dữ liệu bên ngoài từ bên trong một tài liệu XML. Ví dụ, SOAP với đặc tả Attachments (các tệp đính kèm) cho rằng dữ liệu nhị phân có thể được gửi như một phần của một tài liệu MIME nhiều phần, với dữ liệu XML cấu thành phần đầu tiên, và dữ liệu nhị phân được thêm vào như là các phần bổ sung. Điều này làm nảy sinh vấn đề là mặc dù chương trình của bạn có thể biết rằng dữ liệu tồn tại, còn tài liệu thì không biết. Nó cũng không cho phép tối ưu hóa chọn lựa tài liệu hoặc việc xử lý có hiệu lực hồi tố của một tài liệu hiện có bao gồm cả dữ liệu nhị phân.

XOP cải thiện tình hình này bằng cách cung cấp một cơ chế mà theo đó bạn có thể trích xuất có chọn lọc thông tin cần được tối ưu hóa, thêm nó vào một thông báo MIME nhiều phần, bao gồm thông báo SOAP của bạn và tham chiếu nó một cách rõ ràng. Hãy xem một ví dụ

Ví dụ, giả sử thay vì thêm một bài viết mới như là phần tử văn bản, thì nhân viên lại muốn thêm nó như là một tài liệu nhị phân, ít nhất, từ một chương trình xử lý văn bản. Để bao gồm nội dung đó trong phần thân của thông báo là hết sức lộn xộn, như trong Liệt kê 33:

Liệt kê 33. Thêm một tài liệu nhị phân
<?xml version='1.0' ?> 
<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
  <env:Header>
  </env:Header> 
  <env:Body> 
    <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">
       <cms:category>classifieds</category> 
       <cms:subcategory>forsale</cms:subcategory> 
       <cms:articleHeadline><cms:articleHeadline>
       <cms:articleText>wvetwenptiubnweoirntuwopeirt4m[456n09ew7nv
        sa0tv043u6y304o5mu60ew9rebtm45bm4-69nw-0er9utnv3094nb-26204
        95u6-49kv6-m34956h-wb09emjb-0n67u-340v,=qw-enr7w8b64b03278-
        ANDLOTSMOREBASE64ENCODEDDATAHERE</cms:articleText>
    </cms:addArticle> 
  </env:Body> 
</env:Envelope>

XOP quy định rằng để thay thế, bạn trích xuất dữ liệu và thay thế bằng một phần tử Include (Bao gồm) tham chiếu vị trí mới của nó, như trong ví dụ được thể hiện trong Liệt kê 34.

Liệt kê 34. Sử dụng XOP
MIME-Version: 1.0 
Content-Type: Multipart/Related;
    boundary=MIME_boundary;
    type="application/xop+xml"; 
    start="<soapmsg.xml@daily-moon.com>";
    start-info="text/xml" 
Content-Description: An XML document with binary data in it 

--MIME_boundary 
Content-Type: application/xop+xml; 
    charset=UTF-8;
    type="text/xml" 
Content-Transfer-Encoding: 8bit 
Content-ID: <soapmsg.xml@daily-moon.com> 

<env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
  <env:Header></env:Header> 
  <env:Body> 
    <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">
       <cms:category>classifieds</category> 
       <cms:subcategory>forsale</cms:subcategory> 
       <cms:articleHeadline><cms:articleHeadline>
       <cms:articleText>
           <xop:Include xmlns:xop='http://www.w3.org/2004/08/xop/include'
            href='cid:http://daily-moon.com/tbird.doc' />
       </cms:articleText>
    </cms:addArticle> 
  </env:Body> 
</env:Envelope> 

--MIME_boundary
Content-Type: application/vnd.oasis.openoffice 
Content-Transfer-Encoding: binary
Content-ID: <http://daily-moon.com/tbird.doc> 

// binary octets for the word processing file 
--MIME_boundary--

Lưu ý rằng vị trí đã chỉ định trong phần tử Include phù hợp với Content-ID, trừ giao thức là cid:. Đây là thông báo bây giờ được gửi đi, chứ không phải là một thông báo SOAP văn bản rõ.

SOAP, dữ liệu nhị phân và Axis2

Quá trình sử dụng XOP trong các tài liệu SOAP được gọi là MTOM (viết tắt của Cơ chế tối ưu hóa truyền dẫn thông báo - Message Transmission Optimization Mechanism) của SOAP. Axis2 cung cấp sự hỗ trợ cho phương tiện làm việc này với dữ liệu SOAP, nhưng bạn phải chắc chắn để cấu hình ứng dụng thích hợp.

Cụ thể, bạn phải kích hoạt nó trong tệp axis2.xml trong tệp axis2.war (xem Liệt kê 35).

Liệt kê 35. Sử dụng XOP với Axis2
<axisconfig name="AxisJava2.0"> 
   <!-- ================================================= --> 
   <!-- Parameters --> 
   <!-- ================================================= -->
   <parameter name="hotdeployment" locked="false">true</parameter>
   <parameter name="hotupdate" locked="false">true</parameter>
   <parameter name="enableMTOM" locked="false">true</parameter> 

   <!-- Uncomment this to enable REST support --> 
   <!-- <parameter name="enableREST" locked="false">true</parameter>--> 
   
   <parameter name="userName" locked="false">admin</parameter> 
   <parameter name="password" locked="false">axis2</parameter> 
...

Nếu cần, bạn có thể trích xuất tệp axis2.war, thực hiện thay đổi này và nén lại nó vào một tệp .war.

Để thay thế ứng dụng Axis2, hãy truy cập vào bàn điều khiển Geronimo, sử dụng URL được hiển thị trong Liệt kê 36.

Liệt kê 36. Bàn điều khiển Geronimo
http://localhost:8080/console

Đăng nhập với tư cách là hệ thống/người quản lý và nhấn Application>Web App WARs, sau đó gỡ bỏ cài đặt và cài đặt lại ứng dụng Axis2. (Hãy nhớ rằng, bạn sẽ phải nạp lại các dịch vụ Web của bạn sau khi thực hiện bước này).

Thực hiện theo chương trình với MTOM nằm ngoài phạm vi của hướng dẫn này, nhưng bạn có thể nhận thêm thông tin về chủ đề này trong phần Tài nguyên. Chỉ cần biết rằng có nhiều thứ có thể không làm việc như mong đợi trong các phiên bản Axis2 trước phiên bản 0.95, trong đó bao gồm một SOAP chức năng với Attachments API (API các tệp đính kèm) cho việc thực hiện Java (SAAJ).


Tóm tắt

Trong thế giới ngày nay, nơi mà tính tương thích giữa các hệ thống rất quan trọng, các dịch vụ Web có thể là nền tảng của SOA (Kiến trúc hướng dịch vụ) của bạn. Và SOAP là nền tảng của các dịch vụ Web mức doanh nghiệp. Hướng dẫn này đã dạy bạn những khái niệm cơ bản của các dịch vụ Web và đã giải thích cả hai các khái niệm và sự cần thiết lập trình để hiểu và làm việc với SOAP trong các ứng dụng của riêng bạn. Theo hướng dẫn này, bạn đã học được như sau:

  • Các khái niệm quan trọng xung quanh các dịch vụ Web.
  • Cách cài đặt và sử dụng máy chủ ứng dụng Geronimo.
  • Cách cài đặt và sử dụng ứng dụng các dịch vụ Web Axis2.
  • Cách tạo một ứng dụng khách để truy cập một dịch vụ SOAP.
  • Cách tạo một dịch vụ SOAP.
  • Các vấn đề bổ sung xung quanh các dịch vụ SOAP, chẳng hạn như các yêu cầu GET và các tệp đính kèm.

Trong phần 2 của loạt bài này, WSDL (Ngôn ngữ mô tả các dịch vụ Web), bạn sẽ học cách sử dụng WSDL để tự động hóa nhiều bước mà bạn đã thực hiện ở đây, cũng như để cung cấp các phương tiện cho những người khác sử dụng dịch vụ mà bạn xây dựng dễ dàng hơn.


Tải về

Mô tảTênKích thước
Source codews-understand-web-services1.zip12KB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

  • Tải về Apache Geronimo ở đây.
  • Tải về Apache Axis2 ở đây. Hướng dẫn này sử dụng phiên bản 0.94, nhưng các phiên bản sau cũng sẽ dùng được
  • Tải về SDK J2SE ở đây.

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=SOA và dịch vụ Web
ArticleID=549726
ArticleTitle=Hiểu biết về Đặc tả các dịch vụ Web, Phần 1: SOAP
publish-date=10082010