Web Service = SOAP + HTTP + WSDL。其中,SOAP Simple Object Access Protocol)協議是web service的主體,它通過HTTP或者SMTP等應用層協議進行通訊,自身使用XML文件來描述程序的函數方法和參數信息,從而完成不同主機的異構系統間的計算服務處理。這里的WSDL(Web Services Description Language)web 服務描述語言也是一個XML文檔,它通過HTTP向公眾發布,公告客戶端程序關於某個具體的 Web service服務的URL信息、方法的命名,參數,返回值等。。。。。。。。
參考鏈接:http://blog.csdn.net/longwei000/article/details/50592242
本文重在應用,在https://github.com/neugle/spring_mvc_cxf上的代碼修改之,謝謝作者,網上一大堆示例代碼,卻鮮有亮個完整例子的。
1.server端
注意在idea上記得在用Project Structure將resource標注為maven工程能識別的Resource模塊。不然配置文件會找不到。
根據它的mapper文件建立相應數據庫(就一個t_lawyer表),造幾條記錄。
用tomcat8.5將它運行起來,訪問路徑為http://localhost:8092/webservice/testService
2.client端
1)下載apach-cxf,配置其環境變量。
2)wsdl2java -keep http://localhost:8092/webservice/testService?wsdl用於使用wsdl2java命令生成客戶端代碼。
3)copy原工程,刪除java代碼,將上面生成的客戶端代碼copy過來。
4)將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:jaxws="http://cxf.apache.org/jaxws" 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"> <!-- CXF webservice配置 --> <!-- CXF3以后,只需要引入這個配置文件即可,其他兩個廢棄掉了--> <import resource="classpath:META-INF/cxf/cxf.xml"/> <!-- WebService --> <!--<jaxws:endpoint id="testService" implementor="com.rain6.cxf.service.impl.TestWebServiceImpl" address="/testService"/>--> <jaxws:client id="userClient" serviceClass="com.rain6.cxf.service.TestWebService" address="http://localhost:8092/webservice/testService"> </jaxws:client> </beans>
5)寫一個Client.java調用服務端方法
import com.rain6.cxf.service.Lawyer; import com.rain6.cxf.service.TestWebService;import org.springframework.context.support.ClassPathXmlApplicationContext; public class Client { public static void main (String[] strings){ ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:spring/spring-cxf.xml"); TestWebService testWebService = (TestWebService) classPathXmlApplicationContext.getBean("userClient"); Lawyer lawyer = testWebService.selectByPrimaryKey("143347"); System.out.println("----------------->>>>>>>>>>>>>>>>>client calling ......."); System.out.println(lawyer.toString()); } }
3.攔截器
參考鏈接:https://www.cnblogs.com/luangeng/p/6602667.html
1)在服務器端spring-cxf.xml中加入以下配置
<jaxws:inInterceptors>
<!--自定義攔截器--> <bean class="com.rain6.cxf.interceptor.CheckUserInterceptor"></bean>
<!--cxf內置的日志攔截器--> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> </jaxws:inInterceptors>
自定義攔截器必須為AbstractPhaseInterceptor的子類
服務器端的攔截器CheckUserInterceptor.java
public class CheckUserInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public CheckUserInterceptor() {
//在協議化前攔截 super(Phase.PRE_PROTOCOL); } public void handleMessage(SoapMessage soapMessage) throws Fault { //List<Header> headers = soapMessage.getHeaders(); Header header = soapMessage.getHeader(new QName("daidao")); if(header != null){ Element ele = (Element) header.getObject(); String name = ele.getElementsByTagName("name").item(0).getTextContent(); String pwd = ele.getElementsByTagName("password").item(0).getTextContent(); if("kevin".equals(name) && "123456".equals(pwd)){ System.out.println("----------->>>>>>>>>server 通過攔截器"); return; } System.out.println("----------->>>>>>>>>server 不通過攔截器"); throw new Fault(new RuntimeException("用戶名的密碼應該一致。。。。。")); } } }
2)在客戶端spring-cxf.xml中加入以下配置
<jaxws:outInterceptors> <bean class="AddUserInterceptor"> <constructor-arg name="name" value="kevin"></constructor-arg> <constructor-arg name="password" value="123456"></constructor-arg> </bean> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> </jaxws:outInterceptors>
客戶端的攔截器AddUserInterceptor
public class AddUserInterceptor extends AbstractPhaseInterceptor <SoapMessage>{ private String name; private String password; public AddUserInterceptor(String name,String password) { super(Phase.PRE_PROTOCOL); this.name=name; this.password=password; System.out.println("---------------->>>>>>>>>>AddUserInterceptor......."); } public void handleMessage(SoapMessage soapMessage) throws Fault { List<Header> headers = soapMessage.getHeaders(); Document document = DOMHelper.createDocument(); Element rootEle = document.createElement("daidao"); Element nameEle = document.createElement("name"); nameEle.setTextContent(name); rootEle.appendChild(nameEle); Element pwdEle = document.createElement("password"); pwdEle.setTextContent(password); rootEle.appendChild(pwdEle); headers.add(new Header(new QName("daidao"),rootEle)); System.out.println("---------------->>>>>>>>>>client handleMessage"); } }
另外,通過spring 配置實現 webservice 的配置有兩種,jaxws:endpoint和jaxws:server,區別如下
First, they are all for the server side configuration.
Second, jaxws:endpoint is coming from JAXWS API, and it is used to
configure the org.apache.cxf.jaxws.EndpointImpl which extends
javax.xml.ws.Endpoint.
jaxws:server is for configuring the JaxWsServerFactoryBean, which is
coming from the Xfire API.
以我的理解,也就是說使用cxf的話就用jaxws:endpoint