一、客户端添加系统拦截器
1、客户端添加拦截器时,需要导入CXF所需要Jar包
2、代码如下所示
//为客户端添加拦截器
//1、调用ClientProxy的getClient方法,调用该方法以远程Web Service的代理为参数
//2、调用Client的getInInterceptors,getOutInterceptors方法来获取in,out,拦截器列表,接下来就可以添加拦截器了
Client client = ClientProxy.getClient(hw);
client.getInInterceptors().add(new LoggingInInterceptor());
client.getOutInterceptors().add(new LoggingOutInterceptor());
此时运行客户端,就会发现在客户端的控制台上也会出现日志消息
二、自定义拦截器
1、服务端添加自定义拦截器
主要是解析Header元素,对于Body元素不做解析,因为Body元素的内容是由WSDL来定义的
package com.onyas.ws.cxf.util;
import java.util.List;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
*通过 PhaseInterceptor可以指定拦截器在哪个阶段起作用
*/
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public AuthInterceptor() {
//super表示显示调用父类有参数的构造器,程序将不会隐式调用父类的无参构造器
//
super(Phase.PRE_INVOKE);
}
/**
* 实现自己的拦截器时,需要实现handleMessage方法,该方法的形参就是拦截到的SOAP消息,
* 一旦程序中获取到了Soap消息,剩下的事情就可以解析Soap消息,或是修改Soap消息
* @param msg 所拦截到的Soap消息
* @throws Fault
*/
@Override
public void handleMessage(SoapMessage msg) throws Fault {
//得到Soap消息所有的header
List<Header> headers = msg.getHeaders();
//如果根本没有Header
if(headers == null || headers.size()<1){
throw new Fault(new IllegalArgumentException("根本没有header,无法调用"));
}
//假如要求第一个Header携带了用户名,密码
Header firstHeader = headers.get(0);
Element ele = (Element) firstHeader.getObject();
NodeList usernames = ele.getElementsByTagName("username");
NodeList passwords = ele.getElementsByTagName("password");
if(usernames.getLength()!=1){
throw new Fault(new IllegalArgumentException("用户名格式不正确"));
}
if(passwords.getLength()!=1){
throw new Fault(new IllegalArgumentException("密码格式不正确"));
}
// 得到第一个username元素里的文本内容,以该内容作为用户名字
String username = usernames.item(0).getTextContent();
String password = passwords.item(0).getTextContent();
//在实际项目中,应该去查询数据库,该用户名,密码是否被授权调用Web Service
if(!username.equals("root") || !password.equals("123")){
throw new Fault(new IllegalArgumentException("用户名或密码不正确"));
}
}
}
2、客户端在请求时,要加入验证信息,也需要自定义拦截器,以实现改变Header元素的目地
package onyas;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class AddHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private String un;
private String pw;
public AddHeaderInterceptor(String username, String password) {
super(Phase.PREPARE_SEND);//在准备发送SOAP消息时启动拦截器
un = username;
pw = password;
}
@Override
public void handleMessage(SoapMessage msg) throws Fault {
List<Header> headers = msg.getHeaders();
Document doc = DOMUtils.createDocument();
Element Authheader = doc.createElement("AuthHeader");
//此处创建的元素应该按照服务器那边的要求
Element username = doc.createElement("username");
username.setTextContent(un);
Element password = doc.createElement("password");
password.setTextContent(pw);
Authheader.appendChild(username);
Authheader.appendChild(password);
/**
* 上面代码生成了如下的XML片段
* <AuthHeader>
* <username>un</username>
* <password>pw</password>
* </AuthHeader>
*/
//把Authheader元素包装成Header,并添加到Soap消息的Header列表中
headers.add(new Header(new QName("onyas"), Authheader));
}
}