什麼是webservice?
什麼是遠程調用技術?答:系統和系統之間的調用,從遠程系統當中獲取業務數據。
Webservice是web服務,他是用http傳輸SOAP協議數據的一種遠程調用技術。
Webservice的入門程序
服務端
第一步:建立SEI接口
第二步:建立SEI實現類,要在類上加入註解:@WebService,做用是標識這個類是服務類,要發佈裏面的public方法。
第三步:發佈服務,Endpoint的publish方法,有2兩個參數:1.服務地址 2.實現類實例
第四步:測試服務是否發佈成功,經過閱讀使用說明書,肯定服務接口、方法、參數和返回值存在,說明服務發佈成功。
WSDL地址:服務地址+」?wsdl」,好比:http://127.0.0.1:54321/weather?wsdl
WSDL閱讀方式,從下往上,service --> binding --> portType --> 其中有接口、方法、參數和返回值
客戶端
第一步:使用wsimport命令生成客戶端代碼
第二步:根據使用說明書,使用客戶端調用服務端
建立服務視圖,視圖是從service的name屬性獲取
獲取服務實現類,從portType的name屬性獲取
調用查詢方法,從portType下的operation標籤的name屬性獲取
Webservice的優缺點:
優勢:發送方式採用http的post,http默認端口是80,因此跨防火牆。
數據封裝使用XML格式,XML是跨平臺,因此webservice能夠跨平臺。
Webservice支持面向對象開發。
缺點:使用XML封裝數據,須要額外傳輸其餘標籤,性能較差。
Webservice的應用場景
宏觀
軟件集成和複用
微觀
適用場景:
發佈服務(對內/對外),不考慮性能,不考慮客戶端類型,建議使用webservice
服務端已經肯定webservice,客戶端只能使用webservice
不適用場景:
考慮性能時,不建議使用webservice
同構程序下,不建議使用webservice,好比:客戶端服務端都是java開發,建議使用Java RMI,Java的RMI一樣能夠實現遠程調用,並且性能比webservice好不少。
Webservice的三要素
WSDL:
定義:web服務描述語言,它是webservice服務端的使用說明書,它說明服務、接口、方法、參數和返回值,它是伴隨服務發佈成功,而自動生成的,無需編寫。
文檔結構:
service
binding
portType
message
types
閱讀方式:從下往上
SOAP:
定義:SOAP即簡單對象訪問協議,它是使用http傳輸XML格式的數據,跨平臺,跨防火牆,它不是webservice專有協議。
Soap = http + xml
協議的格式:
必須項:envelope和body
非必須項有:header和fault
SOAP1.1和1.2區別
相同點:
都使用http的POST發送請求
協議格式都相同:都有envelope和body標籤
不一樣點:
Content-type不一樣:
SOAP1.1:text/xml; charset=utf-8;
SOAP1.2:application/soap+xml; charset=utf-8
命名空間不一樣:
SOAP1.1:http://schemas.xmlsoap.org/soap/envelope/
SOAP1.2:http://www.w3.org/2003/05/soap-envelope
Webservice的四種客戶端調用方式
生成客戶端的調用方式
Service編程的調用方式
HttpURLConnecton調用方式
Ajax調用方式
深刻開發:用註解修改WSDL內容
@Webservice
@WebMethod
@WebParam
@WebResult
修改完WSDL以後,須要從新生成客戶端代碼。
Apache CXF = Celtix + Xfire,開始叫 Apache CeltiXfire,後來改名爲 Apache CXF 了,如下簡稱爲 CXF。
Apache CXF 是一個開源的web Services 框架,CXF 幫助您快速構建和開發 web Services ,它支持多種協議,好比:SOAP1.1,1,2、XML/HTTP、RESTful HTTP 或者 CORBA。
CORBA(Common Object Request Broker Architecture公共對象請求代理體系結構,早期語言使用的WS。C,c++,C#)
CXF是基於SOA總線結構,依靠spring完成模塊的集成,實現SOA方式。
靈活的部署:能夠運行有Tomcat、Jboss、Jetty(內置)、Weblogic上面。
開發步驟:
第一步:導入jar包
第二步:建立SEI接口,要在接口
上加入註解:@WebServicejavascript
package com.itheima.webservice.cxf.server;
import javax.jws.WebService;
/*
* SEI接口
*/
@WebService
public interface WeatherInterface {
public String queryWeather(String cityName);
}
第三步:建立SEI實現類css
package com.itheima.webservice.cxf.server;
/*
* SEI實現類
*/
public class WeatherInterfaceImpl implements WeatherInterface {
@Override
public String queryWeather(String cityName) {
System.out.println("from client..." + cityName);
if ("北京".equals(cityName)) {
return "冷且霾";
} else {
return "暖且晴";
}
}
}
第四步:發佈服務, 使用JaxWsServerFactoryBean發佈服務,須要設置3個參數:1.服務接口; 2.服務實現類; 3.服務地址; Endpoint僅支持發佈實現類,JaxWsServerFactoryBean支持發佈接口。
html
package com.itheima.webservice.cxf.server;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
/*
* 發佈服務端
*/
public class WeatherServer {
public static void main(String[] args) {
/* JaxWsServerFactoryBean發佈服務,須要設置3個參數:1.服務接口; 2.服務實現類; 3.服務地址;
Endpoint僅支持發佈實現類,JaxWsServerFactoryBean支持發佈接口
*/
// JaxWsServerFactoryBean發佈服務
JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();
// 設置服務接口
jaxWsServerFactoryBean.setServiceClass(WeatherInterface.class);
// 設置服務地址
jaxWsServerFactoryBean.setAddress("http://127.0.0.1:12345/weather");
// 設置服務實現類
jaxWsServerFactoryBean.setServiceBean(new WeatherInterfaceImpl());
// 發佈服務
jaxWsServerFactoryBean.create();
}
}
第五步:測試服務是否發佈成功,閱讀使用說明書,肯定關鍵點。咱們先啓動服務端服務,以下圖所示:java
示例代碼以下:nginx
package com.itheima.webservice.cxf.server;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
/*
* 發佈服務端
*/
public class WeatherServer {
public static void main(String[] args) {
/* JaxWsServerFactoryBean發佈服務,須要設置3個參數:1.服務接口; 2.服務實現類; 3.服務地址;
Endpoint僅支持發佈實現類,JaxWsServerFactoryBean支持發佈接口
*/
// JaxWsServerFactoryBean發佈服務
JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();
// 設置服務接口
jaxWsServerFactoryBean.setServiceClass(WeatherInterface.class);
// 設置服務地址
jaxWsServerFactoryBean.setAddress("http://127.0.0.1:12345/weather");
// 設置服務實現類
jaxWsServerFactoryBean.setServiceBean(new WeatherInterfaceImpl());
// 加入CXF攔截器
jaxWsServerFactoryBean.getInInterceptors().add(new LoggingInInterceptor());
jaxWsServerFactoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
// 發佈服務
jaxWsServerFactoryBean.create();
}
}
從新發布服務端和客戶端,服務端控制檯打印出的結果以下:c++
----------------------------
ID: 1
Address: http://127.0.0.1:12345/weather
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[240], content-type=[text/xml; charset=UTF-8], Host=[127.0.0.1:12345], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache-CXF/3.2.6]}
Payload:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><ns2:queryWeather xmlns:ns2="http://server.cxf.webservice.itheima.com/">
<arg0>山西省運城市永濟市</arg0></ns2:queryWeather>
</soap:Body>
</soap:Envelope>
--------------------------------------
from client...山西省運城市永濟市
九月 22, 2018 12:18:05 上午 org.apache.cxf.services.WeatherInterfaceService.WeatherInterfacePort.WeatherInterface
信息: Outbound Message
---------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body><ns2:queryWeatherResponse xmlns:ns2="http://server.cxf.webservice.itheima.com/">
<return>暖且晴</return></ns2:queryWeatherResponse>
</soap:Body>
</soap:Envelope>
--------------------------------------
示例代碼以下:web
package com.itheima.cxf.weather.client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.itheima.cxf.weather.WeatherInterface;
public class WeatherClient {
public static void main(String[] args) {
// JaxWsProxyFactoryBean調用服務端
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
// 設置服務接口
jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class);
// 設置服務地址
jaxWsProxyFactoryBean.setAddress("http://127.0.0.1:12345/weather");
// 獲取服務接口實例
WeatherInterface weatherInterface = jaxWsProxyFactoryBean.create(WeatherInterface.class);
// 調用查詢方法
String weather = weatherInterface.queryWeather("山西省運城市永濟市");
System.out.println(weather);
}
}
服務端效果截圖以下:ajax
開發步驟:
第一步:在MyEclipse中建立Web Project,以後在lib目錄下引入jar包,而後添加至構建路徑(在Eclipse中建立動態的Web Project)
第二步:建立SEI接口
第三步:建立SEI實現類
咱們能夠直接拷貝以前沒有整合Spring時的代碼:建立SEI接口的代碼和建立SEI實現類的代碼。
由於咱們不在WeatherServer.java中發佈服務端了,而是在Tomcat中發佈服務端,因此咱們須要刪掉WeatherServer.java文件。
第四步:整合Spring,配置spring配置文件,applicationContext.xml,在Spring中使用 <jaxws:server 標籤來發布服務,該標籤是對 JaxWsServerFactoryBean類 的封裝,須要設置:1.設置服務地址;2.設置服務接口;3.設置服務實現類
示例代碼以下:
applicationContext.xmlspring
<?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" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 在Spring中使用 <jaxws:server 標籤來發布服務,該標籤是對 JaxWsServerFactoryBean類 的封裝
須要設置:1.設置服務地址;2.設置服務接口;3.設置服務實現類
注意:這裏面的「設置」都應該叫「配置」才更爲恰當哦。
-->
<jaxws:server address="/weather" serviceClass="com.itheima.webservice.cxf.server.WeatherInterface">
<!-- 配置服務實現類 -->
<jaxws:serviceBean>
<ref bean="WeatherInterfaceImpl"/>
</jaxws:serviceBean>
</jaxws:server>
<!-- 配置服務實現類的bean -->
<bean name="WeatherInterfaceImpl" class="com.itheima.webservice.cxf.server.WeatherInterfaceImpl"></bean>
</beans>
第五步:配置web.xml,配置spring配置文件地址和配置加載的listener,配置CXF的servlet
示例代碼以下:
web.xmlapache
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>day46_03_Webservice_cxf_spring_server</display-name>
<!-- 配置web.xml,配置spring配置文件地址和配置加載的listener,配置CXF的servlet -->
<!-- 配置spring配置文件地址 -->
<context-param>
<!-- 注意:contextConfigLocation 這個是不能修改的 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 配置加載的listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置CXF的servlet:是由於服務端須要接收http請求 -->
<servlet>
<servlet-name>CXF</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXF</servlet-name>
<url-pattern>/ws/*</url-pattern><!-- 路徑映射 -->
<!-- <url-pattern>*.action</url-pattern>擴展映射 -->
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
第六步:部署到tomcat下,啓動tomcat
注意:啓動tomcat時控制檯會出現一個錯誤: Error configuring application listener of class [org.springframework.web.context.ContextLoaderListener],以下圖所示:
第七步:測試服務,閱讀使用說明書WSDL地址規則:http://ip:端口號/項目名稱/servlet攔截路徑/服務名稱?wsdl
例如:http://127.0.0.1:8080/day46_03_Webservice_cxf_spring_server/webservice/weather?wsdl
效果截圖以下:
說明界面地址:http://ip:端口號/項目名稱/servlet攔截路徑
須要在 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" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 在Spring中使用 <jaxws:server 標籤來發布服務,該標籤是對 JaxWsServerFactoryBean類 的封裝
須要設置:1.設置服務地址;2.設置服務接口;3.設置服務實現類
注意:這裏面的「設置」都應該叫「配置」才更爲恰當哦。
-->
<jaxws:server address="/weather" serviceClass="com.itheima.webservice.cxf.server.WeatherInterface">
<!-- 配置服務實現類 -->
<jaxws:serviceBean>
<ref bean="WeatherInterfaceImpl"/>
</jaxws:serviceBean>
<!-- 配置CXF攔截器 -->
<jaxws:inInterceptors>
<ref bean="inInterceptor"/>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<ref bean="outInterceptor"/>
</jaxws:outInterceptors>
</jaxws:server>
<!-- 配置服務實現類的bean -->
<bean name="WeatherInterfaceImpl" class="com.itheima.webservice.cxf.server.WeatherInterfaceImpl"></bean>
<!-- 配置CXF攔截器的bean -->
<bean name="inInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
<bean name="outInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</beans>
重啓Tomcat,沒有報錯,CXF攔截器配置成功。
使用<jaxws:endpoint>標籤
示例代碼以下:
package com.itheima.webservice.cxf.server;
import javax.jws.WebService;
/*
* 簡單類
*
* 由於使用Endpoint標籤發佈服務,是不須要接口的
*/
@WebService // @WebService表示該類是一個服務類,須要發佈其中的public的方法,即我想把它發佈成一個服務
public class HelloWorld {
public String sayHello(String name) {
return "hello," + name;
}
}
application.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" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 在Spring中使用 <jaxws:endpoint 標籤來發布服務,該標籤是對 Endpoint類 的封裝
須要設置:1.設置服務地址;2.設置服務實現類
注意:這裏面的「設置」都應該叫「配置」才更爲恰當哦。
-->
<jaxws:endpoint address="/hello" implementor="com.itheima.webservice.cxf.server.HelloWorld"></jaxws:endpoint>
<!-- 在Spring中使用 <jaxws:server 標籤來發布服務,該標籤是對 JaxWsServerFactoryBean類 的封裝
須要設置:1.設置服務地址;2.設置服務接口;3.設置服務實現類
注意:這裏面的「設置」都應該叫「配置」才更爲恰當哦。
-->
<jaxws:server address="/weather" serviceClass="com.itheima.webservice.cxf.server.WeatherInterface">
<!-- 配置服務實現類 -->
<jaxws:serviceBean>
<ref bean="WeatherInterfaceImpl"/>
</jaxws:serviceBean>
<!-- 配置CXF攔截器 -->
<jaxws:inInterceptors>
<ref bean="inInterceptor"/>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<ref bean="outInterceptor"/>
</jaxws:outInterceptors>
</jaxws:server>
<!-- 配置服務實現類的bean -->
<bean name="WeatherInterfaceImpl" class="com.itheima.webservice.cxf.server.WeatherInterfaceImpl"></bean>
<!-- 配置CXF攔截器的bean -->
<bean name="inInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
<bean name="outInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</beans>
而後從新啓動tomcat,沒有報錯,表示成功!
再次訪問:http://127.0.0.1:8080/day46_03_Webservice_cxf_spring_server/webservice/weather?wsdl
新的效果截圖以下:
開發步驟:
第一步:引入jar包
第二步:生成客戶端代碼
第三步:配置spring配置文件,applicationContent.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" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 在Spring中使用 <jaxws:client 標籤來實現客戶端,該標籤是對 JaxWsProxyFactoryBean類 的封裝
須要設置:1.設置服務地址;2.設置服務接口
注意:這裏面的「設置」都應該叫「配置」才更爲恰當哦。
-->
<jaxrs:client id="weatherClient" address="http://127.0.0.1:8080/day46_03_Webservice_cxf_spring_server/webservice/weather" serviceClass="com.itheima.cxf.weather.WeatherInterface"></jaxrs:client>
</beans>
第四步:從spring的上下文中獲取服務實現類
第五步:調用查詢方法,打印
客戶端代碼示例以下:
WeatherClient.java
package com.itheima.cxf.weather.client;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itheima.cxf.weather.WeatherInterface;
public class WeatherClient {
public static void main(String[] args) {
// 初始化Spring的上下文
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
WeatherInterface weatherInterface = (WeatherInterface) context.getBean("weatherClient");
String weather = weatherInterface.queryWeather("山西省運城市永濟市");
System.out.println(weather);
}
}
運行服務端代碼,沒有報錯,成功!
客戶端控制檯截圖以下所示:
CXF的介紹、安裝和配置
CXF是一個開源的webservice的框架,提供不少成熟的功能,能夠實現快速開發
CXF支持的協議:SOAP1.1/1.2,REST
CXF支持的數據格式:XML,JSON
安裝和配置
安裝JDK,建議1.8
解壓cxf壓縮包到指定目錄,配置CXF_HOME
CXF_HOME加入Path中
測試成功,在cmd中輸入wsdl2java –h
使用CXF發佈SOAP協議的服務
服務端
第一步:引入jar包
第二步:建立SEI接口,要在`接口`上加入註解:@WebService
第三步:建立SEI實現類
第四步:發佈服務,使用JaxWsServerFactoryBean發佈服務,設置3個參數,1.服務接口; 2.服務實現類; 3.服務地址
第五步:測試服務
客戶端
第一步:引入jar包
第二步:生成客戶端代碼
第三步:使用JaxWSProxyFactoryBean調用服務端,設置2個參數,1.服務接口;2.服務地址
第四步:獲取實現類的實例,調用查詢方法
CXF + Spring整合發佈SOAP協議的服務
服務端
第一步:在MyEclipse中建立Web Project,以後在lib目錄下引入jar包,而後添加至構建路徑(在Eclipse中建立 動態的Web Project)
第二步:建立SEI接口
第三步:建立SEI實現類
第四步:配置Spring配置文件,applicationContext.xml,`使用<jaxws:server>標籤`
第五步:配置web.xml,配置spring配置文件地址和配置加載的listener,以及CXF的servlet
第六步:部署tomcat下,啓動tomcat
第七步:測試服務是否發佈成功
WSDL地址規則:http://ip:端口號/項目名稱/servlet攔截路徑/服務名稱?wsdl
客戶端
第一步:引入jar包
第二步:生成客戶端代碼
第三步:配置spring的配置文件,applicationContext.xml,`使用<jaxws:client>標籤`
第四步:初始化spring上下文,獲取接口實現類,調用查詢方法
REST 是一種軟件架構模式,只是一種風格,,REST服務採用 HTTP 作傳輸協議,REST 對於 HTTP 的利用實現精確的資源定位。
Rest要求對資源定位更加準確,以下:
非rest方式:http://ip:port/queryUser.action?userType=student&id=001
Rest方式:http://ip:port/user/student/query/001
Rest方式表示互聯網上的資源更加準確,可是也有缺點,可能目錄的層級較多不容易理解。
REST 是一種軟件架構理念,如今被移植到Web服務上,那麼在開發Web服務上,偏於面向資源的服務適用於REST。
REST簡單易用,效率高(不用生成客戶端)。
SOAP 成熟度較高,安全性較好。
注意:REST 不等於WebService,JAX-RS 只是將REST 設計風格應用到Web 服務開發上。
開發步驟:
第一步:導入jar包
第二步:建立學生pojo類,要在類上加入註解:@ XmlRootElement
示例代碼以下:
package com.itheima.cxf.rest.pojo;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
/*
* 學生實體類
*/
@XmlRootElement(name="student") // 該註解 @XmlRootElement 能夠實現對象和XML數據之間的轉換
public class Student {
private long id;
private String name;
private Date birthday;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
第三步:建立SEI接口
示例代碼以下:
package com.itheima.cxf.rest.server;
import java.util.List;
import javax.jws.WebService;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.itheima.cxf.rest.pojo.Student;
/*
* 學生接口
*/
@WebService // @WebService 做用是:標識這個類是服務類,要發佈裏面的public方法。
@Path("/student") // @Path("/student") 做用是:將請求路徑中的「/student」映射到接口上
public interface StudentInterface {
// 查詢單個學生
@GET // 指定請求方式,若是服務端發佈的時候指定的是GET(POST),那麼客戶端訪問時必須使用GET(POST)
@Produces(MediaType.APPLICATION_XML) // 指定服務的數據類型
@Path("/query/{id}") // @Path("/query/{id}") 做用是:將「/query」映射到方法上,將「{id}」映射到參數上,若是是多個參數,以「/」隔開,放到「{}」中
// 查詢單個學生
public Student query(@PathParam("id")long id);
@GET // 指定請求方式,若是服務端發佈的時候指定的是GET(POST),那麼客戶端訪問時必須使用GET(POST)
@Produces(MediaType.APPLICATION_XML) // 指定服務的數據類型
// @Produces("application/json; charset=utf-8") // 指定服務的數據類型
@Path("/queryList/{name}") // @Path("/queryList/{name}") 做用是:將「/query」映射到方法上,將「{name}」映射到參數上,若是是多個參數,以「/」隔開,放到「{}」中
// 查詢多個學生
public List<Student> queryList(@PathParam("name")String name);
}
第四步:建立SEI實現類
示例代碼以下:
package com.itheima.cxf.rest.server;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.itheima.cxf.rest.pojo.Student;
/*
* 學生的實現類
*/
public class StudentInterfaceImpl implements StudentInterface {
@Override
public Student query(long id) {
Student st = new Student();
st.setId(110);
st.setName("張三");
st.setBirthday(new Date());
return st;
}
@Override
public List<Student> queryList(String name) {
Student st = new Student();
st.setId(110);
st.setName("張三");
st.setBirthday(new Date());
Student st2 = new Student();
st2.setId(120);
st2.setName("李四");
st2.setBirthday(new Date());
List<Student> list = new ArrayList<Student>();
list.add(st);
list.add(st2);
return list;
}
}
第五步:發佈服務, 使用JAXRSServerFactoryBean發佈REST服務,發佈前,須要設置3個參數,1.設置服務實現類;2.設置資源類;3.設置服務地址
,而後咱們啓動服務端服務
示例代碼以下:
package com.itheima.cxf.rest.server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
public class StudentServer {
public static void main(String[] args) {
// 使用 JAXRSServerFactoryBean 發佈REST的服務
JAXRSServerFactoryBean jaxRSServerFactoryBean = new JAXRSServerFactoryBean();
// 設置服務實現類
jaxRSServerFactoryBean.setServiceBean(new StudentInterfaceImpl());
// 設置服務資源類,若是有多個資源類,能夠以「,」隔開。
jaxRSServerFactoryBean.setResourceClasses(StudentInterfaceImpl.class);
// 設置服務地址
jaxRSServerFactoryBean.setAddress("http://127.0.0.1:12345/user");
// 發佈服務
jaxRSServerFactoryBean.create();
}
}
第六步:測試服務
一、訪問服務地址:http://127.0.0.1:12345/user/student/query/110
查詢單個學生,返回XML數據,以下圖所示:
二、訪問服務地址:http://127.0.0.1:12345/user/student/query/110
查詢單個學生,返回JSON數據,以下圖所示:
須要先修改學生接口中配置的註解爲@Produces(MediaType.APPLICATION_JSON),以後再從新發布服務
三、訪問服務地址:http://127.0.0.1:12345/user/student/queryList/110
查詢多個學生,返回XML數據,以下圖所示:
四、訪問服務地址:http://127.0.0.1:12345/user/student/queryList/110
查詢多個學生,返回JSON數據,以下圖所示:
須要先修改學生接口中配置的註解爲@Produces(MediaType.APPLICATION_JSON),以後再從新發布服務
注意事項:
REST服務不用生成客戶端代碼,由於服務端返回來的就是XML數據或者JSON數據,咱們只須要經過URL就能拿到數據進行解析就能夠了,因此不須要生成客戶端代碼了。那麼如何解析URL呢?方式一:使用dom4j框架。
能夠自學一下httpclient框架,該框架是專門發送Http請求,而後從URL中獲取數據的框架。自學網址:http://hc.apache.org/httpclient-3.x/
今天咱們不使用httpclient框架,仍是使用HttpURLConnection調用方式實現服務端調用
示例代碼以下:
package com.itheima.cxf.rest.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/*
* HttpURLConnection調用方式實現服務端調用
*/
public class HttpClient {
public static void main(String[] args) throws IOException {
// 第一步:建立服務地址,注意:不是WSDL地址
URL url = new URL("http://127.0.0.1:12345/user/student/query/110");
// 第二步:打開一個通向服務地址的鏈接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 第三步:設置參數
// 設置POST,POST必須大寫,若是不大寫,報以下異常:
// 3.一、設置發送方式:POST必須大寫
connection.setRequestMethod("POST");
// 3.二、設置數據格式:content-type
// connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
// 3.三、設置輸入輸出:由於默認新建立的connection沒有讀寫權限
connection.setDoInput(true);
// connection.setDoOutput(true);
// 若是不設置輸入輸出,會報以下異常:
// 第四步:組織SOAP數據,發送請求
// String soapXML = getXML("13651311090");
// OutputStream os = connection.getOutputStream();
// os.write(soapXML.getBytes());
// 第五步:接收服務端響應,打印
int responseCode = connection.getResponseCode();
if (200 == responseCode) { // 表示服務端響應成功
InputStream is = connection.getInputStream();
InputStreamReader isr = new InputStreamReader(is); // 因爲字節流容易出現亂碼,因此把字節流轉換爲字符流
BufferedReader br = new BufferedReader(isr); // 爲了高效,裝飾一把,裝飾設計模式
StringBuilder sb = new StringBuilder();
String temp = null;
while (null != (temp = br.readLine())) {
sb.append(temp);
}
System.out.println(sb.toString());
// 使用dom4j解析返回的xml數據,課下做業
// ......
// 從裏往外關流
is.close();
isr.close();
br.close();
}
// os.close();
}
/* public static String getXML(String phoneNum) {
String soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+ "<soap:Body>"
+ "<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"
+ "<mobileCode>" + phoneNum + "</mobileCode>"
+ "<userID></userID>"
+ "</getMobileCodeInfo>"
+ "</soap:Body>"
+ "</soap:Envelope>";
return soapXML;
}*/
}
開發步驟:
第一步:建立Web Project項目(引入jar包)
第二步:建立POJO類
第三步:建立SEI接口
第四步:建立SEI實現類
第五步:配置Spring配置文件,applicationContext.xml,使用 <jaxrs:server> 標籤,須要設置2個參數:1.服務地址;2.服務實現類
示例代碼以下:
<?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" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 在Spring中使用 <jaxrs:server 標籤來發布REST服務,該標籤是對 JAXRSServerFactoryBean類 的封裝
須要設置:1.設置服務地址;2.設置服務實現類
注意:這裏面的「設置」都應該叫「配置」才更爲恰當哦。
-->
<jaxrs:server address="/user">
<jaxrs:serviceBeans>
<ref bean="studentInterface"/>
</jaxrs:serviceBeans>
</jaxrs:server>
<!-- 配置服務實現類 -->
<bean name="studentInterface" class="com.itheima.cxf.rest.server.StudentInterfaceImpl"></bean>
</beans>
第六步:配置web.xml
示例代碼以下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>day46_07_Webservice_cxf_rest_spring_server</display-name>
<!-- 配置web.xml,配置spring配置文件地址和配置加載的listener,配置CXF的servlet -->
<!-- 配置spring配置文件地址 -->
<context-param>
<!-- 注意:contextConfigLocation 這個是不能修改的 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 配置加載的listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置CXF的servlet:是由於服務端須要接收http請求 -->
<servlet>
<servlet-name>CXF</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXF</servlet-name>
<url-pattern>/webservice/*</url-pattern><!-- 路徑映射 -->
<!-- <url-pattern>*.action</url-pattern>擴展映射 -->
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
第七步:將項目部署到tomcat下,啓動tomcat,控制檯沒有報錯便可。
第八步:測試服務REST服務的使用說明書地址:http://127.0.0.1:8080/day46_07_Webservice_cxf_rest_spring_server/webservice/user?_wadl
,以下圖所示:
示例代碼以下:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
function queryStudent() {
// 建立XMLHttpRequest對象
var xhr = new XMLHttpRequest();
// 打開鏈接
xhr.open("get", "http://127.0.0.1:8080/day46_07_Webservice_cxf_rest_spring_server/webservice/user/student/queryList/110?_type=json", true);
// 設置數據類型
// xhr.setRequestHeader("content-type", "text/xml;charset=utf-8");
// 設置回調函數
xhr.onreadystatechange=function() {
// 判斷是否發送成功和判斷服務端是否響應成功
if (4 == xhr.readyState && 200 == xhr.status) {
alert(eval("(" + xhr.responseText + ")").student[0].name);
}
}
// // 組織SOAP協議數據
// var soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
// + "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
// + "<soap:Body>"
// + "<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"
// + "<mobileCode>" + document.getElementById("phoneNum").value + "</mobileCode>"
// + "<userID></userID>"
// + "</getMobileCodeInfo>"
// + "</soap:Body>"
// + "</soap:Envelope>";
// alert(soapXML);
// 發送數據
xhr.send(null);
}
</script>
</head>
<body>
<input type="button" value="學生查詢" onclick="javascript:queryStudent();"/>
</body>
</html>
演示效果以下圖所示:
開發步驟:
第一步:建立Web Project項目(引入jar包)
第二步:生成公網客戶端代碼
第三步:建立SEI接口
示例代碼以下:
package com.itheima.mobile.server;
import javax.jws.WebService;
/*
* SEI接口
*/
@WebService // 該註解的做用是:標識這個類是服務類,要發佈裏面的public方法。
public interface MobileInterface {
public String queryMobile(String phoneNum);
}
第四步:建立SEI實現類,由於最後咱們調用公網客戶端代碼的時候,調用的是服務接口中的實現類,因此咱們要把公網客戶端的服務接口給注入進來。公網客戶端的服務接口爲:MobileCodeWSSoap
示例代碼以下:
package com.itheima.mobile.server;
import com.itheima.mobile.MobileCodeWSSoap;
/*
* SEI實現類
* 由於最後咱們調用公網客戶端代碼的時候,調用的是服務接口中的實現類,因此咱們要把公網客戶端的服務接口給注入進來。
* 公網客戶端的服務接口爲:MobileCodeWSSoap
*/
public class MobileInterfaceImpl implements MobileInterface {
private MobileCodeWSSoap mobileClient;
public MobileCodeWSSoap getMobileClient() {
return mobileClient;
}
public void setMobileClient(MobileCodeWSSoap mobileClient) {
this.mobileClient = mobileClient;
}
@Override
public String queryMobile(String phoneNum) {
return mobileClient.getMobileCodeInfo(phoneNum, "");
}
}
第五步:建立queryMobile.jsp
示例代碼以下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>手機號歸屬地查詢網站</title>
</head>
<body>
<form action="queryMobile.action" method="post">
手機號歸屬地查詢:<input type="text" name="phoneNum"/><input type="submit" value="查詢"><br/>
查詢結果:${result}
</form>
</body>
</html>
第六步:建立MobileServlet.java
示例代碼以下:
package com.itheima.mobile.server.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.itheima.mobile.server.MobileInterface;
public class MobileServlet extends HttpServlet {
private MobileInterface mobileServer;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String phoneNum = request.getParameter("phoneNum");
if (null != phoneNum && "".equals(phoneNum)) {
// 經過Spring上下文初始化mobileServer
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
mobileServer = (MobileInterface) context.getBean("mobileServer");
String result = mobileServer.queryMobile(phoneNum);
request.setAttribute(result, "result");
}
// 跳轉頁面
request.getRequestDispatcher("/WEB-INF/jsp/queryMobile.jsp").forward(request, response);;
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
第七步:配置spring配置文件,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" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 在Spring中使用 <jaxws:server 標籤來來發布服務,該標籤是對JaxWsServerFactoryBean類 的封裝
須要設置:1.設置服務地址;2.設置服務接口;3.設置服務實現類
注意:這裏面的「設置」都應該叫「配置」才更爲恰當哦。
-->
<jaxws:server address="/mobile" serviceClass="com.itheima.mobile.server.MobileInterface">
<!-- 配置服務實現類 -->
<jaxws:serviceBean>
<ref bean="mobileServer"/>
</jaxws:serviceBean>
</jaxws:server>
<!-- 配置服務實現類的bean,並注入 -->
<bean name="mobileServer" class="com.itheima.mobile.server.MobileInterfaceImpl">
<property name="mobileClient" ref="mobileClient"></property>
</bean>
<!-- 配置公網客戶端 -->
<jaxws:client id="mobileClient" address="http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx" serviceClass="com.itheima.mobile.MobileCodeWSSoap"></jaxws:client>
</beans>
第八步:配置web.xml
示例代碼以下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>day46_09_Webservice_eg_mobile</display-name>
<!-- 配置web.xml,配置spring配置文件地址和配置加載的listener,配置CXF的servlet -->
<!-- 配置spring配置文件地址 -->
<context-param>
<!-- 注意:contextConfigLocation 這個是不能修改的 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 配置加載的listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置CXF的servlet:是由於服務端須要接收http請求 -->
<servlet>
<servlet-name>CXF</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXF</servlet-name>
<url-pattern>/webservice/*</url-pattern><!-- 路徑映射 -->
<!-- <url-pattern>*.action</url-pattern>擴展映射 -->
</servlet-mapping>
<!-- 配置mobileServlet -->
<servlet>
<servlet-name>mobileServlet</servlet-name>
<servlet-class>com.itheima.mobile.server.servlet.MobileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mobileServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
第九步:將項目部署到tomcat下,啓動tomcat
第十步:測試
測試服務是否發佈成功,訪問地址:http://127.0.0.1:8080/day46_09_Webservice_eg_mobile/webservice,以下圖所示: