请参照:apache-cxf-2.5.1、jdk1.6.0_10
1.如何基于CXF发布接口以及客户端调用请参照下面的网址:
http://www.cnblogs.com/hoojo/tag/WebService/
这里面说了关于CXF的拦截器、与spring的整合以及复杂数据类型的传递。
2.从官方下载的CXF包里面,有个samples文件夹,这里面有各种应用的例子。
3.CXF本身自带的lib包里面就已经包含了spring的包,如下:
如果你的工程师已经是spring平台,这些包是不需要的。
关于具体每个包的作用以及要不要请结合lib文件夹下面的WHICH_JARS文件,这个文件里面有说明。
4.关于如何根据现有的wsdl生成客户端与服务端:
生成客户端命令
wsdl2java -d [数据绑定的类型] -wv [指定wsdl版本] -p [指定生成的包名] -sn [指定wsdl具体的service name] -client [wsdl文件路径]
整个黑线框里就是我根据wsdl生成的客服端代码,有一个报错的类,你只需要把报错方法里面super第三个参数删除就可以了。
PlatformServiceType_PlatformServiceType_Client生成的这个类主要是一个远程调用的测试类(它需要在当前路径下存放wsdl文件)
PlatformServiceType生成的这个接口包括了所有的方法。
其它的都是一些实体bean对象。
一般我们不用它生成的远程测试类方式,而是用一下方式实现:
/**
*
*/
package com.ml.sns.ws.cxf.remote;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Logger;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.ml.sns.ws.cxf.BabyHealthInfoBean;
import com.ml.sns.ws.cxf.BabyInfoBean;
import com.ml.sns.ws.cxf.PlatformServiceType;
import com.ml.sns.ws.cxf.ResultInfo;
import com.ml.sns.ws.cxf.UserInfoBean;
import com.ml.sns.ws.cxf.interceptor.AddSoapHeader;
/**
* @author minglei
*
*/
public class RemoteClient {
/**
* 日志打印
*/
private static final Logger LOG = null;//Logger.getLogger(RemoteClient.class);
private static RemoteClient remoteClient = null;
private static JaxWsProxyFactoryBean factory = null;
private static PlatformServiceType service = null;
private static String platformAddress = null;
//鉴权属性
public static String authAccount = null;
public static String authPassword = null;
public static String appID = null;
static {
init();
}
/**
* 初始化参数
*/
private static void init() {
try {
// 解析配置文件,获取接口配置信息
InputStream is = RemoteClient.class
.getResourceAsStream("/application.properties");
Properties p = new Properties();
p.load(is);
//远程服务地址http://127.0.0.1:8088/services/snsService
platformAddress = p.getProperty("ws.platform.address");
authAccount = p.getProperty("ws.auth.account");
authPassword = p.getProperty("ws.auth.password");
appID = p.getProperty("ws.platform.appid");
factory = new JaxWsProxyFactoryBean();//创建代理工厂
factory.setServiceClass(PlatformServiceType.class);//服务的接口类----生成的
factory.setAddress(platformAddress);//设置远程服务地址
//构造拦截器列表
ArrayList<Interceptor<?>> list = new ArrayList<Interceptor<?>>();
// 添加soap header
list.add(new AddSoapHeader());
// 添加soap消息日志打印
list.add(new org.apache.cxf.interceptor.LoggingOutInterceptor());
factory.setOutInterceptors(list);
service = (PlatformServiceType) factory.create();//通过代理工厂获得服务的实现调用类
} catch (Exception e) {
if (true) {
LOG.info("Failed initialization webservice information."
+ e.getMessage());
}
}
}
//下面的获得服务的实现调用类,来调用远程的方法
public ResultInfo addBabyInfo(BabyInfoBean babyInfo) {
return service.addBabyInfo(babyInfo);
}
public ResultInfo addUserInfo(UserInfoBean userinfo) {
return service.addUserInfo(userinfo);
}
public ResultInfo addBabyHealthInfo(BabyHealthInfoBean babyHealthInfo) {
return service.addBabyHealthInfo(babyHealthInfo);
}
/**
* 获得远程调用接口实例
* @return RemoteClient
*/
public static RemoteClient getRCInstance()
{
if(remoteClient ==null)
{
remoteClient = new RemoteClient();
}
return remoteClient;
}
}
生成服务端命令
wsdl2java -d [数据绑定的类型] -wv [指定wsdl版本] -p [指定生成的包名] -sn [指定wsdl具体的service name] -impl -server[wsdl文件路径]
上图是根据wsdl生成的服务端
生成的PlatformServiceType_PlatformServiceType_Server类是用来启服务的,一般都web程序都不这么用,而是通过容器启动。
蓝线框里面的两个类,一个是接口,一个是接口的实现类这种正好和我们前通过接口发布服务一致,只需要在xml配置就可以了,在这里就不多说了。
所以,我们的业务可以在接口的实现类里面调用。
5.换SOAP消息头添加与解析:
在远程客服端添加消息头,通过拦截器;在前面4节的代码中已经实现了添加消息头功能。
/**
*
*/
package other.interceptor;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import other.Utils;
/**
* @author minglei
*
*/
public class AddSoapHeader extends AbstractSoapInterceptor {
private static String nameURI = "http://webservice.iBaby.huawei.com/";
public AddSoapHeader() {
super(Phase.WRITE);
}
/**
* 在发送报文前,添加消息头鉴权
*/
public void handleMessage(SoapMessage message) throws Fault {
/**
* 在消息投头中添加复杂对象节点,多层嵌套
* <soap:Header>
* <tns:RequestSOAPHeader xmlns:tns="http://webservice.iBaby.huawei.com/">
* <tns:timestamp xmlns="http://webservice.iBaby.huawei.com/">20120118162416</tns:timestamp>
* <tns:account xmlns="http://webservice.iBaby.huawei.com/">ming</tns:account>
* <tns:authenToken xmlns="http://webservice.iBaby.huawei.com/">......</tns:authenToken>
* </tns:RequestSOAPHeader>
* </soap:Header>
*/
addSoapHeader1(message);
/**
* 在消息投头中添加节点,报文如下:
* <soap:Header>
* <timestamp xmlns="http://webservice.iBaby.huawei.com/">20120118162416</timestamp>
* <account xmlns="http://webservice.iBaby.huawei.com/">ming</account>
* <authenToken xmlns="http://webservice.iBaby.huawei.com/">......</authenToken>
* </soap:Header>
*/
addSoapHeader2(message);
//注意方法同时只能调用一个
}
/**
* @param message
*/
private void addSoapHeader1(SoapMessage message) {
QName qname = new QName("RequestSOAPHeader");
Document doc = DOMUtils.createDocument();
// 自定义节点
Element timestamp = doc.createElement("tns:timestamp");
timestamp.setTextContent(Utils.getSystemTime());
Element account = doc.createElement("tns:account");
account.setTextContent("uououo");
//鉴权authenToken
Element pass = doc.createElement("tns:authenToken");
pass.setTextContent(Utils.encryptSHA256("123456"));
Element root = doc.createElementNS(nameURI, "tns:RequestSOAPHeader");
root.appendChild(timestamp);
root.appendChild(account);
root.appendChild(pass);
SoapHeader head = new SoapHeader(qname, root);
List<Header> headers = message.getHeaders();
headers.add(head);
}
/**
* @param message
*/
private void addSoapHeader2(SoapMessage message) {
//时间戳
Document doc = DOMUtils.createDocument();
QName qname = new QName("timestamp");
Element timestamp = doc.createElementNS(nameURI, "timestamp");
timestamp.setTextContent(Utils.getSystemTime());
SoapHeader headTime = new SoapHeader(qname, timestamp);
//账号
QName qname2 = new QName("account");
Element account = doc.createElementNS(nameURI, "account");
account.setTextContent("mlmlml");
SoapHeader headaAccount = new SoapHeader(qname2, account);
// 鉴权authenToken
QName qname3 = new QName("authenToken");
Element pass = doc.createElementNS(nameURI, "authenToken");
pass.setTextContent(Utils.encryptSHA256("123456"));
SoapHeader headPass = new SoapHeader(qname3, pass);
List<Header> headers = message.getHeaders();
headers.add(headTime);
headers.add(headaAccount);
headers.add(headPass);
}
}
在服务端添加解析消息头的拦截器,然后添加到配置文件中,结合1节网址里面的内容
/**
*
*/
package other.interceptor;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.NodeList;
/** */
/**
*
* @Title:获取soap头信息
*
* @Description:
*
* @Copyright:
*
* @author minglei
* @version 1.00.000
*
*/
public class ReadSoapHeader extends AbstractPhaseInterceptor<SoapMessage> {
private SAAJInInterceptor saa = new SAAJInInterceptor();
public ReadSoapHeader() {
super(Phase.PRE_PROTOCOL);
getAfter().add(SAAJInInterceptor.class.getName());
}
public void handleMessage(SoapMessage message) throws Fault {
SOAPMessage mess = message.getContent(SOAPMessage.class);
if (mess == null) {
saa.handleMessage(message);
mess = message.getContent(SOAPMessage.class);
}
SOAPHeader head = null;
try {
head = mess.getSOAPHeader();
} catch (SOAPException e) {
e.printStackTrace();
}
if (head == null) {
return;
}
try {
// 读取自定义的节点
NodeList nodes = head.getElementsByTagName("tns:account");
NodeList nodepass = head.getElementsByTagName("tns:authenToken");
// 获取节点值,简单认证
if (nodes.item(0).getTextContent().equals("wdw")) {
if (nodepass.item(0).getTextContent().equals("wdwsb")) {
System.out.println("认证成功");
}
} else {
SOAPException soapExc = new SOAPException("认证错误");
throw new Fault(soapExc);
}
} catch (Exception e) {
SOAPException soapExc = new SOAPException("认证错误");
throw new Fault(soapExc);
}
}
}