(四)CXF基于契约优先实现webservice
<?xml version="1.0" encoding="UTF-8"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/cal" xmlns:tns="http://www.example.org/cal" elementFormDefault="unqualified"> <xsd:element name="add" type="tns:add"/> <xsd:element name="addResponse" type="tns:addResponse"/> <!-- 头信息 --> <xsd:element name="license" type="tns:user"></xsd:element> <xsd:complexType name="add"> <xsd:sequence> <xsd:element name="num1" type="xsd:int"/> <xsd:element name="num2" type="xsd:int"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="addResponse"> <xsd:sequence> <xsd:element name="result" type="xsd:long"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="user"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="pwd" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema>
?
?
?
第二步,编写wsdl
<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.example.org/cal" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="CalWsService" targetNamespace="http://www.example.org/cal"> <wsdl:types> <xsd:schema targetNamespace="http://www.example.org/cal"> <xsd:include schemaLocation="cal.xsd"></xsd:include> </xsd:schema> </wsdl:types> <!-- 头信息 --> <wsdl:message name="license"> <wsdl:part name="license" element="tns:license"></wsdl:part> </wsdl:message> <wsdl:message name="add"> <wsdl:part element="tns:add" name="parameters"/> </wsdl:message> <wsdl:message name="addResponse"> <wsdl:part element="tns:addResponse" name="parameters"/> </wsdl:message> <wsdl:portType name="ICalService"> <wsdl:operation name="add"> <wsdl:input message="tns:add"/> <wsdl:output message="tns:addResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="calSOAP" type="tns:ICalService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="add"> <wsdl:input> <soap:body use="literal"/> <!-- header --> <soap:header use="literal" part="license" message="tns:license"></soap:header> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="CalWsService"> <wsdl:port binding="tns:calSOAP" name="calSOAPPart"> <soap:address location="http://localhost:8888/cxf/ws"/> </wsdl:port> </wsdl:service></wsdl:definitions>
?
?
?
第三步:将wsdl通过CXF的wsdl2java命令转换为本地java文件(只要接口即可)
POM.xml中增加wsdl2java的插件命令
<build><plugins><plugin><groupId>org.apache.cxf</groupId><artifactId>cxf-codegen-plugin</artifactId><version>${cxf.version}</version><executions><execution><id>generate-sources</id><phase>compile</phase><configuration><sourceRoot>${project.build.directory}/generated/cxf</sourceRoot><wsdlOptions><wsdlOption> <!-- 本地wsdl文件地址 --><wsdl>src/main/resources/META-INF/wsdl/cal.wsdl</wsdl></wsdlOption></wsdlOptions></configuration><goals><goal>wsdl2java</goal></goals></execution></executions></plugin></plugins></build>
?
模型
package com.hqh.ws.cxf.model;public class User {private String name;private String pwd;public User() {super();}public User(String name, String pwd) {super();this.name = name;this.pwd = pwd;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}@Overridepublic String toString() {return "User [name=" + name + ", pwd=" + pwd + "]";}}
?
?
?
删除接口中的@XmlSeeAlso({ObjectFactory.class})和注解中定义的class属性
在add()上手动加入头信息 @WebParam(name="license", header=true) User user
?
package org.example.cal;import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebResult;import javax.jws.WebService;import javax.xml.ws.RequestWrapper;import javax.xml.ws.ResponseWrapper;import com.hqh.ws.cxf.model.User;/** * This class was generated by Apache CXF 2.6.0 * 2013-08-17T11:29:27.810+08:00 * Generated source version: 2.6.0 * */@WebService(targetNamespace = "http://www.example.org/cal", name = "ICalService")public interface ICalService { @WebResult(name = "result", targetNamespace = "") @RequestWrapper(localName = "add", targetNamespace = "http://www.example.org/cal") @WebMethod @ResponseWrapper(localName = "addResponse", targetNamespace = "http://www.example.org/cal") public long add( @WebParam(name = "num1", targetNamespace = "") int num1, @WebParam(name = "num2", targetNamespace = "") int num2, //手动增加头信息 @WebParam(name="license", header=true) User user );}
?
?
?
编写实现类
package org.example.cal;import javax.jws.WebService;import com.hqh.ws.cxf.model.User;@WebService(endpointInterface="org.example.cal.ICalService",serviceName="CalWsService",portName="calSOAPPart",targetNamespace="http://www.example.org/cal")public class CalServiceImpl implements ICalService {@Overridepublic long add(int num1, int num2, User license) {//打印licenseInfoSystem.out.println(license);long result = num1 + num2;System.out.println(num1+"+"+num2+"="+result);return result;}}
?
?
?
使用CXF发布服务
package org.example.cal;import javax.xml.namespace.QName;import org.apache.cxf.jaxws.JaxWsServerFactoryBean;public class MyCXFServer {public static void main(String[] args) {JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();svrFactory.setAddress("http://localhost:8888/cxf/ws");svrFactory.setServiceClass(ICalService.class);svrFactory.setServiceBean(new CalServiceImpl());//必须显示定义WsdlLocation和ServiceName才能基于契约优先来发布webservicesvrFactory.setWsdlLocation("src/main/resources/META-INF/wsdl/cal.wsdl");svrFactory.setServiceName(new QName("http://www.example.org/cal","CalWsService"));//开启服务svrFactory.create();}}
?
客户端通过公布的wsdl的URL,使用wsdl2java转换为本地java文件
pom.xml中增加wsdl2java插件
<build><plugins><plugin><groupId>org.apache.cxf</groupId><artifactId>cxf-codegen-plugin</artifactId><version>${cxf.version}</version><executions><execution><id>generate-sources</id><phase>compile</phase><configuration><sourceRoot>${project.build.directory}/generated/cxf</sourceRoot><wsdlOptions><wsdlOption> <!-- 网络wsdl文件地址 --><wsdl>http://localhost:8888/cxf/ws?wsdl</wsdl></wsdlOption></wsdlOptions></configuration><goals><goal>wsdl2java</goal></goals></execution></executions></plugin></plugins></build>
编写拦截器
package com.hqh.ws.cxf.interceptor;import java.util.List;import javax.xml.bind.JAXBException;import javax.xml.namespace.QName;import org.apache.cxf.binding.soap.SoapMessage;import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;import org.apache.cxf.databinding.DataBinding;import org.apache.cxf.headers.Header;import org.apache.cxf.interceptor.Fault;import org.apache.cxf.jaxb.JAXBDataBinding;import org.apache.cxf.phase.Phase;import com.hqh.ws.cxf.model.User;public class LicenseOutInterceptorNew extends AbstractSoapInterceptor{/** * 指定加入拦截器到某个阶段 * @param p */public LicenseOutInterceptorNew() {super(Phase.WRITE);}@Overridepublic void handleMessage(SoapMessage message) throws Fault {List<Header> headers = message.getHeaders();System.out.println("headers.size:"+headers.size());try {//创建QNameString namespaceURI = "http://www.example.org/cal";String localPart = "license";String prefix = "ns";QName qname = new QName(namespaceURI, localPart, prefix);//头信息为一个对象User user = new User("root","root123");//创建DataBindingDataBinding dataBinding = new JAXBDataBinding(User.class);//创建HeaderHeader header = new Header(qname, user, dataBinding);//将header加入到SOAP头集合中headers.add(header);} catch (JAXBException e) {e.printStackTrace();throw new Fault(e);}}}
?
在客户端的服务接口上使用注解加入拦截器
package org.example.cal;import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebResult;import javax.jws.WebService;import javax.xml.bind.annotation.XmlSeeAlso;import javax.xml.ws.RequestWrapper;import javax.xml.ws.ResponseWrapper;import org.apache.cxf.interceptor.InInterceptors;import org.apache.cxf.interceptor.OutInterceptors;/** * This class was generated by Apache CXF 2.6.0 * 2013-08-17T12:22:32.760+08:00 * Generated source version: 2.6.0 * */@WebService(targetNamespace = "http://www.example.org/cal", name = "ICalService")@XmlSeeAlso({ObjectFactory.class})//将LicenseOutInterceptorNew加入到out拦截器链中@OutInterceptors (interceptors = {"com.hqh.ws.cxf.interceptor.LicenseOutInterceptorNew" })public interface ICalService { @WebResult(name = "result", targetNamespace = "") @RequestWrapper(localName = "add", targetNamespace = "http://www.example.org/cal", className = "org.example.cal.Add") @WebMethod @ResponseWrapper(localName = "addResponse", targetNamespace = "http://www.example.org/cal", className = "org.example.cal.AddResponse") public long add( @WebParam(name = "num1", targetNamespace = "") int num1, @WebParam(name = "num2", targetNamespace = "") int num2 );}
?
调用服务端提供的服务
/** * 基于契约优先的CXF webservice调用 */@Testpublic void test04() {//ICalService service = new CalWsService().getCalSOAPPart();//long ret = service.add(1, 11);//System.out.println(ret);JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();factory.setAddress("http://localhost:8888/cxf/ws?wsdl");factory.setServiceClass(ICalService.class);ICalService service = (ICalService)factory.create();long ret = service.add(11, 1);System.out.println(ret);}
?
客户端发出的消息与接收到的返回值:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><ns:license xmlns:ns="http://www.example.org/cal"><name>root</name><pwd>root123</pwd></ns:license></soap:Header><soap:Body><ns2:add xmlns:ns2="http://www.example.org/cal"><num1>11</num1><num2>1</num2></ns2:add></soap:Body></soap:Envelope>
?
--------------------------------------12
?
?
?
服务端处理结果:
User [name=root, pwd=root123]11+1=12
?
?
?
?
?