前兩部分描述獲得和設置NetBeans IDE以及JAX-WS代碼。第三部分包含了關于創建一個包含web service的web工程以及要用到的示例代碼的信息。最后一部分描述了利用這個工程你自己的web service的技巧,也是從WSDL開始創建一個服務的指導。注意JAX-WS2.0需要J2SE5.0。
這篇指南包含以下話題:
1、 設置環境
2、 使用JAX-WS2.0庫創建一個新的Web應用
3、 建立一個服務
l 從 java創建一個服務
4、 測試和調試
l 在Web Services Registry中測試服務
l 創建一個單元測試
l 調試客戶端
5、 技巧
l 從WSDL創建服務
l 編寫你自己的JAX-WS2.0 Web Services
1、 設置環境
在開始編寫代碼前,你必須保證已經擁有所有的必須軟件。
安裝軟件
開始之前,你需要在機器上安裝以下軟件:
l NetBeans IDE 5.0(下載)
l Java SDK 5.0(下載)
對于本文中的例子,只需要兩個步驟對NetBeans進行設置。第一步(強烈建議)刪除或者重命名包含在Tomcat(內置于NetBeans5.0中)中的JAXP jar文件。這些文件已經包含在了JDK5.0中了(JAX-WS必須)。在NetBeans中這些文件路徑是<netbeans_home>/enterPRise2/jakarta-tomcat-5.5.9/common/endorsed。你可以修改.jar擴展名以至于不能加載或者完全刪除。盡管雙份的jar包不應該造成沖突,仍然強烈建議從Tomcat中刪除它們。
從http://jax-ws.dev.java.net工程得到JAX-WS2.0二進制版本。從Downloads/Nightly頁面下載JAX-WS2.0二進制安裝文件,運行“java -jar JAXWS_SI_rrrrmmdd.jar”進行安裝。
警告:不要使用最新的官方JAX-WS RI 2.0 EA2版本,因為它和例子要用到的wsimport和wsgen任務不兼容。下一個版本(JAX-WS RI 2.0 EA3)應該可以工作。
為了使Tomcat服務器能夠訪問JAX-WS2.0庫,將所有的jar文件從<jaxws-ri>/lib Directory復制到<netbeans_home>/enterprise2/jakarta-tomcat-5.5.9/common/lib文件夾下。
2、 使用JAX-WS2.0庫創建一個新的Web應用
選擇File—〉New Project(Ctrl-Shift-N)。在Categories下選擇Web,然后選擇Web application。輸入“JAX-WS20Project”作為Project Name,指定Project Location目錄,確保在Server下拉框中Bundled Tomcat (5.5.9)服務器被選中。
點擊Next,然后點擊Finish。
點擊菜單欄中的Tools,然后選擇Library Manager。點擊New Library按鈕,輸入“JAX-WS20”,點擊OK。由于在New Library中ClassPath打開著,點擊Add JAR/Folder,從<jaxws-ri>/lib文件夾下選擇所有的jar文件。
JAX-WS20 jar文件列表:
在Projects試圖中打開JAX-WS20工程,在Libraries節點打開Add Library。選擇JAX-WS20庫,點擊Add Library按鈕。
正常情況下,所有的jar文件在編譯過程中都會被放置在web工程的war文件中(WEB-INF/lib文件夾下)。因為我們已經把這些jar文件復制到Tomcat服務器中了,所以就不需要再作為可發布的war包的一部分了。
為了減小可發布war包的大小,我們將JAX-WS20庫從war包中排除,通過去掉對Libraries節點→Properties對話框中Package復選框的選擇。
不選擇Package復選框:
點擊OK。
JAX-WS20Project就完成了創建一個JAX-WS20服務的準備工作了。
3、 建立一個服務
從Java創建一個服務
增加服務類。在Projects視圖中右鍵點擊JAX-WS20Project節點,選擇New和Java Class。輸入“ServiceImpl”到Class Name欄中,“my.sample.server”到Package欄中,點擊Finish。實現一個web service hello(java.lang.String)操作,利用JAX-WS2.0注釋指定portType名稱、服務名稱和目標命名空間:
package my.sample.server;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.WebMethod;
/**
* A simple java class that will become a web service.
*/
@WebService(name="Hello", serviceName="HelloService", targetNamespace="http://example.com")
public class ServiceImpl {
@WebMethod
public String hello(@WebParam(name="name") String s) {
System.out.println("Service received: " + s);
return "Hello "+s;
}
}
編譯(F9)ServiceImpl類。
警告:為了使注釋能夠支持,JAX-WS20Project中的Source Level應該設置為1.5(在JAX-WS20Project節點調用Properties動作):
修改在Web Pages/WEB-INF文件夾下的發布描述符(web.xml),指定JAX-WS servlet類和ServletContextListener:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>my_service</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my_service</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
</web-app>
在Web Pages/WEB-INF目錄下創建sun-jaxws.xml文件(在WEB-INF節點下創建新的XML文檔,在File Name欄中輸入sun-jaxws)。sun-jaxws.xml文件被JAX-WS運行時用到,并且指定了服務終端實現類和相對URL:
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
<endpoint
name='Hello'
implementation='my.sample.server.ServiceImpl'
url-pattern='/hello'/>
</endpoints>
最后一不是添加下面的xml片段到JAX-WS20Project/build.xml文件。為了編輯工程的build.xml文件,你可以使用菜單欄中的File→Open File或者打開Files選項卡而不是Projects,打開JAX-WS20Project節點,雙擊build.xml。這個target在編譯服務類后將要被NetBeans調用,卻是在創建war文件前。wsgen ant任務將會創建服務需要的JAXB和JAX-WS文件。關于wsgen工具的更多信息參見JAX-WS文檔。
<!-- Overrides build-impl.xml target to create the server
artifacts that will be included in the war file. -->
<target name="-pre-dist">
<taskdef name="wsgen" classname="com.sun.tools.ws.ant.WsGen">
<classpath path="${javac.classpath}"/>
</taskdef>
<wsgen
debug="true"
keep="true"
destdir="build/web/WEB-INF/classes"
resourcedestdir="build/web/WEB-INF/classes"
sei="my.sample.server.ServiceImpl">
<classpath>
<pathelement path="${javac.classpath}"/>
<pathelement location="${java.home}/../lib/tools.jar"/>
<pathelement location="build/web/WEB-INF/classes"/>
</classpath>
</wsgen>
</target>
為了創建和啟動服務,從菜單欄中選擇Run和Run Main Project,或者使用快捷鍵F6。作為可選的(但是很有幫助)步驟,右鍵點擊工程名稱,選擇Properties。選擇“Run”節點,在右面的“Relative URL”欄中輸入“/hello”。通過設置這個值,當你運行這個工程時,NetBeans會在瀏覽器中產生“http://localhost:8084/JAX-WS20Project/hello”地址。這就允許你在發布服務時進行確認,并且如果愿意你也可以查看wsdl文件。你可以修改服務類,只需要點擊F6重新編譯和發布服務,就可以看到在wsdl中發生了什么變化。
正常情況下,hello服務信息應該在瀏覽器窗口中出現。這就標志著服務發布成功。
端口名稱
狀態
信息
Hello
活動(ACTIVE)
地址:http://localhost:8084/JAX-WS20Project/hello
WSDL:http://localhost:8084/JAX-WS20Project/hello?wsdl
端口 QName:{http://example.com}HelloPort
實現類:my.sample.server.ServiceImpl
如果與上不同,在Output Window中查看Bundlet Tomcat(5.5.9)日志文件查看問題的源頭。
4、 測試和調試
在Web Service Registry中測試服務
測試服務最簡單的方法就是使用包含在NetBeans5.0中的Web Services Resgistry。在Runtime選項卡中右鍵點擊Web Services,選擇Add WebService。在“URL”欄中,輸入web service WSDL文件的地址,在這里是“http://localhost:8084/JAX-WS20Project/hello?wsdl”,點擊Get Web Service Description。這將會產生web service的信息。為了測試hello()操作,點擊操作名稱旁邊的Test Operation。然后輸入一個發送值,觀察返回了什么(在這里,修改服務實現類為返回字符串增加一些文本也許是有用的)。點擊Close退出測試。
在Web Service Registry中測試服務:
如果愿意你可以通過點擊Add按鈕添加服務到注冊器中:

那么,你可以在任何時候打開注冊器,雙擊hello節點測試hello操作。
創建一個單元測試
對于一個包含web應用的完整應用程序,你可以正常的為這個應用創建一個新的工程。為了簡單地為測試我們的新web service創建一個客戶端,可以用NetBeans的單元測試功能。
由創建一個新的JUnit測試用例開始。在Projects選項卡中右鍵點擊Test Packages節點,選擇New→File/Folder→JUnit→Empty Test。在Class Name中輸入“Service Test”,Package中輸入“my.sample.test”,點擊Finish。按照下面的方法實現testService()方法:
package my.sample.test;
import junit.framework.*;
import my.sample.test.generated.Hello;
import my.sample.test.generated.HelloService;
public class ServiceTest extends TestCase {
public ServiceTest(String testName) {
super(testName);
}
protected void setUp() throws Exception {
}
protected void tearDown() throws Exception {
}
// TODO add test methods here. The name must begin with 'test'. For example:
public void testService() {
HelloService service = new HelloService();
Hello proxy = service.getHelloPort();
String request = "Apples and Pears";
String response = proxy.hello(request);
System.out.println(response);
}
}
在運行前,添加這段xml代碼到build.xml文件中。NetBeans會在編譯和運行測試客戶端前調用這個target。當這個target運行時,它確保服務被編譯和發布(若需要就重新編譯)。關于wsimport工具的更多信息參見JAX-WS文檔。
<!-- Overrides build-impl.xml target to start server and
generate client artifacts before building test. -->
<target name="-pre-compile-test">
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
<classpath path="${javac.classpath}"/>
</taskdef>
<!-- Use "debug" or "run" here. -->
<antcall target="run"/>
<echo>running wsimport</echo>
<wsimport
debug="true"
keep="true"
destdir="test"
package="my.sample.test.generated"
wsdl="http://localhost:8084/JAX-WS20Project/hello?wsdl"/>
</target>
為了運行測試,從菜單欄中選擇Run,然后選擇Test“JAX-WS20Project”。或者使用快捷鍵Alt-F6。在輸出窗口,你應該可以看到從服務返回的“Hello Apples and Pears”:


調試客戶端
單步執行應用程序中的代碼(和JAX-WS代碼)是比較簡單的。由在ServiceImpl.java(15行)System.out.println("Service received: " + s);上放置斷點開始。最快的方式就是打開文件,在適當的行上點擊編輯器的左邊框。或者將鼠標放在這一個行上,使用Ctrl-F8(關于使用調試器的完整信息參見NetBeans用戶向導)。
當前你可以通過Run→Debug Main Project在調試模式下啟動服務器,然而也可以一步運行客戶端代碼,在工程的build.xml文件中,修改“-pre-compile-test”target的“antcall”行,由<antcall target="run"/>到<antcall target="debug"/>。
<!-- Use "debug" or "run" here. -->
<antcall target="debug"/>
現在再次運行客戶端進行測試(例如,按下Alt-F6)。在編譯之前,NetBeans會以調試模式啟動Tomcat服務器。當客戶端啟動后,調試器應該停止在ServiceImpl適當的行上,你可以單步執行服務器代碼。注意:如果你在JAX-WS工作空間中在某一行上添加了斷點,Alt-F6不會執行直到你將焦點移回到SampleApp工程中某個文件上,可以通過在編輯器中產生一個文件,點擊Projects選項卡中的工程,等等完成。如果你對應用作了修改,當再一次運行時所有的東西都回根據需要重新編譯。記住要停止調試,可以選擇菜單欄中的Run,然后點擊Finish Debugger Session,或者點擊工具欄上的停止按鈕。
為了在客戶端調試代碼,由在ServiceTest.java的test1()方法中放置斷點開始。然后在Project視圖中右鍵點擊這個文件,選擇Debug File(在編輯器中將這個作為活動文件,然后使用Ctrl-Shift-F5)。這會在調試器中啟動客戶端以及服務。
5、 技巧
從WSDL創建服務
對于這個例子你可以使用JAX-WS20“<jaxws-ri>/samples/fromwsdl”文件夾下的AddNumbers.wsdl。首先復制這個文件到“JAX-WS20Project/web/WEB-INF/wsdl”文件夾下。
然后添加新的<servlet-mapping>到web.xml文件中:
<servlet-mapping>
<servlet-name>my_service</servlet-name>
<url-pattern>/addNumbers</url-pattern>
</servlet-mapping>
(注意<servlet-name>的值和Hello服務中的一樣)。
添加新的<endpoint>到sun-jaxws.xml文件中:
<endpoint name="AddNumbers"
implementation="my.sample.server.AddNumbersImpl"
wsdl="WEB-INF/wsdl/AddNumbers.wsdl"
service='{http://duke.org}AddNumbersservice'
port='{http://duke.org}AddNumbersPort'
url-pattern="/addNumbers"/>
你還需要創建包含wsimport任務的“-pre-compile”target,它會在執行compile target之前被運行。我們的target會調用<wsimport>任務產生WSDL文件(和引用的schema文件)中所有必須的java artifact。
<!-- Overrides -pre-compile target in build.xml to create jax-ws
java artifacts that will created and compiled to WEB-INF/classes directory. -->
<target name="-pre-compile">
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
<classpath path="${javac.classpath}"/>
</taskdef>
<echo>running wsimport</echo>
<!-- wsdl attribute is absolute path, so ${basedir} is included -->
<wsimport
debug="true"
keep="true"
destdir="build/web/WEB-INF/classes"
package="wsimport.generated.addnumbers"
wsdl="${basedir}/web/WEB-INF/wsdl/AddNumbers.wsdl"/>
</target>
注意:java artifact會生成到“WEB-INF/classes”文件下的“wsimport.generated.addnumbers”包中。
最后,你應該創建一個服務實現類(可以創建在同一個包中而非ServiceImpl):
package my.sample.server;
import javax.jws.WebService;
import wsimport.generated.addnumbers.*;
/**
* A simple java class to implement a web service. Until the
* endpoint interface has been generated, the class declaration
* below will show up as a compiler error.
*/
@WebService(endpointInterface="wsimport.generated.addnumbers.AddNumbersPortType")
public class AddNumbersImpl implements AddNumbersPortType {
public void oneWayInt(int arg0) {
System.out.println("received value "+arg0);
}
public int addNumbers(int arg0,int arg1) throws AddNumbersFault_Exception {
if (arg0<0 arg1<0) throw new AddNumbersFault_Exception("negative number",new AddNumbersFault());
return arg0+arg1;
}
}
(實現類必須實現由wsimport任務生成的服務終端接口)
現在可以進行編譯和發布這個工程了。
如果你運行工程,接下來的頁面在瀏覽器中出現:
端口名稱
Status(狀態)
Information(信息)
Hello
ACTIVE
地址:http://localhost:8084/JAX-WS20Project/hello
WSDL:http://localhost:8084/JAX-WS20Project/hello?wsdl
端口QName:{http://example.com}HelloPort
實現類:my.sample.server.ServiceImpl
AddNumbers
ACTIVE
地址:http://localhost:8084/JAX-WS20Project/addNumbers
WSDL:http://localhost:8084/JAX-WS20Project/addNumbers?wsdl
端口QName:{http://duke.com}AddNumbersPort
實現類:my.sample.server.AddNumbersImpl
你也可以使用和Hello服務同樣的方式測試和調試AddNumbers服務。這是從NetBeans Web Service Registry的一個屏幕截圖:
編寫你自己的JAX-WS20 Web Services
為了編寫你自己的服務,你可以添加另外一個服務實現類到這個工程中或者新建一個工程。你還需要添加新的<servlet-mapping>元素到web.xml中,新的<endpoint>元素到sun-jaxws.xml中。另外,還要在build.xml文件中增加新的<wsgen>任務(用來從java類生成web service)或者新的<wsimport>任務(用來從WSDL生成web service)。
更多的幫助請參考JAX-WS Project文檔。
(出處:http://www.survivalescaperooms.com)
新聞熱點
疑難解答