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