一、什麼是WebService
2013年初出校門,便開始了北漂之旅。閒暇時間就看程序方面的書籍,其中李剛老師的《瘋狂XML講義》也曾拜讀過,那時便有了WebService的初步認知,Spring+Cxf或Spring+axis2也曾練過,未能在項目上大刀闊斧。直到2016年底,給甲方實施企業服務總線(ESB)的時候 ,開始各種天花亂墜的WebService服務、規範開始應用,也逐步揭開了WebService的層層面紗。那麼什麼是WebService呢?在這裏我僅僅從實用性方面做出解釋,更爲深層次的不做言談。
Web Service是一個平臺獨立的,低耦合的,自包含的、基於可編程的web的應用程序,SOAP是一種WebService實現協議。我們所言的Web Service狹義上就是一種基於SOAP協議的接口規範。那麼什麼是SOAP協議呢?即HTTP+XML。其定義以HTTP爲傳輸協議,以XML爲消息協議(報文規範)的一種通訊、交互、溝通的機制。這種機制實現了系統間的底耦合,只需遵從於協議,可以使用任何代碼實現(Tips:上面的定義是一種通俗的解釋,並不嚴謹,比如傳輸協議HTTP也可能是MQ/JMS等)。
二、WebService的本質是什麼
上面已經初步介紹了什麼是WebService,實質就是用一種標準通訊協議(如:HTTP、JMS、MQ),將一個以XML報文爲規範的消息傳遞,這個XML消息規範來源於http://schemas.xmlsoap.org/wsdl/soap/。其將一個XML定義爲信封,有報文頭Header、報文體Body組成,Header可以有多個Xml元素組成,Body僅僅只能有一個元素組成(多爲Complex元素)。
三、Endpoint、JAX-WS、CXF、axis2、自定義Servlet+Document解析,五種方式介紹
下面我們講解一個案例,並以此案例採用上述五種方式實現(實質爲四種)
案例:某一認證服務,用於認證用戶信息,當用戶證件號及姓名一致,則反饋成功,否則認證失敗。同時,爲很好的控制服務訪問,接入方均需告知接入方標識及授權碼。
案例分析:根據上面案例,我們可以提取出認證的實體(消息),用戶(UserInfo)及授權信息(License),用戶有UserName、ID兩個屬性,授權信息有ID及Key兩個屬性。授權信息通常放置在Header中,便於橫向編程訪問控制。業務信息放置於Body中,便於具體業務處理。我們確定該服務爲認證服務VerifyService,操作爲用戶認證UserVerify。整體命名空間爲:http://hlb.com/verifyService。
(一)準備工作
1.編寫WSDL如下(如你對XML 命名空間、複雜類型、序列等有所瞭解,WSDL編寫也較爲簡單):
源文件下載地址:https://download.csdn.net/download/smartyob/12055937
2.java代碼反向生成(wsimport其餘參數自行研究,不做講解)
至此,完成WSDL到JAVA代碼的轉型,編寫實現類如下:
準備工作完成
(二)EndPoint、JAX-WS方式的WebService
優點:不依賴於java框架,源於java自身定義
EndPoint發佈編寫如下:
package test;
import javax.xml.ws.Endpoint;
import com.hlb.verifyservice.impl.VerifyServiceImpl;
public class VerifyServiceMain {
public static void main(String[] args) {
Endpoint endpoint = Endpoint.create(new VerifyServiceImpl());
endpoint.publish("http://127.0.0.1:8090/ws/VerifyService");
}
}
運行發佈:
測試成功:
JAX-WS方式依賴jar包如下:
主要步驟有:
1.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"
id="WebApp_ID" version="2.5">
<listener>
<!-- 引入jaxws-ri.jar中的監聽器 -->
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<!-- servlet-name與sun-jaxws.xml中的name一致 -->
<servlet-name>VerifyService</servlet-name>
<!-- 使用jaxws-ri.jar中的servlet -->
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>VerifyService</servlet-name>
<!-- servlet-name與sun-jaxws.xml中的url-pattern一致 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
2.配置endpoint
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
<endpoint name="VerifyService" implementation="com.hlb.verifyservice.impl.VerifyServiceImpl"
url-pattern="/VerifyService"></endpoint>
</endpoints>
測試結果
VerifyServiceMain 爲EndPoint發佈,Web啓動爲JAX-WS發佈,程序代碼詳見:https://download.csdn.net/download/smartyob/12056014
(三)CXF方式的WebService
這裏介紹的是Spring方式進行Bean的代理對關鍵代碼貼圖如下:
1. web.xml 申明cxf、spring的集成
<?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"
id="WebApp_ID" version="2.5">
<!--配置spring容器的管理 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- cxf的配置 -->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
</web-app>
2.applicationContext.xml,spring對Bean的管理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Spring 模塊化治理及定義 -->
<import resource="spring-cxf.xml" />
<!-- Bean定義 -->
<bean id="VerifyServiceImpl" class="com.hlb.verifyservice.impl.VerifyServiceImpl"></bean>
</beans>
3.spring-cxf.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:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!-- implementor屬性裏寫的是bean的id,以#,後面是BeanName-->
<jaxws:endpoint implementor="#VerifyServiceImpl" address="/VerifyService" />
</beans>
4.啓動測試
程序代碼詳見:https://download.csdn.net/download/smartyob/12058918
(四)axis2方式的WebService
1. web.xml 申明axis2、spring的集成
2.applicationContext.xml,spring對Bean的管理
3.啓動測試
(五)自定義Servlet+Document解析方式的WebService
第二章節已經對WebService有了粗暴的解釋,HTTP+XML
HTTP:使用Servlet、SpringMVC的Controller承載
XML:使用Documet解析獲取業務數據
數據在哪裏呢?答案是 RequestBody中,不做解釋,流程如下:
1.創建 WebService的Servlet
package com.hbl.servlet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.w3c.dom.Document;
import com.hlb.utils.util.xml.DomUtil;
/**
* Servlet implementation class WebServiceServlet
*/
public class WebService extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public WebService() {
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
InputStream in = request.getInputStream();
try {
Document dom = DomUtil.getDocumentByInputStream(in);
String UserName = DomUtil.getNodeByReg(dom.getDocumentElement(), "Body>userVerify>UserInfoData>UserName").getTextContent();
System.out.println("UserName:"+UserName);
} catch (Exception e) {
e.printStackTrace();
}
response.getOutputStream().write("<soapenv:Envelope xmlns:soapenv=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\" xmlns:ver=\\\"http://hlb.com/verifyService\\\"><soapenv:Header><ver:License><ver:ID>?</ver:ID><ver:Key>?</ver:Key></ver:License></soapenv:Header><soapenv:Body><ver:UserVerifyResponse><ver:ResponseCode>0000</ver:ResponseCode><ver:ResponseMessage>Suucess</ver:ResponseMessage></ver:UserVerifyResponse></soapenv:Body></soapenv:Envelope>".getBytes());
}
}
2.啓動測試
1.SOAP報文(XML)HTTP請求獲得RequestBody中
2.Dom解析業務數據
3.組織報文放置與ResponseBody中反饋
這個就是本質代碼