1. 使用CXF提供的拦截器
拦截器在我看来分为两端两向,两端分为:客户端和服务端,两向(方向)分为:进(in)和出(out),即大致四类拦截器。
在这里利用cxf提供的 日志拦截器举例
1.1 在服务端的发布类中获取所有拦截器,在 in 和 out两个方向(即调用和返回的过程) 添加日志拦截器
package com.lonely.server.impl; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; import com.lonely.server.HelloWs; public class ReleaseClient { public static void main(String[] args) { System.out.println("WS 服务端 start~~~~~~"); String address = "http://localhost:8090/sayhello"; HelloWs helloWs = new HelloWsImpl(); JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean(); // 设置地址 jaxWsServerFactoryBean.setAddress(address); // 设置接口 jaxWsServerFactoryBean.setServiceClass(HelloWs.class); // 设置实现类 jaxWsServerFactoryBean.setServiceBean(helloWs); // 添加 in 日志拦截器 jaxWsServerFactoryBean.getInInterceptors().add(new LoggingInInterceptor()); // 添加 out 日志拦截器 jaxWsServerFactoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); jaxWsServerFactoryBean.create(); System.out.println("WS 服务端 started~~~~~~~"); } }1.2 启动发布
1.3 在客户端的发布类中获取所有拦截器,在 in 和 out两个方向(即调用和返回的过程) 添加日志拦截器
在客户端需要借用 ClientProxy 创建 Client来获取所有拦截器,具体代码如下
package com.lonely.client; import java.util.List; import org.apache.cxf.endpoint.Client; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import com.lonely.server.HelloWs; import com.lonely.server.HelloWsService; import com.lonely.server.MyClass; import com.lonely.server.MyClassArray; import com.lonely.server.User; public class HelloInvoking { public static void main(String[] args) { HelloWsService helloWsService = new HelloWsService(); HelloWs helloWs = helloWsService.getHelloWsPort(); // System.out.println(helloWs.sayHelloWs("dugu")); /* * Clazz clazz = new Clazz(); clazz.setClassId(1); List<User> list = * helloWs.findUsersByClassId(clazz); for (User user : list) { * System.out.println(user.getUsername() + ":" + user.getClassId()); } */ // 获取 Client对象,来获取拦截器 Client client = ClientProxy.getClient(helloWs); // 添加 in 日志拦截器 client.getInInterceptors().add(new LoggingInInterceptor()); // 添加 out 日志拦截器 client.getOutInterceptors().add(new LoggingOutInterceptor()); MyClassArray myClassArray = helloWs.findAllUsers(); List<MyClass> list = myClassArray.getItem(); for (MyClass myClass : list) { System.out.println("班级:" + myClass.getKey()); List<User> users = myClass.getValue(); for (User user : users) { System.out.println(" 学生:" + user.getUsername()); } } } }1.4 运行看效果,至此,cxf提供的拦截器 配置完成,下面是 自定义拦截器配置
2. 自定义拦截器的配置使用
在这里通过该demo可以实现身份的验证,只有身份验证通过才可以成功调用方法成功。
2.1 在服务器端 配置一个 in 的 自定义身份验证拦截器,拦截所有请求,获取其身份信息进行验证
package com.lonely.intercepter; 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; public class MyIntercepter extends AbstractPhaseInterceptor<SoapMessage> { public MyIntercepter() { // 在调用方法之前拦截 super(Phase.PRE_INVOKE); } @Override public void handleMessage(SoapMessage message) throws Fault { // 1. 获取拦截器,这里就假设只有一个拦截器 List<Header> headers = message.getHeaders(); if (headers == null || headers.size() == 0) { throw new IllegalArgumentException("没有获取到表头信息"); } Header header = headers.get(0); // 2. 获取元素 Element element = (Element) header.getObject(); NodeList uNodeList = element.getElementsByTagName("userName"); NodeList cNodeList = element.getElementsByTagName("classId"); Node uNode = uNodeList.item(0); String userName = uNode.getTextContent(); Node cNode = cNodeList.item(0); String classId = cNode.getTextContent(); // 3.验证 if (!userName.equals("aa") || !classId.equals("1")) { throw new IllegalArgumentException("用户名或密码错误"); } } }2.2 在 发布类中 添加该 拦截器
// 在调用方法之前验证身份,创建一个身份验证的 in 拦截器 jaxWsServerFactoryBean.getInInterceptors().add(new MyIntercepter());
2.3 启动发布
2.4 在客户端 配置一个调用webservice服务前 的拦截器,作用在于 在调用前把身份信息封装到 soap的header信息中
package com.lonely.intercepter; 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 AuthIntercepter extends AbstractPhaseInterceptor<SoapMessage> { private String userName; private String classId; public AuthIntercepter(String userName, String classId) { // 发起调用前 super(Phase.PREPARE_SEND); this.userName = userName; this.classId = classId; } /** * 调用服务端方法前 将身份信息封装到soap中,服务端拦截器拦截获取信息验证 */ @Override public void handleMessage(SoapMessage message) throws Fault { // 获取soap表头信息 List<Header> headers = message.getHeaders(); // 1.创建document和元素 Document document = DOMUtils.createDocument(); Element authEle = document.createElement("authInfo"); Element uEle = document.createElement("userName"); Element cEle = document.createElement("classId"); // 2.赋值 uEle.setTextContent(userName); cEle.setTextContent(classId); authEle.appendChild(uEle); authEle.appendChild(cEle); // 3. 添加到headers中 headers.add(new Header(new QName("auth"), authEle)); } }2.5 在客户端的 测试类中,添加 该 out 拦截器
// 添加 out 自定义身份验证拦截器 client.getOutInterceptors().add(new AuthIntercepter("aa", "1"));2.6 调用测试,分别 正确和错误都演示一边
成功调用
身份错误,调用失败
2.7 至此,拦截器使用demo 完成