目錄
1 定義Service
2 服務端釋出Service
2.1 排除WebService中的某個方法
3 用戶端通路Service
4 java2ws工具的使用
4.1 指令行使用java2ws
4.2 Maven使用java2ws
5 基于Spring的Jax-ws WebService
5.1 Service定義
5.2 服務端釋出Service
5.3 用戶端擷取Service
6 WSDL生成Java代碼
6.1 wsdl2java工具
6.2 cxf-codegen-plugin
Jax-ws是WebService的一種規範。
Jax-ws的WebService定義是通過注解進行的,我們必須在其WebService類的接口上使用@WebService注解進行标記。
如上,我們把HelloWorld定義為一個WebService,其對應有一個sayHi操作。其對應的實作類如下:
對于Jax-ws WebService而言,釋出Service有兩種方式。
第一種:
第二種:
我們可以看到在上面我們的sayHi操作的參數who變成了arg0,這是因為接口在被編譯為class檔案的時候不能儲存參數名,有時候這會影響可讀性。如果需要參數名顯示的可讀性強一些的話,我們可以使用@WebParam來指定,如:
@WebService的serviceName可以用來指定service的名稱,預設情況下如果Service是通過Endpoint.publish()方法釋出的則serviceName為實作類的簡單名稱+Service(如HelloWorldImplService),如果是通過JaxWsServerFactoryBean的create方法釋出的則為接口的簡單名稱+Service(如HelloWorldService)。name屬性可以用來指定service對應的portName,預設情況下如果Service是通過Endpoint.publish()方法釋出的則portName為實作類的簡單名稱+Port(如HelloWorldImplPort),如果是通過JaxWsServerFactoryBean的create方法釋出的則為接口的簡單名稱+Port(如HelloWorldPort)。
除了@WebService、@WebParam之外,Jax-ws還為我們提供了一系列的注解,如@WebMethod、@OneWay。
@WebMethod是用來标注在WebService的方法即操作上的,通過它我們可以指定某一個操作的操作名、使用SOAP綁定時的Action名稱,以及該方法是否允許釋出為WebService。@WebMethod有三個屬性:operationName、action和exclude。@WebMethod還是挺有用的,當你釋出的WebService中有方法不希望WebService通路的時候就可以通過@WebMethod來指定将其排除在外。下面我們來介紹一下使用WebMethod排除WebService中的一個方法。
@Oneway是标注在Service接口的操作方法上的。使用@Oneway标注的方法表示它不需要等待服務端的傳回,也不需要預留資源來處理服務端的傳回。
首先我們往我們的HelloWorld接口中新增一個方法sayHello。
對于有接口的WebService而言,@WebMethod的exclude定義必須指定在其實作類對應的需要排除的方法上,而其他屬性則必須在接口方法上定義。是以我們的實作類定義如下:
這樣,在服務釋出時就會把sayHello方法排除在外。有興趣的朋友可以通過檢視指定exclude前後的wsdl檔案驗證一下sayHello方法是否在exclude為true時被排除了。用戶端在通路sayHello方法的時候也是不會成功的。
類似于WebService簡單實作裡面的ClientProxyFactoryBean,在使用Jax-ws時我們可以通過JaxWsProxyFactoryBean來通路服務,如:
除了上面的方式之外,我們還可以這樣擷取Service:
在上面的代碼中我們隻需要有一個Service執行個體,就能通過它來擷取真正的WebService,是以,我們如果把上面的代碼改成如下形式也是可以的。
上面這種通過Service來擷取WebService的方法是不适用前面介紹的簡單WebService實作的,即不适用擷取通過ServerFactoryBean釋出的WebService。
Cxf為我們提供了一個java2ws工具。通過該工具我們可以根據SEI(Service Endpoint Implementation的縮寫)類及其相關的類來生成WebService的服務端、用戶端和wsdl檔案等。SEI需要是使用了@WebService标注的Service接口或類。
在Cxf根目錄下的bin目錄下有一個java2ws工具,我們可以在指令行下使用該指令生成相應代碼。Java2ws指令後面可以接很多參數,主要有:
參數名
作用
-?|-h|-help
這三個參數都可輸出java2ws指令的幫助資訊
-wsdl
生成wsdl檔案
-o fileName
指定生成的wsdl檔案的名稱
-d resourceDir
指定資源檔案存放的目錄,生成的wsdl檔案也會放在該目錄下
-server
指定生成服務端代碼
-client
指定生成用戶端代碼
-wrapperbean
指定生成wrapper和fault bean
-cp classpath
指定java2ws搜尋SEI和相關類型類的路徑
-t targetNameSpace
指定targetNameSpace
-servicename serviceName
指定serviceName
-verbose
在生成代碼的時候顯示注釋資訊
-quiet
在生成代碼的時候不顯示注釋資訊
-s sourceDir
指定生成的java代碼存放的目錄
-classdir classdir
指定生成的java代碼編譯後的class類存放的目錄
className
指定SEI類的名稱
在使用java2ws指令時className是必須給定的,其他的參數都可選。java2ws将會到classpath路徑下或使用-cp參數指定的classpath路徑下尋找SEI類及其相關類型。
示例:
java2ws –server com.tiantian.cxftest.sample.jaxws.HelloWorld(生成服務端代碼)
java2ws –wsdl –cp . com.tiantian.cxftest.sample.jaxws.HelloWorld(在目前目錄下尋找HelloWorld類生成wsdl檔案)
Cxf為java2ws工具提供了一個Maven的插件,叫cxf-java2ws-plugin。是以當我們的項目是使用Maven的時候我們可以在項目的pom.xml檔案中加入Cxf提供的cxf-java2ws-plugin,這樣當我們執行Maven的某個操作的時候就會觸發java2ws指令生成對應的代碼。如:
對于java2ws指令的參數可以通過configuration元素下的元素來指定。可以配置的參數如下:
classpath
搜選SEI類等相關類的類路徑,預設情況下會到目前項目的類路徑下尋找
outputFile
生成的wsdl檔案存放的位置,預設是${project.build.directory}/generated/wsdl/${className}.wsdl
genWsdl
預設為true。是否生成wsdl檔案。
genServer
預設false。是否生成Server端代碼。
genClient
預設為false。是否生成Client端代碼。
genWrapperbean
預設為false。是否生成wrapper bean
frontend
表明使用的frontend。支援jaxws和simple,預設是jaxws。
databinding
指定資料綁定。預設frontend為jaxws時用jaxb,simple用aegis
serviceName
soap12
指定生成的wsdl檔案包含soap1.2綁定
targetNameSpace
指定用來生成wsdl檔案時的target namespace
verbose
生成代碼的過程中顯示注釋資訊
quiet
attachWsdl
當為true時,在對目前項目進行Maven的install操作時會把生成的wsdl檔案以目前項目的groupId、artifactId和version,以type為wsdl一起安裝到Maven的repository中去。預設為true
address
指定port的address
使用cxf-java2ws-plugin插件生成的Java代碼預設會放在項目的根目錄下。
Service定義跟之前的定義是一樣的。
首先在web.xml檔案中定義一個CXFServlet,用于釋出和攔截WebService請求。
接下來在我們的WebService配置檔案裡面定義我們的WebService釋出,即CXFServlet指定的jaxws-cxf-servlet.xml檔案(預設是cxf-servlet.xml檔案)。這裡我們定義如下:
用戶端可以直接從Spring的bean配置檔案中把WebService配置為一個個普通的Spring bean對象進行使用。這主要有兩種方式,第一種是使用Jaxws命名空間,第二種是使用JaxWsProxyFactoryBean。
在定義之前需要往bean配置檔案中引入Jax-ws的命名空間。這裡我們在classpath下定義一個jaxws-cxf-client.xml檔案,其内容如下所示:
之後我們就可以把這些定義好的WebService當做一個普通的bean對象來使用了,如:
如果我們已經有了wsdl定義檔案的話,我們就可以通過wsdl檔案生成對應的Java代碼,包括WebService的Service類定義、服務端代碼、用戶端代碼等。這裡主要介紹兩種WSDL生成Java代碼的方式。
wsdl2java是CXF自帶的工具,在CXF根目錄下的bin目錄下。我們可以在指令行使用這一工具。wsdl2java指令後可以接很多參數,主要有:
參數
這三個參數都可以檢視wsdl2java指令的幫助資訊,可以檢視wsdl2java可以帶哪些參數
-p packageName
指定生成的java類使用的包名稱,如未指定将根據wsdl檔案裡面的targetNameSpace來決定。
-d dir
生成的Java檔案的存放在dir目錄
-compile
編譯生成的Java檔案
-classdir dir
指定編譯生成的檔案存放在dir目錄下
生成WebService的服務端釋出代碼
生成WebService的用戶端通路代碼
-impl
生成Service類的實作類代碼,即上面的HelloWorldImpl
-all
生成所有可以生成的代碼
wsdlurl
Wsdl檔案的通路路徑,可以是本地file,也可以是web上的請求。
如:wsdl2java –all http://localhost:8080/test/services/HelloWorld?wsdl
wsdl2java在生成Service實作類的時候隻會生成基本的代碼結構,至于裡面的操作的具體邏輯還需要我們自己來實作。
cxf-codegen-plugin是cxf針對于maven的一個插件。當我們的項目是基于Maven的項目時,我們可以在pom.xml檔案中引入cxf-codegen-plugin,如:
在上面例子中,當我們執行mvn generate-sources時就會運作wsdl2java這個指令。其配置資訊是通過configuration元素來指定的。通過sourceRoot可以指定生成的Java代碼的存放位置,上面我們指定了生成代碼的存放位置為target目錄下的generated-sources/cxf目錄,該目錄也是在沒有指定sourceRoot時,cxf-codegen-plugin存放生成的Java代碼的預設位置。每個wsdlOption元素對應于一個用來生成代碼的WSDL定義。wsdl元素用于指定wsdl檔案的存放位置。wsdl2java指令的其他參數可以通過wsdlOption元素下的extraargs元素來指定。如:
每一個extraarg元素代表一個參數,如果使用extraarg元素指定wsdl2java參數後面還帶有參數值時,參數值也用一個extraarg來表示。如我們需要指定生成代碼的包名時,我們的cxf-codegen-plugin應該這樣聲明:
使用serviceName元素指定要生成Java代碼的service
通過serviceName元素我們可以指定要針對目前wsdl檔案裡面的哪個service定義來生成檔案。如:
使用wsdlRoot來指定wsdl檔案存放的目錄
我們知道在使用cxf-codegen-plugin的時候一個wsdlOption元素代表要生成的一個wsdl定義,當我們有多個wsdl檔案時就需要定義多個wsdlOption,如:
當我們的wsdl檔案少的時候這樣做還可以,但是當wsdl檔案比較多的時候這樣做就有點麻煩了。這個時候我們可以通過wsdlRoot元素來指定我們的wsdl檔案存放的目錄,cxf-codegen-plugin在掃描的時候隻會掃描wsdlRoot指定的目錄,而不會掃描其子目錄。光指定了wsdlRoot還不能起作用,wsdlRoot必須和includes元素或者excludes元素配合使用。includes元素表示要包含哪些檔案,而excludes元素表示要排除哪些檔案。是以當我們要使用wsdl2java指定對wsdlRoot下的所有檔案生成java代碼時,我們可以這樣做:
或者這樣做:
使用defaultOptions來指定公共的選項
當我們使用wsdlRoot元素來指定wsdl檔案存放目錄時,我們就不能再指定wsdl2java指令執行時的可選參數了。這個時候我們可以通過defaultOptions元素來指定。defaultOptions元素下指定的選項對所有的wsdlOption元素都會産生作用。如: