Like Share Discussion Bookmark Smile

J.J. Huang   2019-04-17   Spring Boot   瀏覽次數:次   DMCA.com Protection Status

SpringBoot - 第二十九章 | WebService簡介及應用 (Server)

在專案開發過程中,常常需要與其他系統做介接,而這些系統往往都有一點年紀了,雖然上了年紀,但是相對他們的穩定度基本上經的起考驗,所以不能說技術老舊就是不好;而在考量到不同的程式語言、架構、環境下,這些系統之間的溝通,我們就會選擇一個比較普羅大眾的一些協議,例如使用SOAP⋯下面將會介紹Spring-Web-Services。

WebService介紹

以下截取於:維基百科

Web服務是一種服務導向架構的技術,透過標準的Web協議提供服務,目的是保證不同平台的應用服務可以互操作。

根據W3C的定義,Web服務(Web service)應當是一個軟體系統,用以支持網路間不同機器的互動操作。網路服務通常是許多應用程式接口(API)所組成的,它們透過網路,例如國際網際網路(Internet)的遠程伺服機端,執行客戶所提交服務的請求。

儘管W3C的定義涵蓋諸多相異且無法介分的系統,不過通常我們指有關於主從式架構(Client-server)之間根據SOAP協議進行傳遞XML格式消息。無論定義還是實現,WEB服務過程中會由伺服機提供一個機器可讀的描述(通常基於WSDL)以辨識伺服機所提供的WEB服務。另外,雖然WSDL不是SOAP服務端點的必要條件,但目前基於Java的主流WEB服務開發框架往往需要WSDL實現客戶端的原始碼生成。一些工業標準化組織,比如WS-I,就在WEB服務定義中強制包含SOAPWSDL

簡單的說,WebService就是一種跨編程語言和跨操作系統平台的遠程調用技術。
注意:Web Service、Web API、WCF容易讓人搞混(作者以前就常搞錯),這邊有推薦個文章可以參考 WCF、Web Service、Web API三者差異

核心定義

考慮到並沒某個獨立文件包含一切相關內容,可採用模組化的方式給出對WEB服務的描述,但不能給出一個「絕對全面和準確」的定義。受外部環境和實現技術影響,各方給出的核心定義可能稍有出入,但通常包括:

定義 說明
SOAP 一個基於XML的可擴展消息信封格式,需同時綁定一個網路傳輸協議。這個協議通常是HTTP或HTTPS,但也可能是SMTP或XMPP。
WSDL 一個XML格式文件,用以描述服務埠訪問方式和使用協議的細節。通常用來輔助生成伺服機和客戶端代碼及配置訊息。
UDDI 一個用來發布和搜索WEB服務的協議,應用程式可藉由此協議在設計或運行時找到目標WEB服務。

這些標準由這些組織制訂:W3C負責XML、SOAP及WSDL;OASIS負責UDDI。

協議集

為提高WEB服務間的互操作能力,WS-I還特別發布了WEB服務協議集(Profile)。協議集包含了一系列特定版本的核心定義(諸如SOAPWSDL),以及對其使用上的限制與約束。WS-I還發布了用於部署協議集兼容WEB服務的測試工具及相關用例。

WS-系列追加定義

為擴展WEB服務能力,一些新的標準已經或正在被開發。這些標準通常被冠以WS字頭(Web Service的簡稱),以下是一個WS系列追加標準的不完全列表:

定義 說明
WS安全(WS-Security) 定義了如何在SOAP中使用XML加密或XML簽名來保護消息傳遞。可作為HTTPS保護的一種替代或擴充。
WS信賴性(WS-Reliability) 一個來自OASIS的標準協議,用來提供可信賴的WEB服務間消息傳遞。
WS可信賴消息(WS-ReliableMessaging) 同樣是一個提供信賴消息的協議,由Microsoft, BEA 和IBM發布。目前OASIS正對其實施標準化工作。
WS尋址(WS-Addressing) 定義了在SOAP消息內描述發送/接收方地址的方式。
WS事務(WS-Transaction) 定義事務處理方式。

一直以來,W3C負責制定了不少WS追加定義,但近來此舉開始受到懷疑。一些人呼籲W3C作為網路和語義網構建者應當把精力放在核心網路本身,而不是為WEB服務改換版本。特別是2007年2月的企業級WEB服務論壇上,對W3C不再充當WEB服務定義者的訴求開始表面化。 此外,OASIS對WEB服務擴展實施了許多標準化工作。包括WEB服務資源框架以及WSDM

W3C (World Wide Web Consortium):全球資訊網協會,又稱W3C理事會,是全球資訊網的主要國際標準組織。為半自治非政府組織。

WEB服務的方式

WEB服務實際上是一組工具,並有多種不同的方法呼叫之。三種最普遍的手段是:遠端程序呼叫RPC),服務導向架構SOA)以及表述性狀態轉移REST)。

服務 說明
遠端程序呼叫(RPC) WEB服務提供一個分布式函數或方法接口供用戶呼叫,這是一種比較傳統的方式。
通常,在WSDL中對RPC接口進行定義(類似於早期的XML-RPC)。
儘管最初的WEB服務廣泛採用RPC方式部署,但針對其過於緊密之耦合性的批評聲也隨之不斷。
這是因為RPC式WEB服務實質上是利用一個簡單的映射,以把用戶請求直接轉化成為一個特定語言編寫的函數或方法。
如今,多數服務提供商認定此種方式在未來將難有作為,在他們的推動下,WS-I基本協議集(WS-I Basic Profile)已不再支持遠端程序呼叫。
服務導向架構(SOA) 現在,業界比較關注的是遵從服務導向架構(Service-oriented architecture,SOA)概念來構築WEB服務。
在服務導向架構中,通訊由消息驅動,而不再是某個動作(方法呼叫)。
這種WEB服務也被稱作面向消息的服務。
SOA式WEB服務得到了大部分主要軟體供應商以及業界專家的支持和肯定。
作為與RPC方式的最大差別,SOA方式更加關注如何去連接服務而不是去特定某個實現的細節。WSDL定義了聯絡服務的必要內容。
表述性狀態轉移(REST) 表述性狀態轉移式(Representational state transfer,REST)WEB服務類似於HTTP或其他類似協議,
它們把接口限定在一組廣為人知的標準動作中(比如HTTP的GET、PUT、DELETE)以供呼叫。
此類WEB服務關注與那些穩定的資源的互動,而不是消息或動作。
此種服務可以透過WSDL來描述SOAP消息內容,透過HTTP限定動作接口;或者完全在SOAP中對動作進行抽象。

Spring-Web-Services 介紹

Spring Web Services(Spring-WS)是Spring社區的一個產品,專注於建立文件驅動的Web服務。 Spring Web Services旨在促進契約優先的SOAP服務開發,允許使用多種方式之一來操作XML有效負載來建立靈活的Web服務。 該產品基於Spring本身,這意味著你可以使用Spring概念(如依賴注入)作為Web服務的一個組成部分。

人們使用Spring-WS有很多原因,但大多數人在找到替代Web服務最佳實踐後缺乏的替代SOAP堆棧時會被它吸引。 Spring-WS使最佳實踐變得簡單。 這包括諸如WS-I基本概要,契約優先發展以及合同與實施之間鬆散耦合等實踐。 Spring Web服務的其他主要功能包括:

  • 強大的映射
    你可以將傳入的XML請求分發到任何對象,具體取決於消息有效內容,SOAP Action標頭或XPath表達式。

  • XML API支持
    傳入的XML消息不僅可以使用標準的JAXP API(如DOM,SAX和StAX)處理,還可以處理JDOM,dom4j,XOM甚至編組技術。

  • 靈活的XML編組
    Spring Web Services構建於Spring Framework中的Object / XML Mapping模組,該模組支持JAXB 1和2,Castor,XMLBeans,JiBX和XStream。

  • 重用你的Spring專業知識
    Spring-WS使用Spring應用程序上下文進行所有配置,這應該有助於Spring開發人員快速,快速地獲得最佳速度。此外,Spring-WS的體系結構類似於Spring-MVC的體系結構。

  • 支持WS-Security
    WS-Security允​​許你簽署SOAP消息,加密和解密它們,或對它們進行身份驗證。

  • Spring Security集成
    Spring Web Services的WS-Security實現提供了與Spring Security的集成。這意味著你也可以將現有的Spring Security配置用於SOAP服務。

  • Apache許可證
    你可以放心地在項目中使用Spring-WS。

Spring-WS由許多模組組成

  • XML模組(spring-xml.jar)
    包含用於Spring Web Services的各種XML支持類。該模組主要用於Spring-WS框架本身,而不是Web服務開發人員。

  • Core模組(spring-ws-core.jar)
    是Spring Web服務功能的核心部分。它提供了中央和接口,伺服器端 框架,強大的消息調度,以及用於實現Web服務端點的各種支持類; 和客戶端。 WebServiceMessage SoapMessage WebServiceTemplate

  • 支持模組(spring-ws-support.jar)
    包含其他傳輸(JMS,電子郵件和其他)。

  • 安全包(spring-ws-security.jar)
    提供了WS-Security實現與核心Web服務封裝中集成。它允許你添加主要令牌,簽名,解密和加密SOAP消息。此外,它還允許你利用現有的Spring Security安全實施進行身份驗證和授權。


Spring-WS建立Web服務

Spring-WS的伺服器端支持是圍繞一個MessageDispatcher調度傳入消息到端點的,具有可配置的端點映射,響應生成和端點攔截。端點通常使用註釋進行@Endpoint註釋,並具有一個或多個處理方法。這些方法通過檢查消息的一部分(通常是有效負載)來處理傳入的XML請求消息,並建立某種響應。你通常使用另一個註釋來註釋該方法@PayloadRoot,以指示它可以處理的消息類型。

加入pom的依賴

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<!-- 生產wsdl文件 -->
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>

建立author.xsd (簡單的獲取作者訊息範例)

路徑:/src/main/resources/author.xsd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.jj.com/webservice"
targetNamespace="http://www.jj.com/webservice" elementFormDefault="qualified">

<!-- 定義請求實體 -->
<xs:element name="authorRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<!-- 定義回應實體 -->
<xs:element name="authorResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="author" type="tns:author"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<!-- 定義請求實體 -->
<xs:element name="authorListRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="nonce" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>

<!-- 定義回應實體 -->
<xs:element name="authorListResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="author" type="tns:author" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>

<!-- 定義作者 訊息 -->
<xs:complexType name="author">
<xs:sequence>
<xs:element name="name" type="xs:string" />
<!-- 愛好列表形式nillable = true可為空,maxOccurs = unbouned無限 -->
<xs:element name="hobby" type="xs:string" nillable="true" maxOccurs="unbounded" />
<!-- 性别 枚舉類型 限定 -->
<xs:element name="sex" type="tns:sex" />
<!-- 生日 -->
<xs:element name="birthday" type="xs:string" />
<!-- 描述 -->
<xs:element name="description" type="xs:string" />
</xs:sequence>
</xs:complexType>

<!-- 枚舉類型 性别:男 女 -->
<xs:simpleType name="sex">
<xs:restriction base="xs:string">
<xs:enumeration value="male"/>
<xs:enumeration value="female"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

注意:
1.請求和返回的名字是有要求的,兩個名字前面要一樣,後綴分別是固定的配置,默認為Request和Response; 當然可以通過requestSuffix和responseSuffix屬性來修改默認值的。
2.關於XSD的規則,可以參考 XSD規則

Maven 產生 實體對象

在pom.xml裡面<build><plugins>中加入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
<!-- package路徑 -->
<packageName>com.jj.learning.springboot.chapter29.webservice</packageName>
</configuration>
</plugin>

運行 Maven install

project -> 右鍵 -> Run as -> Macen install,產生如下圖

建立 WsConst

建立 AuthorEndpoint (類似Controller的請求入口)

以上範例,大部分訊息都寫死。但在實際開發中,會加入各自的業務邏輯,引入相應的service類。
注意:
1.方法聲明上的@PayloadRoot標註中的namespacelocalPart分別就是wsdl中的targetNamespacesoap方法名稱。
2.@ResponsePayload@RequestPayload這兩個標註的用法,以及它們對應的資料類型就是此前通過ma​​ven插件對wsdl定義生成的java類。

關於請求參數,是否需要加@RequestPayload說明:

一般上,都是使用JAXB2對象了,也就是先前生成的實體對象。然而其他的對象參數,可以獲取到不同的參數值的。

關於回應參數,是否需要加@ResponsePayload說明:

建立 WebServiceConfig

測試

啟動應用後,輸入http://localhost:8080/ws/author.wsdl ,就可以看到wsdl的內容。

Postman 測試

http://localhost:8080/ws/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0"?>

<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:gs="http://www.jj.com/webservice">

<soap:Header>
</soap:Header>

<soap:Body>
<gs:authorRequest>
<gs:name>J.J.Huang</gs:name>
</gs:authorRequest>
</soap:Body>

</soap:Envelope>

說明已經成功了,這邊大量複製了參考文章來做我的筆記,因為我對這個沒有非常的熟悉,希望透過這樣的一步一步,閱讀、實作,讓自己更精進;在下一章節會繼續接著講解Client端的部分。

註:以上參考了
Baidu百科Web Service 文章。
維基百科Web服務 文章。
Spring Web Services Reference Documentation
oKongSpringBoot | 第三十三章:Spring web Servcies集成和使用文章。