一 编写服务端
1 编写接口,在接口上面有@webService注解,表示该类是webService,接口里面方法注解为@webMethod,表示该方法是webService的方法
2 编写接口的实现类
3 编写拦截器,继承AbstractPhaseInterceptor类,实现handleMessage方法,在该方法里面实现拦截器的业务逻辑,在这里我实现的是如果客户端sopa消息传递用户名是wl,密码是1985310就是认证通过的客户端,可以继续向下执行,否则抛出异常,Phase这个类有很多常量,表示在服务器端的各个阶段拦截。
package com.atguigu.day01_ws.ws.auth;
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.Node;
import org.w3c.dom.NodeList;
//PhaseInterceptor 可以指定拦截器在哪个阶段起作用
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public AuthInterceptor() {
super(Phase.PRE_INVOKE);//调用之前拦截soap消息
}
@Override
public void handleMessage(SoapMessage msg) throws Fault {
System.out.println("服务端拦截器="+msg);
List<Header>headers= msg.getHeaders();
if( headers==null||headers.size()<=0){
throw new Fault(new IllegalArgumentException("没有header 不能调用"));
}
Header firstHeader=headers.get(0);
Element ele=(Element)firstHeader.getObject();
NodeList userIds= ele.getElementsByTagName("userId");
NodeList passwards= ele.getElementsByTagName("password");
System.out.println("用户名个数="+userIds.getLength());
System.out.println("密码个数="+passwards.getLength());
if(userIds.getLength()!=1 || passwards.getLength()!=1 ){
throw new Fault(new IllegalArgumentException("格式不对"));
}
String userId= userIds.item(0).getTextContent();
String passward= passwards.item(0).getTextContent();
System.out.println("用户名="+userId);
System.out.println("密码="+passward);
if(!"wl".equals(userId)||!"1985310".equals(passward) ){
throw new Fault(new IllegalArgumentException("用户名或者密码不对"));
}
}
}
4 运行服务端,并设置该拦截器
设置服务器端入拦截器
List<Interceptor<? extends Message>> inInterceptors =endpointImpl.getInInterceptors();
inInterceptors.add(new AuthInterceptor());
二 编写客户端
1 根据wsdl 生成客户端代码,左边是生成的客户端代码
2 编写客户端拦截器,在发送soap消息之前,把用户名和密码塞到soap消息的头部,在准备发送soap消息的时候进行拦截
package com.atguigu.day01_ws.ws.auth;
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;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
//PhaseInterceptor 可以指定拦截器在哪个阶段起作用
public class AddHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private String userId;
private String password;
public AddHeaderInterceptor(String userId,String password) {
super(Phase.PREPARE_SEND);//准备发送soap消息的时候
this.userId=userId;
this.password=password;
}
@Override
public void handleMessage(SoapMessage msg) throws Fault {
System.out.println("客户端拦截器"+msg);
List<Header>headers= msg.getHeaders();
Document doc=DOMUtils.createDocument();
Element ele=doc.createElement("authHeader");
Element idEle=doc.createElement("userId");
idEle.setTextContent(userId);
Element passwordEle=doc.createElement("password");
passwordEle.setTextContent(password);
ele.appendChild(idEle);
ele.appendChild(passwordEle);
headers.add(new Header( new QName("www.xxx") ,ele));
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3 运行客户端,并设置出拦截器
运行结果
服务端打印出用户名和密码信息,证明客户端传递了用户名和密码
客户端打印出消息
用tcp监控得到客户端传递的消息,确实是传递了用户名和密码
cxf的拦截器成功。