使用 python 开发 Web Service
使用 python 開發(fā) Web Service
Python 是一種強大的面向?qū)ο竽_本語言,用 python 開發(fā)應(yīng)用程序往往十分快捷,非常適用于開發(fā)時間要求苛刻的原型產(chǎn)品。使用 python 開發(fā) web service 同樣有語言本身的簡捷高速的特點,能使您快速地提供新的網(wǎng)絡(luò)服務(wù),從而適應(yīng)快速發(fā)展的網(wǎng)絡(luò)商業(yè)環(huán)境。本文將用實例一步步描述如何用 Python 開發(fā) web service。
1?評論:
?
- 內(nèi)容
搭建開發(fā)環(huán)境
一個基本的 python web service 開發(fā)環(huán)境由以下這些工具組成:
Python2.4,Eclipse WTP,PyDev plug-in,Python ZSI包。
安裝 python2.4
Python2.4 可以在網(wǎng)站 http://www.python.org/download/realses/2.4,下載安裝包,安裝過程非常簡單,在此不再贅述。
安裝 Eclipse WTP
Eclipse WTP 可以在 http://download.eclipse.org/webtools/downloads/ 下載。
安裝 pyDev
在 http://pydev.sourceforge.net/download.html 下載 pyDev 插件,解壓后將 features 目錄和 plugin 目錄下的所有文件都拷貝到 Eclipse 的相同目錄下就可以了。本文中使用的是 release1.3.9。
安裝 python ZSI
從 ZSI 的網(wǎng)站上下載最新的安裝包,在寫這篇文章的時候,最新的 ZSI 版本為 2.0。解壓縮后運行如下命令:
圖 1.
ZSI 還依賴與一些其它的 python 開源包:SOAPpy,pyXML。本文在后面列出了它們的下載地址。必須安裝這些 python 包 ZSI2.0 才能正常運行。
本文提供的 Web service 描述
在本文中我們將利用 python 提供幾個 web service,然后用 Java 客戶端調(diào)用它們。作為演示,我們僅設(shè)計了三個簡單的 web service:
getTime():返回代表當(dāng)前時間的字符串。沒有輸入?yún)?shù)。
sayHello(username):返回一個字符串,內(nèi)容為“Hello username”,其中 username 為傳入?yún)?shù)。
showUser(username):根據(jù)輸入的 username 返回一個復(fù)雜數(shù)據(jù)類型 userInfo,描述用戶的年齡,性別,聯(lián)系地址。
創(chuàng)建工程
首先創(chuàng)建一個工程。打開 Eclipse,選擇 File->New Project。當(dāng) pyDev 插件安裝好后,會有一個 pyDev project 的選項。選擇該選項并創(chuàng)建一個 pyDev 工程。
編寫 wsdl 文件
Wsdl 是一個 XML 文件,它主要用來描述所提供的網(wǎng)絡(luò)服務(wù)的細節(jié)。用戶通過 wsdl 文件就可以了解您所提供的網(wǎng)絡(luò)服務(wù)的調(diào)用接口的所有細節(jié)。
感謝 Eclipse WTP 提供的 WSDL Editor,它使得編寫 WSDL 文件變成了一件輕松的事情。WSDL Editor 提供了可視化的編輯界面。利用 WSDL Editor,用戶可以完全從服務(wù)本身來思考,無需深入了解 WSDL 的細節(jié)。
首先要在工程中增加一個 WSDL 文件,點擊菜單 File->New 選擇 Other,在彈出的對話框中選擇WSDL文件。如下圖所示:
圖 2.
單擊 next,給新文件命名為 myServices.wsdl。選擇缺省選項并點擊 finish 按鈕就會生成一個缺省的空 wsdl 文件。此時,將看到如下所示的編輯界面:
圖 3.
缺省的 WSDL 包含了三個部分 Service,Binding 和 operation。對于一般的應(yīng)用,只需修改 operation,即上圖中最右邊的方框。為了提供前面所描述的三個網(wǎng)絡(luò)服務(wù),我們需要在這個方框中增加三個新的 operation。
第一個網(wǎng)絡(luò)服務(wù)是 getTime。將缺省 wsdl 文件的 operation 方框中的第一個表項修改一下,就可以完成 getTime 的定義了。首先單擊標(biāo)題 NewOperation,將名字高亮選中,如下圖所示:
圖 4.
將其重新命名為 getTime。getTime 服務(wù)沒有入口參數(shù)。但有一個返回值,我們定義返回值為一個表示時間的字符串。注意圖二中方框外右邊的兩個箭頭,雙擊它們就可以分別進入定義入口和出口參數(shù)的窗口。首先雙擊 Input 后面的箭頭 (上圖中用紅色圓圈標(biāo)出),可以進入如下圖所示的參數(shù)定義窗口:
圖 5.
在新打開的 Inline Schema of myServices.wsdl 窗口中,我們可以設(shè)置 getTime 的入口參數(shù)。getTime 不需要入口參數(shù),因此將缺省的入口參數(shù) in 刪除:
圖 6.
關(guān)閉新打開的窗口,回到圖一所示的 wsdl 編輯界面。雙擊 getTime 的 output 后面的箭頭,定義返回值。將缺省的返回值名字 out 修改為 timeStr,類型 string,不需要改變:
圖 7.
這樣 getTime 就設(shè)計好了。下面回到主窗口,添加 sayHello 的定義。在 Operation 方框上單擊鼠標(biāo)右鍵,選擇 Add Operation:
圖 8.
同樣,雙擊方框右邊的箭頭,分別設(shè)置其入口參數(shù)和返回值。sayHello 的入口參數(shù)為字符型,名字為 username。返回值也是 string 類型。
添加新的 operation,命名為 showUser。這個服務(wù)的入口參數(shù)也是用戶名,類型為 string,但是它的返回值是一個復(fù)雜類型。用 WSDL Editor 可以方便地定義復(fù)雜類型。進入返回值設(shè)計窗口(雙擊 output 后的箭頭),在 element 上單擊鼠標(biāo)右鍵,彈出菜單中選擇 Set Type->New。在彈出對話框中選擇 Complex Type,并將新類型命名為 userInfo。
在eclipse的outline 窗口中選中 types->userInfo,定義 userInfo。
圖 9.
主窗口顯示出 userInfo 的設(shè)計界面,鼠標(biāo)右鍵單擊 userInfo,選擇彈出菜單的 add element,增加三個 string 類型的元素 name, gender 和 address。如下圖所示:
圖 10.
現(xiàn)在可以存盤了,三個服務(wù)都已經(jīng)設(shè)計好。下一步,我們將用 python ZSI 提供的腳本處理 WSDL 文件,并生成服務(wù)代碼框架。
編寫 web service 服務(wù)端代碼
ZSI 包提供了兩個腳本用來根據(jù) wsdl 文件生成相應(yīng)的 server 端和 client 端的 python 代碼框架。下面的命令生成 server 端代碼:
圖 11.
腳本 wsdl2py 的 -b 選項會生成一些輔助代碼,后面的描述中將會看到這些輔助代碼能簡化編程。運行以上兩條命令后,會生成三個文件:
myServices_services.py , myServices_services_server.py , myServices_services_types.py
這三個 python 文件就是服務(wù)端的代碼框架。為了提供最終的 web 服務(wù),我們還需要添加一個文件,用來實現(xiàn)每個 web 服務(wù)的具體代碼。將新文件命名為 serviceImpl.py(完整的源代碼可以在文章最后下載)。僅實現(xiàn) getTime 的 serviceImpl.py 如下:
from myServices_services_server import * from time import time,ctime from ZSI.ServiceContainer import AsServer class mySoapServices(myServices):def soap_getTime(self,ps):try:rsp = myServices.soap_getTime(self, ps)request = self.requestrsp.set_element_timeStr(ctime())except Exception, e:print str(e)return rsp首先導(dǎo)入 myServices_services_server,它是由 wsdl2py 腳本生成的 Web 服務(wù)框架代碼。類 myServices 是 web 服務(wù)的基礎(chǔ)類,每一個 web 服務(wù)都對應(yīng)其中的一個方法。getTime 對應(yīng) myServices 類中的 soap_getTime 方法。缺省的 soap_getTime 方法只是一個基本框架,但完成了 soap 解析并且能返回該服務(wù)的入口參數(shù)對象。
為了實現(xiàn) getTime,我們需要重載 soap_getTime 方法。定義新類 mySoapServices,繼承自 myServices。在 mySoapServices 類中重載父類的 soap_getTime() 方法。
getTime 的主要功能是返回一個表示當(dāng)前時間的字符串。python 系統(tǒng)函數(shù) ctime,就可以得到當(dāng)前的系統(tǒng)時間。重載 soap_getTime() 函數(shù)中,首先調(diào)用父類的 soap_getTime() 方法,得到返回值對象rsp。
調(diào)用返回值對象 rsp 的 set_element_xxx() 方法,就可以對返回值對象中的元素進行賦值。這個方法是由 wsdl2py 的 -b 選項生成的。
set_element_timeStr(ctime()) 將返回值的 timeStr 元素賦值為代表當(dāng)前時間的字符串。
sayHello() 的代碼與此類似。但是與 getTime 不同,sayHello 服務(wù)還需要處理客戶端調(diào)用時傳入的入口參數(shù)。sayHello 方法的源代碼:
def soap_sayHello(self,ps):try:rsp = myServices.soap_sayHello(self,ps)request = self.requestusrName = request.get_element_userName()rsp.set_element_helloStr("Hello "+usrName)except Exception, e:print str(e)return rsprequest 代表入口參數(shù)對象。對于 sayHello 服務(wù),入口參數(shù)只有一個元素 userName。調(diào)用 request 對象的 get_element_userName() 方法就可以得到該元素的值。
調(diào)用返回值對象 rsp 的 set_element_helloStr 將返回字符串賦值給 helloStr 元素。
showUser 服務(wù)與前面兩個服務(wù)的不同在于返回值是一個復(fù)雜對象,該復(fù)雜對象在 python 中可以用下面這個類來表示:
class userInfo:def __init__(self,nm,gen,addr):self.name = nmself.gender = genself.address = addrshowUser 服務(wù)根據(jù)客戶端傳入的用戶名在數(shù)據(jù)庫中查找該用戶的詳細信息并填充 userInfo 對象,相應(yīng)代碼如下:
def soap_showUser(self,ps):try:rsp = myServices.soap_showUser(self,ps)request = self.requestuName = request.get_element_userName()userDetail = rsp.new_user()nm=self.users[uName].nameuserDetail.set_element_name(nm)gender=self.users[uName].genderuserDetail.set_element_gender(gender)addr=self.users[uName].addressuserDetail.set_element_address(addr)rsp.set_element_user(userDetail)except Exception, e:print str(e)return rsp調(diào)用 request 對象的 get_element_userName 方法得到入口參數(shù),并賦值給 uName。然后在數(shù)據(jù)庫中查找用戶uName的詳細信息,將詳細信息填充到 userInfo 類對象中,并返回。作為演示,我們并沒有真的到數(shù)據(jù)庫中查詢,而是在內(nèi)存中建立一個字典:
u1 = userInfo("u1","M","Shanghai")u2 = userInfo("u2","F","Beijing")self.users={}self.users["u1"]=u1self.users["u2"]=u2該字典中有兩個用戶:u1 和 u2。演示代碼在該字典中查詢用戶,將查選結(jié)果返回用戶。
調(diào)用 rsp 對象的 new_element_user() 方法創(chuàng)建一個新的返回對象,并用 userDetail 保存。
調(diào)用 userDetail.set_element_gender 將用戶性別信息設(shè)置到返回值對象的 gender 元素中。同樣方法設(shè)置用戶名和地址。
最后將新建的 userDetail 對象設(shè)置到返回值 rsp 中:rsp.set_elememnt_user(userDetail)。
發(fā)布 web service
所有 web 服務(wù)代碼都已經(jīng)寫好了,需要服務(wù)器代碼來發(fā)布它們。在復(fù)雜并且有較高要求的應(yīng)用環(huán)境中,用戶可能需要用 apache 等強大的 web server 來發(fā)布 web services。限于篇幅,本文不打算介紹如何在 apache 上發(fā)布 python web services。本文將使用 ZSI 自帶的 SOAP server。
正如下圖所示,使用 ZSI soap server 只需要很少的幾行代碼:
from ZSI.ServiceContainer import AsServer from serviceImpl import mySoapServices from ZSI import dispatch if __name__ == "__main__":port = 8888AsServer(port,(mySoapServices('test'),))這段代碼無需太多解釋。port 定義了 web service 發(fā)布的端口號。ZSI 包的 AsServer 方法只有兩個參數(shù):一個是端口;另外一個是包含了 web 服務(wù)實現(xiàn)代碼的類,在我們的實驗中就是 mySoapServices。字符串 test,表示 web 服務(wù)發(fā)布時的虛擬路徑。當(dāng)上述代碼成功運行之后,就會在 localhost 上開啟一個 web server,并在端口 8888 發(fā)布 myServices 服務(wù)。一切都非常簡單,體現(xiàn)了用 python 語言的最吸引人的特點,快速而強大!
我們將在本機訪問 myServices,相應(yīng)的 URL 為 http://localhost/test?wsdl。
編寫 java 客戶端
現(xiàn)在我們使用 eclipse 集成環(huán)境來開發(fā) web services 的客戶端程序,調(diào)用前面章節(jié)描述的那些 web services。
Eclipse 提供了一個簡單的方法來創(chuàng)建 web service 應(yīng)用程序,即 Web Service Wizard。
首先創(chuàng)建一個 Web Project。
打開 File->New->Other…->Dynamic Web Project,創(chuàng)建一個新的工程。
圖 12.
然后就可以創(chuàng)建 java 客戶端。選擇 File -> New -> Other... -> Web Services -> Web Service Client
圖 13.
選擇 Next,在下一個窗口中的 Service Definition 中填寫相應(yīng)的 webservice 的發(fā)布地址 URL。在本文中為: http://localhost:8888/test?wsdl
圖 14.
選擇 Finish 按鈕。將自動生成 java 代碼。包括以下幾個文件: MyService_PortType.java MyService_Service.java MyService_ServiceLocatior.java MyServiceProxy.java MyServiceSOAPStub.java
另外 showUser() 返回一個復(fù)雜對象,所以 eclipse 還創(chuàng)建了一個 java 類表示該復(fù)雜對象類,文件名為 UserInfo.java
作為測試,我們寫了一個 java 小程序,調(diào)用 getTime。
import org.example.www.myService.MyServiceProxy; public class HelloClient {public static void main(String[] args){try {System.out.println("Step1");MyServiceProxy hello = new MyServiceProxy();System.out.println("Step2");java.lang.String str = hello.getTime();System.out.println("step over");System.out.println(str);} catch (Exception ex){System.out.println(ex.getMessage());}} }sayHello 和 showUser 的調(diào)用代碼與上面的示例類似。
總結(jié)
用 Eclipse 的 WTP 開發(fā) WSDL 文件,用 python 實現(xiàn) Web 服務(wù)都比較簡單而快速。用這兩個強大的工具能夠迅速地開發(fā) Web 服務(wù)應(yīng)用,適用于原型產(chǎn)品的快速開發(fā)。 這樣就能抓住先機,比對手更快的推出新的Web應(yīng)用,從而在市場上立于不敗之地。
參考資料
- ZSI online document http://pywebsvcs.sourceforge.net/zsi.html
- SOAPy download page : http://soapy.sourceforge.net
- pyXML download page: http://pyxml.sourceforge.net
條評論
轉(zhuǎn)載于:https://www.cnblogs.com/L-H-R-X-hehe/p/3815450.html
總結(jié)
以上是生活随笔為你收集整理的使用 python 开发 Web Service的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 民生银行信用卡可以通过短信激活吗?怎么用
- 下一篇: Python3 From Zero——{