基于契约优先编写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