實現webservice的幾種方式
1. 概念瞭解
-
WebService是兩個系統的遠端呼叫,使兩個系統進行資料互動,如應用:天氣預報服務、銀行ATM取款、使用郵箱賬號登入各網站等。
-
WebService之間的呼叫是跨語言的呼叫。Java、.Net、php,傳送Http請求,使用的資料格式是XML格式。
-
webxml.com.cn上面有一些免費的WebService服務,可以進去看看。
2. 客戶端實現的幾種方式
2.1 Wsimport實現方式
概念理解:
- WSDL – WebService Description Language – Web服務描述語言。
- 通過XML形式說明服務在什麼地方-地址。address location
- 通過XML形式說明服務提供什麼樣的方法 – 如何呼叫。operation
注意:該種方式使用簡單,但一些關鍵的元素在程式碼生成時寫死到生成程式碼中,不方便維護,所以僅用於測試。
實現方式:
(1)Wsimport命令介紹
Wsimport就是jdk(1.6版本之後)提供的的一個工具,他的作用就是根據WSDL地址生成客戶端程式碼;
Wsimport位置JAVA_HOME/bin
Wsimport常用的引數:
-s,生成java檔案的
-d,生成class檔案的,預設的引數
-p,指定包名的,如果不加該引數,預設包名就是wsdl文件中的名稱空間的倒序;
public class MobileClient { public static void main(String[] args) { //建立服務訪問點集合的物件 ,wsdl文件中:<wsdl:service name="MobileCodeWS"> MobileCodeWS mobileCodeWS = new MobileCodeWS(); //獲取服務實現類,wsdl中:<wsdl:portType name="MobileCodeWSSoap"> MobileCodeWSSoap mobileCodeWSSoap = mobileCodeWS.getPort(MobileCodeWSSoap.class); //根據服務訪問點的集合中的服務訪問點的繫結物件來獲得繫結的服務類 MobileCodeWSSoap mobileCodeWSSoap = mobileCodeWS.getMobileCodeWSSoap(); String mobileCodeInfo = mobileCodeWSSoap.getMobileCodeInfo("18518114962", ""); System.out.println(mobileCodeInfo); } }
2.2 service實現方式
service程式設計呼叫方式 ,這種方式其實就是隻需引用服務的方法類就行,不需要全部引用。
public class ServiceClient {
public static void main(String[] args) throws IOException {
//建立WSDL的URL,注意不是服務地址
URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl");
//建立服務名稱
//1.namespaceURI - 名稱空間地址 (wsdl文件中的targetNamespace)
//2.localPart - 服務檢視名 ,wsdl文件中:<wsdl:service name="MobileCodeWS">
QName qname = new QName("http://WebXml.com.cn/", "MobileCodeWS");
/ /wsdlDocumentLocation - wsdl地址 ,serviceName - 服務名稱
Service service = Service.create(url, qname);
//獲取服務實現類 wsdl中:<wsdl:portType name="MobileCodeWSSoap">
MobileCodeWSSoap mobileCodeWSSoap = service.getPort(MobileCodeWSSoap.class);
//呼叫查詢方法
String result = mobileCodeWSSoap.getMobileCodeInfo("1866666666", "");
System.out.println(result);
}
}
2.3 HttpURLConnection呼叫方式
操作步驟,開發步驟:
第一步:建立服務地址
第二步:開啟一個通向服務地址的連線
第三步:設定引數 設定POST,POST必須大寫,如果不大寫,報異常
第四步:組織SOAP資料,傳送請求
第五步:接收服務端響應,列印
public class HttpURLConectionMode {
public static void main(String[] args) throws IOException {
//第一步:建立服務地址,不是WSDL地址
URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx");
//第二步:開啟一個通向服務地址的連線
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//第三步:設定引數
//3.1傳送方式設定:POST必須大寫
connection.setRequestMethod("POST");
//3.2設定資料格式:content-type
connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
//3.3設定輸入輸出,因為預設新建立的connection沒有讀寫許可權,
connection.setDoInput(true);
connection.setDoOutput(true);
//第四步:組織SOAP資料,傳送請求
String soapXML = getXML("15226466316");
OutputStream os = connection.getOutputStream();
os.write(soapXML.getBytes());
//第五步:接收服務端響應,列印(xml格式資料)
int responseCode = connection.getResponseCode();
if(200 == responseCode){//表示服務端響應成功
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
StringBuilder sb = null;
try {
is = connection.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
sb = new StringBuilder();
String temp = null;
while(null != (temp = br.readLine())){
sb.append(temp);
}
System.out.println(sb.toString());
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
br.close();
isr.close();
is.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;
}
}
2.4 Ajax呼叫方式
jsonp無法實現跨域,因為webservice服務的響應格式為xml格式;
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
function queryMobile(){
//建立XMLHttpRequest物件
var xhr = new XMLHttpRequest();
//開啟連線
xhr.open("post","http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx",true);
//設定資料型別
xhr.setRequestHeader("content-type","text/xml;charset=utf-8");
//設定回撥函式
xhr.onreadystatechange=function(){
//判斷是否傳送成功和判斷服務端是否響應成功
if(4 == xhr.readyState && 200 == xhr.status){
alert(xhr.responseText);
}
}
//組織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(soapXML);
}
</script>
</head>
<body>
手機號查詢:<input type="text" id="phoneNum"/> <input type="button" value="查詢" onclick="javascript:queryMobile();"/>
</body>
</html>
下面圖是展示wsdl文件中的關鍵欄位,以及對服務方法的如何使用以及功能描述
3 .服務端的實現
服務端使用cfx+spring和註解實現服務端釋出
pom檔案新增jar包
<!-- 新增cxfwebservice依賴jar包 2018-07-05 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.5.1</version>
</dependency>
web.xml新增配置
<!-- cxf WEBSERVICE配置 -->
<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>/renewal/*</url-pattern>
</servlet-mapping>
spring配置檔案新增配置
<!-- 新增cxfwebservice檔案 -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!--下面的class屬性值一定要跟你專案中服務實現類的包路徑完全一致 -->
<jaxws:endpoint id="renewalPaymentLock" implementor="com.sinosoft.sinopay.web.weixinpay.biz.service.impl.RenewalPaymentLockServiceImpl" address="/RenewalPaymentLock" />
最終生成是地址是: ip/renewal/RenewalPaymentLock?wsdl (web.xml+springd拼接而成的)
介面中虛擬碼實現:
@WebService
public interface RenewalPaymentLockService {
@WebMethod
public String RenewalPaymentLock(String renewalJson);
}
實現類註解:
@WebService(endpointInterface = "com.sinosoft.sinopay.web.weixinpay.biz.service.RenewalPaymentLockService")
endpointInterface 是介面中的地址(包名)
參考文章:https://blog.csdn.net/menghuanzhiming/article/details/78475785