(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