(4)CXF基于契约优先实现webservice
(四)CXF基于契约优先实现webservice
基于契约优先编写CXF的webservice
wsdl中增加HEADER,传递一个User对象
使用注解添加Interceptor
第一步:编写xsd
<?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; } @Override public 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 { @Override public long add(int num1, int num2, User license) { //打印licenseInfo System.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才能基于契约优先来发布webservice svrFactory.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); } @Override public void handleMessage(SoapMessage message) throws Fault { List<Header> headers = message.getHeaders(); System.out.println("headers.size:"+headers.size()); try { //创建QName String 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"); //创建DataBinding DataBinding dataBinding = new JAXBDataBinding(User.class); //创建Header Header 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调用 */ @Test public 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