一、Java中WebService規范
JAVA 中共有三種WebService 規范,分別是JAX-WS、JAX-RS、JAXM&SAAJ(廢棄)。
1.JAX-WS規范
JAX-WS 的全稱為Java API for XML-Based Webservices ,早期的基於SOAP 的JAVA 的Web 服務規范JAX-RPC(Java API For XML-Remote Procedure Call)目前已經被JAX-WS 規范取代。從java5開始支持JAX-WS2.0版本,Jdk1.6.0_13以后的版本支持2.1版本,jdk1.7支持2.2版本。
采用標准SOAP(Simple Object Access Protocol) 協議傳輸,soap屬於w3c標准。Soap協議是基於http的應用層協議,soap協議傳輸是xml數據。
采用wsdl作為描述語言即webservice使用說明書,wsdl屬w3c標准。
xml是webservice的跨平台的基礎,XML主要的優點在於它既與平台無關,又與廠商無關。
XSD,W3C為webservice制定了一套傳輸數據類型,使用xml進行描述,即XSD(XML Schema Datatypes),任何編程語言寫的webservice接口在發送數據時都要轉換成webservice標准的XSD發送。
2.JAX-RS規范
JAX-RS 是JAVA 針對REST(Representation State Transfer)風格制定的一套Web 服務規范,由於推出的較晚,該規范(JSR 311,目前JAX-RS 的版本為1.0)並未隨JDK1.6 一起發行。
支持JAX-RS服務規范的框架有:
CXF——XFire和Celtix的合並(一個由IONA贊助的開源ESB,最初寄存在ObjectWeb上)。
Jersey——Sun公司的JAX-RS參考實現。
RESTEasy——JBoss的JAX-RS項目。
Restlet——也許是最早的REST框架了,它JAX-RS之前就有了。
注:REST 是一種軟件架構模式,只是一種風格,rest服務采用HTTP 做傳輸協議。
二、WebService(jax-ws)三要素
SOAP: 基於HTTP協議,采用XML格式,用來傳遞信息的格式。
WSDL: 用來描述如何訪問具體的服務。
UDDI: 用戶自己可以按UDDI標准搭建UDDI服務器,用來管理,分發,查詢WebService 。其他用戶可以自己注冊發布WebService調用。
1.SOAP(通訊協議)
Simple Object Accrss Protocol,簡單對象訪問協議是在分散或分布式的環境中交換信息的簡單的協議,是一個基於XML的協議,它包括四個部分:
(1)SOAP封裝(envelop),封裝定義了一個描述消息中的內容是什么,是誰發送的,誰應當接受並處理它,以及如何處理它們的框架;
(2)SOAP編碼規則,用於表示應用程序需要使用的數據類型的實例。
(2)SOAP RPC 表示遠程過程調用和應答的協定。
(4)SOAP綁定(binding),使用底層協議交換信息。
(1)請求的協議體
POST /weather HTTP/1.1
Accept: text/xml, multipart/related
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://weather.itheima.com/WeatherInterface/getWeatherByCityNameRequest"
User-Agent: JAX-WS RI 2.2.4-b01
Host: 127.0.0.1:54321
Connection: keep-alive
Content-Length: 235
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getWeatherByCityName xmlns:ns2="http://weather.itheima.com">
<cityName>北京</cityName>
</ns2:getWeatherByCityName>
</S:Body>
</S:Envelope>
(2)響應的協議體
HTTP/1.1 200 OK
Transfer-encoding: chunked
Content-type: text/xml; charset=utf-8
Date: Fri, 09 Oct 2015 07:23:29 GMT
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getWeatherByCityNameResponse xmlns:ns2="http://weather.itheima.com">
<WeatherInfo>今天風很大</WeatherInfo>
</ns2:getWeatherByCityNameResponse>
</S:Body>
</S:Envelope>
(3)發布基於soap1.2協議的服務
在SEI實現類上添加如下注解
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
發布基於soap1.2協議的服務,需要jax-ws包要求2.2.8以上版本。
(4)soap1.2請求的協議體
POST /weather HTTP/1.1
Accept: application/soap+xml, multipart/related
Content-Type: application/soap+xml; charset=utf-8;
action="http://weather.itheima.com/WeatherInterface/getWeatherByCityNameRequest"
User-Agent: JAX-WS RI 2.2.4-b01
Host: 127.0.0.1:54321
Connection: keep-alive
Content-Length: 233
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Body>
<ns2:getWeatherByCityName xmlns:ns2="http://weather.itheima.com">
<cityName>北京</cityName>
</ns2:getWeatherByCityName>
</S:Body>
</S:Envelope>
(5)soap1.2響應的協議體
HTTP/1.1 200 OK
Transfer-encoding: chunked
Content-type: application/soap+xml; charset=utf-8
Date: Fri, 09 Oct 2015 07:54:53 GMT
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Body>
<ns2:getWeatherByCityNameResponse xmlns:ns2="http://weather.itheima.com">
<WeatherInfo>今天風很大</WeatherInfo>
</ns2:getWeatherByCityNameResponse>
</S:Body>
</S:Envelope>
2.WSDL
WSDL(Web Service Description Language),是一個用來描述Web服務(Web Service)和說明如何與Web服務通信的XML語言。因為是基於XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的,這將是一個很大的好處。
(1)wsdl的閱讀方法
是從下往上讀。
每個wsdl有且只有一個Service節點。
1、先找Service節點
2、Service節點中找port節點。每個port對應一個PortType。
3、Port節點對應一binding節點。每個binding節點對應一個PortType
4、PortType中有operation 節點就是服務的方法。
5、operation 中有Input(參數)和output(返回值)
6、Input(參數)和output(返回值)對應message節點
7、Message對應element節點。Element節點對應complexType節點描述了參數及返回值的數據類型。
(2)使用注解規范wsdl
@WebService: 定義服務,在public class上邊。
targetNamespace:指定命名空間。
name:portType的名稱。
portName:port的名稱。
serviceName:服務名稱。
@WebResult:定義返回值。
name:返回結果值的名稱。
@WebParam:定義參數。
name:指定參數的名稱。
@WebMethod
exclude:排除指定的方法。
默認情況下,SEI實現類中所以的public方法會發布成服務方法。
如果不想把public方法發布成服務方法,需要使用@WebMethod注解。把此方法排除。在實現類中至少有一個方法發布為服務方法。
http://127.0.0.1:12345/weather?wsdl
http://127.0.0.1:12345/weather?xsd=1
作用: 通過注解,可以更加形像的描述Web服務。對自動生成的wsdl文檔進行修改,為使用者提供一個更加清晰的wsdl文檔。
當修改了WebService注解之后,會影響客戶端生成的代碼。調用的方法名和參數名也發生了變化。
3.UDDI
UDDI 是一種目錄服務,通過它,企業可注冊並搜索 Web services。企業將自己提供的Web Service注冊在UDDI,也可以使用別的企業在UDDI注冊的web service服務,從而達到資源共享。
UDDI旨在將全球的webservcie資源進行共享,促進全球經濟合作。
但是使用webservice並不是必須使用UDDI,因為用戶通過WSDL知道了web service的地址,可以直接通過WSDL調用webservice。
三、區域查詢系統
1.需求分析
創建區域查詢服務系統,對外發布WebService服務,供客戶端調用,根據parentid查詢區域信息,返回區域信息列表,並支持分頁。
2.服務端
第一步:創建一java工程
第二步:導入mysql的數據庫驅動。
第三步:創建一個dao。根據parentid查詢區域列表。返回區域pojo的list。支持分頁。
第四步:創建一個SEI
第五步:創建SEI實現類。@Webservice注解不要忘。
第六步:發布服務。
AreaDao.java
public class AreaDao{ public List<Area> getAreaList(String parentId,int page,int rows){ //JDBC查詢數據庫 Connection con = null; PreparedStatement ps = null; ResultSet rs = null; List<Area> list = new ArrayList<Area>(); try{ //加載數據庫驅動 Class.forName("com.mysql.jdbc.Driver"); //創建一個連接 con = DriverManager.getConnection("jdbc:mysql://localhost:3306/webservice","root","123456"); //創建Preparement String sql = "SELECT * FROM area WHERE PARENTID=? LIMIT ?,?"; ps = con.prepareStatement(sql); ps.setString(1,parentId); ps.setInt(2,(page - 1) * rows); ps.setInt(3,rows); //執行查詢 rs = ps.executeQuery(); //取查詢結果 while(rs.next()){ Area a = new Area(); a.setAreaCode(rs.getString("AREACODE")); a.setAreaFullName(rs.getString("AREAFULLNAME")); a.setAreaLevel(rs.getString("AREALEVEL")); a.setAreaName(rs.getString("AREANAME")); a.setParentId(rs.getString("PARENTID")); a.setShortName(rs.getString("SHORTNAME")); list.add(a); } return list; }catch(Exception e){ e.printStackTrace(); } finally{ try{ rs.close(); ps.close(); con.close(); }catch(SQLException e){ e.printStackTrace(); } } return list; } }
AreaInterface.java
/* * 區域查詢SEI */ public interface AreaInterface{ List<Area> getAreaList(String parentId,int page,int rows); }
AreaInterfaceImpl.java
/* *SEI實現類 */ @WebService public class AreaInterfaceImpl implements AreaInterface{ @Override public List<Area> getAreaList(String parentId,int page,int rows){ //使用Dao查詢區域列表 AreaDao dao = new AreaDao(); List<Area> list = dao.getAreaList(parentId,page,rows); return list; } }
AreaServer.java
/* * 區域查詢服務發布 */ public class AreaServer{ public static void main(String[] args){ Endpoint.publish("http://127.0.0.1:12345/area",new AreaInterfaceImpl()); } }
3.客戶端
第一步:創建一個java工程
第二步:基於wsdl生成客戶端調用代碼
第三步:創建服務視圖
第四步:獲得PortType對象
第五步:調用服務端方法。
AreaClient.java
/* * 客戶端調用代碼 */ public class AreaClient{ public static void main(String[] args){ //創建服務視圖 AreaInterfaceImplService service = new AreaInterfaceImplService(); //從服務視圖獲取PortType AreaInterfaceImpl port = service.getAreaInterfaceImplPort(); List<Area> list = port.getAreaList("1.1.",1,5); for(Area area : list){ System.out.println(area.getAreaName()); } } }