https://www.bilibili.com/video/BV15t411S7V1?p=3&share_source=copy_web
WEB服務接口
1 學習目標
(1) webservice基本概念
(2) ApacheCXF框架介紹
(3) JAX-WS規范下webservice開發
(4) JAX-RS規范下webservice開發
2 webservice 基本概念
2.1 什么是web服務
這里列舉一些常見的web服務:
1. 手機淘寶、京東….
2. 天氣預報
3. 手機號歸屬地
4. 股票查詢
5. 發手機短消息
6. 手機充值功能
7. 中英文翻譯
8. 銀行轉賬業務
9. 公司的“進銷存系統”在某商品缺貨時自動給供應商下訂單
2.2 簡介
(1) webservice 即web服務,它是一種跨編程語言和跨操作系統平台的遠程調用技術。
Web Service所使用的是Internet上統一、開放的標准,如HTTP、XML、SOAP(簡單對象訪問協議)、WSDL等,所以Web Service可以在任何支持這些標准的環境(Windows,Linux)中使用。
這有助於大量異構程序和平台之間的互操作性,從而使存在的應用程序能夠被廣泛的用戶訪問。
如圖:
(2) JAVA 中共有三種WebService 規范,分別是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。
(3) webService三要素:soap、wsdl、uddi
注: 這里的一些概念將在下一章節詳細講解。
2.3 術語
2.3.1 webservice開發規范
JAVA 中共有三種WebService規范,分別是JAXM&SAAJ、JAX-WS(JAX-RPC)、JAX-RS。
下面來分別簡要的介紹一下這三個規范。
(1.)JAX-WS:
JAX-WS(Java API For XML-WebService),JDK1.6 自帶的版本為JAX-WS2.1,其底層支
持為JAXB。JAX-WS(JSR 224)規范的API 位於javax.xml.ws.*包,其中大部分都是注解,
提供API 操作Web 服務(通常在客戶端使用的較多,由於客戶端可以借助SDK 生成,因此這個包中的API 我們較少會直接使用)。
(2.)JAXM&SAAJ:
JAXM(JAVA API For XML Message)主要定義了包含了發送和接收消息所需的API,相當
於Web 服務的服務器端,其API 位於javax.messaging.*包,它是JAVA EE 的可選包,因此
你需要單獨下載。
SAAJ(SOAP With Attachment API For Java,JSR 67)是與JAXM 搭配使用的API,為構建
SOAP 包和解析SOAP 包提供了重要的支持,支持附件傳輸,它在服務器端、客戶端都需要
使用。這里還要提到的是SAAJ 規范,其API 位於javax.xml.soap.*包。
JAXM&SAAJ 與JAX-WS 都是基於SOAP 的Web 服務,相比之下JAXM&SAAJ暴漏了SOAP
更多的底層細節,編碼比較麻煩,而JAX-WS 更加抽象,隱藏了更多的細節,更加面向對
象,實現起來你基本上不需要關心SOAP 的任何細節。那么如果你想控制SOAP 消息的更
多細節,可以使用JAXM&SAAJ,目前版本為1.3。
(3.)JAX-RS:
JAX-RS 是JAVA 針對REST(RepresentationState Transfer)風格制定的一套Web 服務規范,
由於推出的較晚,該規范(JSR 311,目前JAX-RS 的版本為1.0)並未隨JDK1.6 一起發行,
你需要到JCP 上單獨下載JAX-RS 規范的接口,其API 位於javax.ws.rs.*包。
這里的JAX-WS 和JAX-RS 規范我們采用Apache CXF 作為實現,CXF 是Objectweb Celtix
和Codehaus XFire 合並而成。CXF 的核心是org.apache.cxf.Bus(總線),類似於Spring 的
ApplicationContext,Bus 由BusFactory 創建,默認是SpringBusFactory 類,可見默認CXF
是依賴於Spring 的,Bus 都有一個ID,默認的BUS 的ID 是cxf。你要注意的是Apache CXF
2.2 的發行包中的jar 你如果直接全部放到lib 目錄,那么你必須使用JDK1.6,否則會報
JAX-WS 版本不一致的問題。對於JAXM&SAAJ 規范我們采用JDK 中自帶的默認實現。
2.3.2 SOAP 協議
(1) SOAP即簡單對象訪問協議(Simple Object Access Protocol),它是用於交換XML(標准通用標記語言下的一個子集)編碼信息的輕量級協議。它有三個主要方面:XML-envelope為描述信息內容和如何處理內容定義了框架,將程序對象編碼成為XML對象的規則,執行遠程過程調用(RPC)的約定。SOAP可以運行在任何其他傳輸協議上。
(2) SOAP作為一個基於XML語言的協議用於有網上傳輸數據。
(3) SOAP = 在HTTP的基礎上+XML數據。
(4) SOAP是基於HTTP的。
(5) SOAP的組成如下
a) Envelope – 必須的部分。以XML的根元素出現。
b) Headers – 可選的。
c) Body – 必須的。在body部分,包含要執行的服務器的方法。和發送到服務器的數據。
2.3.3 wsdl說明書
Web Service描述語言WSDL(SebService Definition Language)就是用機器能閱讀的方式提供的一個正式描述文檔而基於XML(標准通用標記語言下的一個子集)的語言,用於描述Web Service及其函數、參數和返回值。因為是基於XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的。
wsdl說明書
1) 通過wsdl說明書,就可以描述webservice服務端對外發布的服務;
2) wsdl說明書是一個基於xml文件,通過xml語言描述整個服務;
3) 在wsdl說明中,描述了:
對外發布的服務名稱(類)
接口方法名稱(方法)
接口參數(方法參數)
服務返回的數據類型(方法返回值)
2.3.4 UDDI
Web 服務提供商又如何將自己開發的 Web 服務公布到因特網上,
這就需要使用到 UDDI 了,UDDI的話,是一個跨產業,跨平台的開放性架構,可以幫助 Web 服務提供商在互聯網上發布 Web 服務的信息。
UDDI 是一種目錄服務,企業可以通過 UDDI 來注冊和搜索 Web 服務。
簡單來時候話,UDDI 就是一個目錄,只不過在這個目錄中存放的是一些關於 Web 服務的信息而已。
並且 UDDI 通過SOAP 進行通訊,構建於 . Net 之上。
UDDI 即 Universal Description,Discovery andIntegration,也就是通用的描述,發現以及整合。
UDDI 的目的是為電子商務建立標准;UDDI是一套基於Web的、分布式的、為WebService提供的、信息注冊中心的實現標准規范,同時也包含一組使企業能將自身提供的Web Service注冊,以使別的企業能夠發現的訪問協議的實現標准。
2.4 應用場景
Web Service 可以適用於應用程序集成、軟件重用、跨防火牆通信等需求。不同的業務要求不同。具體如下:
(1) 跨防火牆通信
(2) 應用系統集成
(3) 軟件和數據重用
簡單來說,如果一個功能,需要被多個系統使用可以使用webservice開發一個服務端接口,供不同的客戶端應用。主要應用在企業內部系統之間的接口調用、面向公網的webservice服務。
2.5 優缺點
2.5.1 優點:
a) 異構平台的互通性
理論上, Web Service 最大的優勢是提供了異構平台的無縫街接技術手段。由於不同的用戶使用不同的硬件平台,不同的操作平台,不同的操作系統,不同的軟件,不同的協議通信,這就產生了互相通信的需求。 Web Service 使任何兩個應用程序,只要能讀寫XML,那么就能互相通信。
b) 更廣泛的軟件復用(例如手機淘寶可以復用已有淘寶的業務邏輯.)
軟件的復用技術通過組合已有模塊來搭建應用程序,能大幅度提高軟件的生產效率和質量。用戶只要獲得了描述 Web Service 的 WSDL 文件,就可以方便地生成客戶端代理,並通過代理訪問 Web Service 。
c) 成本低、可讀性強、應用范圍廣
Web Service 可用基於 XML 的 SOAP 來表示數據和調用請求。並且通過 HTTP 協議傳輸 XML 格式的數據
d) 迅捷的軟件發行方式
(每個web Service稱為一個生產者.不同的生產者可以相互協同合作完成整個應用)
Web Service 將徹底地改變軟件的發行方式。
軟件供應商可以把軟件分解成若Web Service 模塊構成的系統,直接在 Web 上發布。
e) 最重要的一點
客戶端與服務端可能是用不同的語言開發的,但是,通過webservice提供服務接口,客戶端與服務端之前可以傳遞對象。
2.5.2 缺點:
由於soap是基於xml傳輸,本身使用xml傳輸會傳輸一些無關內容從而影響效率,隨着soap協議的完善,soap協議增加了許多內容,這樣就導致了使用soap去完成簡單的數據傳輸而攜帶的信息更多效率再受影響;
Web Service作為web跨平台訪問的標准技術,很多公司都限定要求使用Web Service,但如果是簡單的接口可以直接使用http傳輸自定義數據格式,開發更快捷。
2.6 面向服務架構SOA
SOA(Service-OrientedArchitecture)面向服務架構是一種思想,它將應用程序的不同功能單元通過中立的契約(獨立於硬件平台、操作系統和編程語言)聯系起來,使得各種形式的功能單元更好的集成。目前來說,WebService 是SOA 的一種較好的實現方WebService 采用HTTP 作為傳輸協議,SOAP(Simple Object Access Protocol)作為傳輸消息的格式。但WebService 並不是完全符合SOA 的概念,因為SOAP 協議是WebService 的特有協議,並未符合SOA 的傳輸協議透明化的要求。SOAP 是一種應用協議,早期應用於RPC 的實現,傳輸協議可以依賴於HTTP、SMTP 等。
SOA 的產生共經歷了如下過程:
通常采用SOA 的系統叫做服務總線(BUS),結構如下圖所示:
3 ApacheCXF 框架介紹
3.1 關於 Apache CXF
Apache CXF = Celtix + XFire,ApacheCXF 的前身叫 Apache CeltiXfire,現在已經正式更名為 Apache CXF 了,以下簡稱為 CXF。CXF 繼承了 Celtix 和XFire 兩大開源項目的精華,提供了對 JAX-WS 全面的支持,並且提供了多種 Binding 、DataBinding、Transport 以及各種 Format 的支持,並且可以根據實際項目的需要,采用代碼優先(Code First)或者 WSDL 優先(WSDL First)來輕松地實現 Web Services 的發布和使用。目前它仍只是 Apache 的一個孵化項目。
Apache CXF 是一個開源的 Services 框架,CXF 幫助您利用 Frontend 編程 API 來構建和開發 Services ,像 JAX-WS 。這些 Services 可以支持多種協議,比如:SOAP、XML/HTTP、RESTfulHTTP 或者 CORBA ,並且可以在多種傳輸協議上運行,比如:HTTP、JMS 或者 JBI,CXF 大大簡化了 Services 的創建,同時它繼承了 XFire 傳統,一樣可以天然地和 Spring 進行無縫集成。
3.2 功能特性
CXF 包含了大量的功能特性,但是主要集中在以下幾個方面:
(1) 支持 Web Services 標准:CXF 支持多種 Web Services 標准,包含 SOAP、Basic Profile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和 WS-Security。
(2) Frontends:CXF 支持多種“Frontend”編程模型,CXF 實現了 JAX-WS API (遵循 JAX-WS 2.0 TCK 版本),它也包含一個“simple frontend”允許客戶端和 EndPoint 的創建,而不需要 Annotation 注解。CXF 既支持 WSDL 優先開發,也支持從 Java 的代碼優先開發模式。
(3) 容易使用: CXF 設計得更加直觀與容易使用。有大量簡單的 API 用來快速地構建代碼優先的 Services,各種 Maven 的插件也使集成更加容易,支持 JAX-WS API ,支持 Spring 2.0 更加簡化的 XML 配置方式,等等。
(4) 支持二進制和遺留協議:CXF 的設計是一種可插撥的架構,既可以支持 XML ,也可以支持非 XML 的類型綁定,比如:JSON 和 CORBA。
4 ApacheCXF 實現WebService(Jax-ws)
4.1 服務端
4.1.1 創建項目
- file--->new --->module...
maven --->creat from---> quickstart
-
next
-
next
4.1.2 添加cxf依賴
-
項目的pom.xml 添加如下依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast</groupId> <artifactId>01_jaxws_server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>服務端項目</name> <dependencies> <!-- 要進行jaxws 服務開發 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.0.1</version> </dependency> <!-- 內置jetty web服務器 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.0.1</version> </dependency> <!-- 日志實現 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <showWarnings>true</showWarnings> </configuration> </plugin> </plugins> </pluginManagement> </build> </project>
4.1.3 寫服務接口
package com.yu.service;
import javax.jws.WebService;
/**
* 對外發布服務的接口
*/
@WebService
public interface HelloService {
/**
* 對外發布服務的接口的方法
* @param name
* @return
*/
public String sayHello(String name);
}
4.1.4 寫服務接口實現
package com.yu.service.impl;
import com.yu.service.HelloService;
public class HelloServiceImpl implements HelloService{
@Override
public String sayHello(String name) {
return name+"Welcome to yu";
}
}
4.1.5 發布服務
package com.yu;
import com.yu.service.impl.HelloServiceImpl;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
public class Server {
public static void main(String[] args) {
//發布服務的工廠
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
//設置服務地址
factory.setAddress("http://localhost:8010/ws/hello");
//設置服務類
factory.setServiceBean(new HelloServiceImpl());
//添加日志輸入、輸出攔截器,觀察soap請求,soap響應內容
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutFaultInterceptors().add(new LoggingOutInterceptor());
//發布服務
factory.create();
System.out.println("發布服務成功,端口8010!!!!");
}
}
4.1.6 訪問wsdl說明書
- 服務發布成功:
-
訪問wsdl說明書
閱讀順序,從下往上讀。
http://localhost:8010/ws/hello?wsdl
4.2 客戶端
寫客戶端之前要先明確:
- 服務端地址
- 服務端接口、接口方法(方法參數、返回值)
4.2.1 創建項目
創建項目:02_jaxws_client
4.2.2 添加依賴
與服務端項目依賴一致。
4.2.3 服務接口
4.2.4 遠程訪問服務端
package com.yu;
import com.yu.service.HelloService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class Client {
public static void main(String[] args) {
//服務接口訪問地址 http://localhost:8010/ws/hello
//創建cxf代理工廠
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
//設置遠程訪問服務端地址
factory.setAddress("http://localhost:8010/ws/hello");
//設置接口類型
factory.setServiceClass(HelloService.class);
//對接口生成代理對象
HelloService helloService = factory.create(HelloService.class);
// 代理對象 class com.sun.proxy.$Proxy34 Java代理:1靜態代理 2動態代理(Jdk接口代理,cglib子類代理) ¥CGLIB
System.out.println(helloService.getClass());
//遠程訪問服務端方法
String content = helloService.sayHello("Jet");
System.out.println(content);
}
}
4.3 添加日志攔截器,觀察soap協議內容
4.3.1 服務端
//添加日志輸入、輸出攔截器,觀察soap請求,soap響應內容
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutFaultInterceptors().add(new LoggingOutInterceptor());
4.3.2 客戶端調用,觀察日志
- 查看soap請求、soap響應傳輸的xml數據:
2018-04-10 10:52:30,439 72440 [tp2017085051-18] INFO serServiceImplPort.UserService - Inbound Message
----------------------------
ID: 4
Address: http://192.168.95.62:8000/userService
Encoding: UTF-8
Http-Method: POST soap請求
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[193], content-type=[text/xml; charset=UTF-8], Host=[192.168.95.62:8000], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache CXF 3.0.1]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcome xmlns:ns2="http://service.itcast.cn/"><arg0>請求數據</arg0></ns2:welcome></soap:Body></soap:Envelope>
--------------------------------------
2018-04-10 10:52:30,442 72443 [tp2017085051-18] INFO serServiceImplPort.UserService - Outbound Message
---------------------------
ID: 4
Response-Code: 200 soap響應
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcomeResponse xmlns:ns2="http://service.itcast.cn/"><return>響應數據</return></ns2:welcomeResponse></soap:Body></soap:Envelope>
--------------------------------------
5 Spring 整合 ApacheCXF 實現WebService(Jax-ws)
5.1 服務端
5.1.1 創建web項目
- file--->new --->module...
maven --->creat from---> webapp
-
next
-
next
-
next
5.1.2 添加依賴
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yu</groupId>
<artifactId>03_jaxws_spring_server</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>03_jaxws_spring_server Maven Webapp</name>
<dependencies>
<!-- CXF WS開發 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<!-- 運行tomcat7方法:tomcat7:run -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- 指定端口 -->
<port>8080</port>
<!-- 請求路徑 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
5.1.3 web.xml 配置CXFServlet
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--1 cxfservlet配置 -->
<servlet>
<servlet-name>cxfServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxfServlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<!--2 spring容器配置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
5.1.4 服務接口、服務實現
項目目錄結構:
HelloService及接口同上
5.1.5 Spring 整合 ApacheCXF
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<!--Spring 整合cxf發布服務,關鍵點:
1 服務地址
2 服務類
服務完整訪問地址:
http://localhost:8080/ws/hello
-->
<jaxws:server address="/hello">
<jaxws:serviceBean>
<bean class="com.yu.service.impl.HelloServiceImpl"></bean>
</jaxws:serviceBean>
</jaxws:server>
</beans>
5.1.6 啟動服務,發布服務
5.1.7 訪問wsdl說明書
地址: http://localhost:8080/ws/hello?wsdl
5.2 客戶端
5.2.1 創建項目
復制03項目創建04_jaxws_spring_client項目
web.xml配置內容可以刪除。服務實現也刪除。
5.2.2 添加依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yu</groupId>
<artifactId>04_jaxws_spring_client</artifactId>
<version>1.0-SNAPSHOT</version>
<name>04_jaxws_spring_client</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- CXF WS開發 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<!-- 運行tomcat7方法:tomcat7:run -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- 指定端口 -->
<port>8080</port>
<!-- 請求路徑 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
5.2.3 service接口
復制項目時候已經完成。
5.2.4 Spring 整合 ApacheCXF 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<!--
Spring整合ApacheCXF,客戶端配置
關鍵點:
通過Spring整合ApacheCXF,創建客戶端的代理對象,遠程訪問服務端。
jaxws:client
id 應用中注入的接口的代理對象的名稱
address 服務端訪問地址
serviceClass 指定接口路徑,會根據該類型生成代理對象
-->
<jaxws:client
id="helloService"
serviceClass="com.yu.service.HelloService"
address="http://localhost:8080/ws/hello"></jaxws:client>
</beans>
5.2.5 junit測試
package com.yu;
import com.yu.service.HelloService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Client {
// 注入遠程訪問服務端的接口的代理對象。
@Resource
private HelloService helloService;
@Test
public void remote(){
//查看接口的代理對象類型 class com.sun.proxy.$Proxy45
System.out.println(helloService.getClass());
//遠程訪問服務端方法 JerryWelcome to yu
System.out.println(helloService.sayHello("Jerry"));
}
}
6 Restful 風格
一種軟件架構風格,設計風格而不是標准,只是提供了一組設計原則和約束條件。它主要用於客戶端和服務器交互類的軟件。基於這個風格設計的軟件可以更簡潔,更有層次,更易於實現緩存等機制。
REST(英文:Representational State Transfer,簡稱REST)描述了一個架構樣式的網絡系統,比如 web 應用程序。它首次出現在 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規范的主要編寫者之一。在目前主流的三種Web服務交互方案中,REST相比於SOAP(Simple Object Access protocol,簡單對象訪問協議)以及XML-RPC更加簡單明了,無論是對URL的處理還是對Payload的編碼,REST都傾向於用更加簡單輕量的方法設計和實現。值得注意的是REST並沒有一個明確的標准,而更像是一種設計的風格。
所謂"資源",就是網絡上的一個實體,或者說是網絡上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在。你可以用一個URI指向它,每種資源對應一個特定的URI。要獲取這個資源,訪問它的URI就可以,因此URI就成了每一個資源的地址或獨一無二的識別符。所謂"上網",就是與互聯網上一系列的"資源"互動,調用它的URI。
表現層,我們把"資源"具體呈現出來的形式,叫做它的"表現層"(Representation)。
比如,文本可以用txt格式表現,也可以用HTML格式、XML格式、JSON格式表現,甚至可以采用二進制格式;圖片可以用JPG格式表現,也可以用PNG格式表現。
Restful 風格: http://bbs.csdn.net/topics/390908212
非resfull風格:http://bbs.csdn.net/topics?tid=390908212
嚴格地說,有些網址最后的".html"后綴名是不必要的,因為這個后綴名表示格式,屬於"表現層"范疇,而URI應該只代表"資源"的位置。它的具體表現形式,應該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段才是對"表現層"的描述。
狀態轉化(State Transfer)
訪問一個網站,就代表了客戶端和服務器的一個互動過程。在這個過程中,勢必涉及到數據和狀態的變化。互聯網通信協議HTTP協議,是一個無狀態協議。這意味着,所有的狀態都保存在服務器端。因此,如果客戶端想要操作服務器,必須通過某種手段,讓服務器端發生"狀態轉化"(StateTransfer)。而這種轉化是建立在表現層之上的,所以就是"表現層狀態轉化"。客戶端用到的手段,只能是HTTP協議。具體來說,就是HTTP協議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:
GET用來獲取資源,
POST用來新建資源,
PUT用來更新資源,
DELETE用來刪除資源。
訪問服務器資源,通過不同的http請求方式,服務器就知道對CRUD的哪個操作!
JAX-RS 發布服務就是使用RESTFUL風格。
7 ApacheCXF 實現webservice (Jax-rs)
- 基於restful風格的webservice,請求使用的是http協議,可以傳遞xml/json數據
7.1 服務端
7.1.1 創建項目
-
next
7.1.2 添加依賴
-
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <groupId>com.itheima</groupId> <artifactId>05_jaxrs_server</artifactId> <version>1.0-SNAPSHOT</version> <modelVersion>4.0.0</modelVersion> <name>05_jaxrs_server</name> <dependencies> <!-- jaxrs 支持包 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>3.0.1</version> </dependency> <!-- 內置的jetty服務器 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> <!-- 客戶端調用時候使用的包(WebClient工具類調用服務端) --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>3.0.1</version> </dependency> <!-- 基於restful風格的webservice,客戶端與服務端之間可以傳遞json,這個就是json支持相關包 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-extension-providers</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.codehaus.jettison</groupId> <artifactId>jettison</artifactId> <version>1.3.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies>
```<build> <pluginManagement> <plugins> <!-- maven的jdk編譯插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <showWarnings>true</showWarnings> </configuration> </plugin> </plugins> </pluginManagement> </build>
7.1.3 服務接口、實現、實體類
7.1.3.2 准備代碼
/**
* @XmlRootElement 指定根元素,作用:客戶端與服務端傳遞對象數據時候,序列化為xml或json的根元素的名稱
* 客戶端與服務端傳遞XML:
* <Car1></Car> 這里的根元素Car是由name="Car"指定的
*
* 客戶端與服務端傳遞JSON:
* {"Car": {"id":100,"name":"","price":100}}
*
*/
@XmlRootElement(name = "Car")
public class Car {
private Integer id;
private String carName;
private Double price; 省略get、set
}
@XmlRootElement(name = "User")
public class User {
private Integer id;
private String username;
private String city;
private List<Car> cars = new ArrayList<Car>(); 省略get、set
}
@Path("/userService") // 路徑;訪問當前服務接口時候的路徑。
@Produces("*/*")
public interface IUserService {
@POST
@Path("/user") // 路徑; 訪問當前服務接口的方法路徑
// @Consumes 服務端支持的請求的數據格式(xml、json)
@Consumes({ "application/xml", "application/json" })
public void saveUser(User user);
@PUT
@Path("/user")
@Consumes({ "application/xml", "application/json" })
public void updateUser(User user);
@GET
@Path("/user")
// @Produces 服務端支持的響應的數據格式
@Produces({ "application/xml", "application/json" })
public List<User> findAllUsers();
@GET
@Path("/user/{id}")
@Consumes("application/xml")
@Produces({ "application/xml", "application/json" })
public User finUserById(@PathParam("id") Integer id);
@DELETE
@Path("/user/{id}")
@Consumes({"application/xml", "application/json"})
public void deleteUser(@PathParam("id") Integer id);
}
public class UserServiceImpl implements IUserService {
public void saveUser(User user) {
System.out.println("save user:" + user);
}
public void updateUser(User user) {
System.out.println("update user:" + user);
}
public List<User> findAllUsers() {
List<User> users = new ArrayList<User>();
// 汽車
List<Car> carList1 = new ArrayList<Car>();
Car car1 = new Car(101,"保時捷",1000000d);
Car car2 = new Car(102,"林肯",400000d);
carList1.add(car1);
carList1.add(car2);
// 用戶
User user1 = new User(1,"小明","廣州",carList1);
User user2 = new User(2,"小麗","深圳",carList1);
// 用戶集合
users.add(user1);
users.add(user2);
return users;
}
public User finUserById(Integer id) {
if (id == 1) {
return new User(1,"小明","廣州",null);
}
return null;
}
public void deleteUser(Integer id) {
System.out.println("delete user id :" + id);
}
}
7.1.3.2 使用的注解分析
使用的注解:
@XmlRootElement
指定根元素,
作用:客戶端與服務端傳遞對象數據時候,序列化為xml或json的根元素的名稱
@Path("/userService")
路徑;訪問當前服務接口時候的路徑、接口方法的路徑。
@POST insert操作
@PUT update操作
@GET select 查詢操作
@DELETE delete刪除操作
@Consumes 服務端支持的請求的數據格式(xml、json)
@Produces 服務端支持的響應的數據格式
7.1.4 發布服務
package com.itheima;
import com.itheima.service.UserServiceImpl;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
public class Server {
/**
* 發布restful風格的webservice的服務
*/
public static void main(String[] args) {
//1.創建服務工廠
JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
//2.設置服務地址、
factory.setAddress("http://localhost:8001/rs");
//3.實例化服務類、
factory.setServiceBean(new UserServiceImpl());
// 添加日志攔截器
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
//4.創建服務
factory.create();
System.out.println("發布服務成功..8001");
}
}
7.2 客戶端
7.2.1 創建項目
創建項目
7.2.2 添加依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>com.itheima</groupId>
<artifactId>06_jaxrs_client</artifactId>
<version>1.0-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<name>06_jaxrs_client</name>
<dependencies>
<!-- jaxrs 支持包 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 內置的jetty服務器 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<!-- 客戶端調用時候使用的包(WebClient工具類調用服務端) -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 基於restful風格的webservice,客戶端與服務端之間可以傳遞json,這個就是json支持相關包 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<!-- maven的jdk編譯插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
7.2.3 寫junit,遠程訪問服務端
WebClient
.create() 指定服務端地址
.type() 指定請求數據格式(xml、json)
.accept() 指定響應數據格式
.post()/put()/delete()/get() 指定請求類型
package com.itheima;
import com.itheima.domain.User;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.Test;
import javax.ws.rs.core.MediaType;
import java.util.Collection;
public class Client {
@Test
public void save() throws Exception {
// 基於restful風格的webservice開發的客戶端調用,直接通過一個類:WebClient類完成
WebClient
.create("http://localhost:8001/rs/userService/user") // 地址
.type(MediaType.APPLICATION_JSON) // 請求數據格式是json
.post(new User(100,"Kobe","gz",null)); // 發送請求的類型
}
@Test
public void update() throws Exception {
WebClient
.create("http://localhost:8001/ws/userService/user") // 地址
.type(MediaType.APPLICATION_JSON) // 請求數據格式是json
.put(new User(100,"Kobe","gz",null)); // 發送請求的類型
}
@Test
public void delete() throws Exception {
}
@Test
public void findOne() throws Exception {
User user =
WebClient
.create("http://localhost:8001/ws/userService/user/1") // 地址
.accept(MediaType.APPLICATION_JSON) // 響應的數據格式
.get(User.class);
System.out.println(user);
}
@Test
public void findAll() throws Exception {
Collection<? extends User> collection =
WebClient
.create("http://localhost:8001/ws/userService/user")
.accept(MediaType.APPLICATION_JSON)
.getCollection(User.class);
System.out.println(collection);
}
}
8 Sping整合CXF實現基於Restful風格的webservice(jax-rs)
8.1 服務端
8.1.1 創建web項目
8.1.2 添加依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>07_jaxrs_spring_server</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>07_jaxrs_spring_server</name>
<dependencies>
<!-- cxf 進行rs開發 必須導入 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 日志引入 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<!-- 客戶端 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 擴展json提供者 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 轉換json工具包,被extension providers 依賴 -->
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.7</version>
</dependency>
<!-- spring 核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- spring web集成 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- spring 整合junit -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- junit 開發包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
```
```
<build>
<pluginManagement>
<plugins>
<!-- maven的jdk編譯插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<!-- 運行tomcat7方法:tomcat7:run -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- 指定端口 -->
<port>8080</port>
<!-- 請求路徑 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
8.1.3 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>cxfservlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxfservlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<!-- 1. 配置springioc容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
8.1.4 服務接口、實現、實體類
與之前案例一樣:
8.1.5 Spring整合CXF
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://cxf.apache.org/core"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<!--
Spring整合ApacheCXF,發布jaxws服務:
1. 服務地址
2. 服務bean
完整服務地址:
http://localhost:8080/ws/userService
-->
<jaxrs:server address="/userService">
<jaxrs:serviceBeans>
<bean class="com.itheima.service.UserServiceImpl"></bean>
</jaxrs:serviceBeans>
<jaxrs:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
</jaxrs:inInterceptors>
<jaxrs:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
</jaxrs:outInterceptors>
</jaxrs:server>
</beans>
8.1.6 發布服務
8.2 客戶端
8.2.1 創建項目
創建服務端
8.2.2 添加依賴
上面已經完成
8.2.3 實體類
上面已經完成
8.2.4 測試
package com.itheima;
import com.itheima.domain.User;
import org.apache.cxf.jaxrs.client.WebClient;
public class Client {
public static void main(String[] args) {
// 測試1: 保存
WebClient
.create("http://localhost:8080/ws/userService/userService/user")
.post(new User());
// 測試2:刪除(傳入id)
WebClient
.create("http://localhost:8080/ws/userService/userService/user/100")
.delete();
}
}
9 小結
所以,以后如果在開發中涉及多個系統之間的交互,webservice是不錯的選擇。
個人認為使用service最大的好處是客戶端與服務端語言的兼容性及交互時候可以傳遞對象。
今天講到的內容再次梳理一遍:
- webservice 概念
- 簡介
- 術語(開發規范、soap協議、UDDI)
-
應用場景、優缺點
-
Apache CXF 框架介紹
-
jax-ws 規范下的webservice開發、與spring整合
-
jax-rs 風格下的webservice開發、與spring整合