(六) CXF 拦截器--自定义拦截器

来源:互联网 发布:可非止咳糖浆淘宝交易 编辑:程序博客网 时间:2024/05/18 00:18

【一 SOAP 消息简介】

      简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固化的信息。

      CXF 中自定义拦截器,其实就是对SOAP 消息的封装和解析。

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header>   不是强制出现的, head 元素的内容由程序员控制添加, 主要用于携带一些其它的信息</soap:Header><soap:Body> body 元素的内容总是默认的,但是有两种情况            1. 当webService 正确交互时,Body元素内容由WSDL 控制            2. 当WebService 交互错误时,body元素的内容将是Fault 元素</soap:Body></soap:Envelope>

【二  自定义权限拦截器】


    【1. 自定义SOAP 消息体】

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><user><username>zong</username><passwor>123456</passwor></user></soap:Header><soap:Body><ns2:sayByeBye xmlns:ns2="http://server.cxf.zgf.org/"><arg0>zong</arg0></ns2:sayByeBye></soap:Body></soap:Envelope>

 【2. 客户端出拦截器】

package org.zgf.cxf.interceptors;import javax.xml.namespace.QName;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;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.Document;import org.w3c.dom.Element;/** * 客户端拦截器:拦截客户端发出的SOAP 消息,然后在<SOAP:Header> 标签中添加自定义xml元素 * */public class UserOutInterceptor extends AbstractPhaseInterceptor<SoapMessage>{private String username;private String password;public UserOutInterceptor(String username, String password) {super(Phase.PRE_PROTOCOL);this.username = username;this.password = password;}@Overridepublic void handleMessage(SoapMessage soapMessage) throws Fault {try {//1. 用原生的w3c 的API 构建 <soap:header>中的一个 元素DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();Document document = documentBuilder.newDocument();Element userEle  = document.createElement("user");Element usernameEle = document.createElement("username");Element passwordEle = document.createElement("password");usernameEle.setTextContent(username);passwordEle.setTextContent(password);userEle.appendChild(usernameEle);userEle.appendChild(passwordEle);//2. 创建一个header,然后添加到当前的header列表中Header header = new Header(new QName("user"),userEle);soapMessage.getHeaders().add(header );} catch (ParserConfigurationException e) {e.printStackTrace();}}}

【3. 服务器端入拦截器】

package org.zgf.cxf.interceptors;import javax.xml.namespace.QName;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;/** * 服务器端拦截器:在消息到达服务器端时,拦截SOAP 消息,解析 <SOAP:Header> 元素中的指定元素 * 继承AbstractPhaseInterceptor * 消息类型:SOAP 消息 */public class UserInInterceptor extends AbstractPhaseInterceptor<SoapMessage> {public UserInInterceptor() {super(Phase.PRE_PROTOCOL);//准备协议化之前拦截 }@Overridepublic void handleMessage(SoapMessage soapMessage) throws Fault {String username;String password;//1. 解析用户名和密码,如果解析过程出错,证明请求参数格式不正确try {Header userHeader = soapMessage.getHeader(new QName("user"));//必须是  org.w3c.dom.ElementElement userElement = (Element) userHeader.getObject();username = userElement.getElementsByTagName("username").item(0).getTextContent();password = userElement.getElementsByTagName("password").item(0).getTextContent();} catch (Exception ex) {throw new Fault(new RuntimeException("请求参数格式不正确"));}//2. 验证用户名和密码if("zong".equals(username) && "123456".equals(password)){System.out.println("权限认证通过....");}else{throw new Fault(new RuntimeException("对不起,您的用户名或密码有误!"));}}}

【4. 服务器端启动】

package org.zgf.cxf.test.o3;import java.util.List;import javax.xml.ws.Endpoint;import org.apache.cxf.interceptor.Interceptor;import org.apache.cxf.interceptor.LoggingInInterceptor;import org.apache.cxf.interceptor.LoggingOutInterceptor;import org.apache.cxf.jaxws22.EndpointImpl;import org.apache.cxf.message.Message;import org.zgf.cxf.interceptors.UserInInterceptor;import org.zgf.cxf.server.HelloWordWS;/** * 测试 ws 服务器发布 */public class TestPublishServer {public static void main(String[] args) {//1. 设置发布地址:ip 需要为本机ip, 端口号为本机未被占用的端口号String address = "http://172.22.12.85:8180/ws/hellowordws";Endpoint endpoint = Endpoint.publish(address, new HelloWordWS());EndpointImpl endpointImpl = (EndpointImpl)endpoint;//2. 获取入拦截器列表,默认为null,并添加cxf提供的日志人拦截器List<Interceptor<? extends Message>> inInterCeptors = endpointImpl.getInInterceptors();inInterCeptors.add(new LoggingInInterceptor()); inInterCeptors.add(new UserInInterceptor()); //添加用户自定义拦截器//3. 获取出拦截器列表,默认为null,并添加cxf提供的日志出拦截器 List<Interceptor<? extends Message>> outInterCeptors = endpointImpl.getOutInterceptors();outInterCeptors.add(new LoggingOutInterceptor());System.out.println("web service 接口发布成功... ");}}

【5. 客户端访问】

package org.zgf.cxf.test.o3;import java.util.List;import org.apache.cxf.endpoint.Client;import org.apache.cxf.frontend.ClientProxy;import org.apache.cxf.interceptor.Interceptor;import org.apache.cxf.interceptor.LoggingInInterceptor;import org.apache.cxf.interceptor.LoggingOutInterceptor;import org.apache.cxf.message.Message;import org.zgf.cxf.client.HelloWordWSService;import org.zgf.cxf.client.IHelloWorldWS;import org.zgf.cxf.interceptors.UserOutInterceptor;public class Test_client {public static void main(String[] args) {//1. 创建服务代理工厂(继承 javax.xml.ws.Service 的类)HelloWordWSService hwws = new HelloWordWSService();//2. 创建服务代理IHelloWorldWS hws = hwws.getHelloWordWSPort();//3. 获取Client 对象Client client = ClientProxy.getClient(hws);//4. 获取入参拦截器列表,默认为null,添加cxf 自带的日志入拦截器List<Interceptor<? extends Message>> inInterCeptors = client.getInInterceptors();inInterCeptors.add(new LoggingInInterceptor());//5. 获取出拦截器列表,默认为null,添加cxf自带的日志出拦截器List<Interceptor<? extends Message>> outInterCeptors = client.getOutInterceptors();outInterCeptors.add(new UserOutInterceptor("zong", "1234ds56"));outInterCeptors.add(new LoggingOutInterceptor());String result = hws.sayByeBye("zong");System.out.println("result:" + result);}}

【6. 测试结果--客户端】

---------------------------ID: 1Address: http://172.22.12.85:8180/ws/hellowordwsEncoding: UTF-8Content-Type: text/xmlHeaders: {Accept=[*/*], SOAPAction=[""]}Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><user><username>zong</username><password>1234ds56</password></user></soap:Header><soap:Body><ns2:sayByeBye xmlns:ns2="http://server.cxf.zgf.org/"><arg0>zong</arg0></ns2:sayByeBye></soap:Body></soap:Envelope>--------------------------------------三月 15, 2016 3:24:55 下午 org.apache.cxf.services.HelloWordWSService.HelloWordWSPort.IHelloWorldWSINFO: Inbound Message----------------------------ID: 1Response-Code: 500Encoding: UTF-8Content-Type: text/xml;charset=UTF-8Headers: {Content-Length=[240], content-type=[text/xml;charset=UTF-8], Server=[Jetty(7.5.4.v20111024)]}Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>对不起,您的用户名或密码有误!</faultstring></soap:Fault></soap:Body></soap:Envelope>--------------------------------------Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: 对不起,您的用户名或密码有误!at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)at com.sun.proxy.$Proxy27.sayByeBye(Unknown Source)at org.zgf.cxf.test.o3.Test_client.main(Test_client.java:34)Caused by: org.apache.cxf.binding.soap.SoapFault: 对不起,您的用户名或密码有误!at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:75)at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:46)at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35)at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:114)at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69)at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:801)at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1679)at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1517)at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1425)at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:50)at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:188)at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:650)at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:462)at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:365)at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:318)at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:95)at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)... 2 more

【7. 总结】

    源码下载: WS-CXF.zip

0 0