真正的輕量級WebService框架——使用JAX-WS(JWS)發布WebService
WebService歷來都很受重視,特別是Java陣營,WebService框架和技術層出不窮。知名的XFile(新的如CXF)、Axis1、Axis2等。
而Sun公司也不甘落后,從早期的JAX-RPC到現在成熟的、支持RPC調用與消息傳遞的JAX-WS都經過了市場的考驗,十分成熟,而且使用JAX-WS開發WebService的收益是很大的,它是輕量級的。
我們使用JAX-WS開發WebService只需要很簡單的幾個步驟:寫接口和實現=>發布=>生成客戶端(測試或使用)。
而在開發階段我們也不需要導入外部jar包,因為這些api都是現成的。首先是接口的編寫(接口中只需要把類注明為@WebService,把要暴露給客戶端的方法注明為@WebMethod即可,其余如@WebResult、@WebParam等都不是必要的,而客戶端和服務端的通信用RPC和Message-Oriented兩種,區別和配置以后再說):
1 package service;
2
3 import java.util.Date;
4
5 import javax.jws.WebMethod;
6 import javax.jws.WebParam;
7 import javax.jws.WebResult;
8 import javax.jws.WebService;
9 import javax.jws.soap.SOAPBinding;
10
11 /**
12 * 作為測試的WebService接口
13 *
14 * @author Johness
15 *
16 */
17 @WebService
18 @SOAPBinding(style = SOAPBinding.Style.RPC)
19 public interface SayHiService {
20
21 /**
22 * 執行測試的WebService方法
23 */
24 @WebMethod
25 void SayHiDefault();
26
27 /**
28 * 執行測試的WebService方法(有參)
29 *
30 * @param name
31 */
32 @WebMethod
33 void SayHi(@WebParam(name = "name") String name);
34
35 /**
36 * 執行測試的WebService方法(用於時間校驗)
37 *
38 * @param clentTime 客戶端時間
39 * @return 0表示時間校驗失敗 1表示校驗成功
40 */
41 @WebMethod
42 @WebResult(name = "valid")
43 int CheckTime(@WebParam(name = "clientTime") Date clientTime);
44 }
然后是實現類(注解@WebService及其endpointInterface屬性是必要的):
1 package service.imp;
2
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5
6 import javax.jws.WebService;
7 import javax.jws.soap.SOAPBinding;
8
9 import service.SayHiService;
10
11 /**
12 * 作為測試的WebService實現類
13 *
14 * @author Johness
15 *
16 */
17 @WebService(endpointInterface = "service.SayHiService")
18 @SOAPBinding(style = SOAPBinding.Style.RPC)
19 public class SayHiServiceImp implements SayHiService {
20
21 @Override
22 public void SayHiDefault() {
23 System.out.println("Hi, Johness!");
24 }
25
26 @Override
27 public void SayHi(String name) {
28 System.out.println("Hi, " + name + "!");
29 }
30
31 @Override
32 public int CheckTime(Date clientTime) {
33 // 精確到秒
34 String dateServer = new java.sql.Date(System.currentTimeMillis())
35 .toString()
36 + " "
37 + new java.sql.Time(System.currentTimeMillis());
38 String dateClient = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
39 .format(clientTime);
40 return dateServer.equals(dateClient) ? 1 : 0;
41 }
42
43 }
然后是發布(一般有兩種方式):
方式一(此方式只能作為調試,有以下bug:
jdk1.6u17?以下編譯器不支持以Endpoint.publish方式發布document方式的soap,必須在service接口和實現類添加“@SOAPBinding(style = SOAPBinding.Style.RPC)”注解;
訪問受限,似乎只能本機訪問(應該會綁定到publish的URL上,如下使用localhost的話就只能本機訪問)……):
1 package mian;
2
3 import javax.xml.ws.Endpoint;
4
5 import service.imp.SayHiServiceImp;
6
7 public class Main {
8
9 /**
10 * 發布WebService
11 * 簡單
12 */
13 public static void main(String[] args) {
14 Endpoint.publish("http://localhost:8080/testjws/service/sayHi", new SayHiServiceImp());
15 }
16
17 }
方式二(基於web服務器Servlet方式):
以Tomcat為例,首先編寫sun-jaxws.xml文件並放到WEB-INF下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" 3 version="2.0"> 4 <endpoint name="SayHiService" 5 implementation="service.imp.SayHiServiceImpl" 6 url-pattern="/service/sayHi" /> 7 </endpoints>
然后改動web.xml,添加listener和servlet(url-pattern要相同哦):
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> 3 4 <listener> 5 <listener-class> 6 com.sun.xml.ws.transport.http.servlet.WSServletContextListener 7 </listener-class> 8 </listener> 9 <servlet> 10 <servlet-name>SayHiService</servlet-name> 11 <servlet-class> 12 com.sun.xml.ws.transport.http.servlet.WSServlet 13 </servlet-class> 14 </servlet> 15 <servlet-mapping> 16 <servlet-name>SayHiService</servlet-name> 17 <url-pattern>/service/sayHi</url-pattern> 18 </servlet-mapping> 19 20 <welcome-file-list> 21 <welcome-file>index.html</welcome-file> 22 <welcome-file>index.htm</welcome-file> 23 <welcome-file>index.jsp</welcome-file> 24 </welcome-file-list> 25 </web-app>
最后部署到Tomcat里,值得一提的是您可能需要添加以下jar包(因為Tomcat沒有):

啟動Tomcat。
服務端工作就完成了,注意兩個事情。
注意:項目需要使用UTF-8編碼(至少sun-jaxws.xml必須是UTF-8格式的);
對於MyEclipse的內置Tomcat,可能會出現不需要手動添加上述jar包,但獨立部署時應該添加,因為它們使用的class-path不一樣;
多個不同路徑的接口也要使用同一個WSServlet;
最好加上@SOAPBinding(style = SOAPBinding.Style.RPC)注解。
部署好了之后打開瀏覽器輸入網址:http://localhost:8080/testjws/service/sayHi?wsdl。可以看到東西就證明發布成功了。
附上項目樹狀圖:

最后是客戶端使用,由於WebService是平台和語言無關的基於xml的,所以我們完全可以使用不同語言來編寫或生成客戶端。
一般有三種方式來使用(對於Java語言而言):
一,使用jdk自帶工具wsimport生成客戶端:

jdk自帶的wsimport工具生成,上圖我是把客戶端文件生成到了桌面src文件中(-d),並保留了源文件(-keep),指定了包名(-p)。
然后我們就可以使用生成的文件來調用服務器暴露的方法了:

值得一提的是你生成使用的jdk和你客戶端的jre需要配套!
從上面的目錄結構我們可以發現:服務端的每個webmethod都被單獨解析成為了一個類(如果使用了實體,實體也會被解析到客戶端,並且是源碼,所以建議使用實體時慎重)。

(上面的圖是舊圖,只是為了表示一下jaxws是為每個webmethod生成類的情況)
而我們的service則被生成了一個代理類來調用服務,接下來我們看看使用情況:
1 package test;
2
3 import java.util.Date;
4 import java.util.GregorianCalendar;
5
6 import javax.xml.datatype.DatatypeConfigurationException;
7 import javax.xml.datatype.DatatypeFactory;
8 import javax.xml.datatype.XMLGregorianCalendar;
9
10 import testjws.client.SayHiService;
11 import testjws.client.SayHiServiceImpService;
12
13 public class Main {
14
15 public static void main(String[] args) throws DatatypeConfigurationException {
16 // 獲取service
17 SayHiService service = new SayHiServiceImpService().getSayHiServiceImpPort();
18
19 // sayhi
20 service.sayHiDefault();
21 service.sayHi("Ahe");
22
23 // checktime
24 // 這里主要說一下時間日期的xml傳遞,方法還略顯復雜
25 GregorianCalendar calender = new GregorianCalendar();
26 calender.setTime(new Date(System.currentTimeMillis()));
27 XMLGregorianCalendar xmldate = DatatypeFactory.newInstance().newXMLGregorianCalendar(calender);
28 System.out.println(service.checkTime(xmldate));
29
30 }
31
32 }
看看服務器的輸出,我們是否調用成功:

成功了!
對於校驗時間的方法客戶端也收到反饋了:

二,使用諸如MyEclipse(Eclipse for Jave EE也可以)創建一個Web Service Client的項目

然后填入wsdl地址即可,后續步驟我就不貼出了。
三,自己寫代碼-_-,其實這個方法不得不說是最好的。
(最后編輯時間2014-03-08 00:23:18)



