拦截器这个概念基本上都已经熟悉了,本文要讲的CXF拦截器就是在客户端调用前拦截,以及调用服务端方法前拦截。因为考虑两个应用互相掉接口的权限和安全性问题,服务端要验证是否合理才传递东西给客户端,所以客户端可以把一些服务端需要的东西配置xml传递过去。
常用的一些拦截器,需要配置,比如日志,客户端分输出的和输入的,服务端分输入的和输出的,另外把服务端pom文件的依赖copy到客户端去。除了已经有的我们还可以自定义拦截器,比如客户端我们写一个拦截器在请求发出前我们配置一些服务端要验证的东西比如权限,服务端也写一个在请求到达后调用接口方法时验证,验证通过我们就返回数据给客户端。
1:服务端接口暴露方法
package com.qqw.webserviceImpl;
import javax.xml.ws.Endpoint;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import com.qqw.interceptor.MyInterceptor;
import com.qqw.webservice.HelloWorld;
public class Server {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("ws is start");
HelloWorld hwHelloWorld=new HelloWorldImpl();
String address="http://172.16.10.123/helloWorld";
//Endpoint.publish(address, hwHelloWorld);
JaxWsServerFactoryBean factoryBean=new JaxWsServerFactoryBean();
factoryBean.setAddress(address);
factoryBean.setServiceClass(HelloWorld.class);
factoryBean.setServiceBean(hwHelloWorld);
factoryBean.getInInterceptors().add(new MyInterceptor());
factoryBean.getInInterceptors().add(new LoggingInInterceptor());//添加in日志拦截器
factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());//添加out日志拦截器
factoryBean.create();
System.out.println("ws is started");
}
}
2:服务端的自定义拦截器
package com.qqw.interceptor;
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;
public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public MyInterceptor() {
super(Phase.PRE_INVOKE);//在调用接口方法之前拦截
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers = message.getHeaders();
if(headers==null || headers.size()==0){
throw new Fault(new IllegalArgumentException("没有Header,拦截器实施拦截"));
}
Header header = headers.get(0);
Element ele = (Element) header.getObject();
NodeList uNode = ele.getElementsByTagName("userName");
NodeList pNode = ele.getElementsByTagName("passWord");
if(uNode.getLength()!=1){
throw new Fault(new IllegalArgumentException("用户名格式不对"));
}
if(pNode.getLength()!=1){
throw new Fault(new IllegalArgumentException("密码格式不对"));
}
if(!uNode.item(0).getTextContent().equals("qqw") || !pNode.item(0).getTextContent().equals("123456")){
throw new Fault(new IllegalArgumentException("用户名或密码错误"));
}
}
}
3:客户端的调用
package com.qqw.webservice;
import java.util.List;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import com.qqw.interceptor.AddHeaderInterceptor;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HelloWorldService hService=new HelloWorldService();
HelloWorld helloWorld = hService.getHelloWorldPort();
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(helloWorld);
client.getOutInterceptors().add(new LoggingOutInterceptor());//out日志
client.getInInterceptors().add(new LoggingInInterceptor());//in日志
client.getOutInterceptors().add(new AddHeaderInterceptor("qqw","123456")); // 添加自定义拦截器
User user=new User();
user.setName("qqw1");
List<Role> roleList = helloWorld.getUserRole(user);
for(int i=0;i<roleList.size();i++){
System.out.println("编号:"+roleList.get(i).getId()+"/角色名称:"+roleList.get(i).getName());
}
MyRoleArray map = helloWorld.getMap();
List<MyRole> list = map.item;
for(int i=0;i<list.size();i++){
System.out.print(list.get(i).getKey()+":");
for(Role r:list.get(i).getValue()){
System.out.print(r.getId()+","+r.getName());
}
System.out.println("================");
}
}
}
4:客户端的自定义拦截器
package com.qqw.interceptor;
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 userName;
private String passWord;
public AddHeaderInterceptor(String userName,String passWord) {
super(Phase.PREPARE_SEND);//准备调用前调用
this.userName=userName;
this.passWord=passWord;
}
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers = message.getHeaders();
Document document = DOMUtils.createDocument();
Element element = document.createElement("authHeader");
Element uelement = document.createElement("userName");
uelement.setTextContent(userName);
Element pelement = document.createElement("passWord");
pelement.setTextContent(passWord);
element.appendChild(uelement);
element.appendChild(pelement);
headers.add(new Header(new QName("qqw"), element));
}
}
5:查看控制台
(1)服务端的发布(服务端日志)
(2)客户端调用(客户端日志)
可以看到客户端在准备调服务端接口前,拦截器起了作用,把用户名和密码写进了document里面通过xml形式传递过去,服务端验证后把数据再次以xml形式返回过来
(3)服务端的日志
可以看到服务端先把传过来的用户名和密码解析,合理后把数据以xml形式传给客户端。同理如果用户名或密码错误,服务端和客户端会提示自定义的异常信息。至此CXF的拦截器完毕。