CXF-使用interceptor处理Soap Headers
来源:互联网 发布:网络配线架说明书 编辑:程序博客网 时间:2024/06/05 15:28
最近需要对外提供 web service 服务,初步调研后决定采用 CXF 进行开发。CXF 是 apache 提供的开源框架,对 JAX-WS 标准的实现较为完整,并提供了与 spring 框架的集成,功能较为丰富。由于涉及到在 SOAP 头中传输身份验证信息,本文主要讲解如何通过 CXF 提供的 interceptor 来处理 SOAP 头中的数据。实际上, JAX-WS 规范的 Handler 也可以进行类似消息的处理,由于是标准中的定义,因此具有较强的通用性。但是在大部分情况下开发者其实并不太关注程序的可移植性,而且 CXF 的 interceptor 提供了更为丰富的功能,因此使用上较为广泛。相关 jar 包可以在这里下载,里面包含了 CXF 及其所依赖的各 jar 包。
服务端
下面是一个简单的 SEI(Service Endpoint Inteface),已经使用 JAX-WS 定义的标注将其暴露为一个 web service 接口:
@WebService(targetNamespace = "http://services.devsumo.com/cxfMessenger/v001")@XmlSeeAlso(AuthHeader.class)public interface CXFMessenger { @WebMethod String sendMessage( @WebParam(name="recipient") String recipient, @WebParam(name="messageContent") String messageContent);}
这里每一个请求都需要传入用户的用户名、密码进行校验,我们新建一个 AuthHeader 类:
@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "AuthHeader")public class AuthHeader { protected String username; protected String password; public String getusername() { return username; } public void setusername(String value) { this.username = value; } public String getpassword() { return password; } public void setpassword(String value) { this.password = value; }}
CXF 自己已经提供了许多功能强大的 Interceptor 以便开发者使用,不过这里我们使用 AbstracSoapInterceptor 类作为我们的基础类。AbstractSoapInterceptor 是其他 Interceptor 类的基类,为我们提供了基本的代码模板:
public class AuthInterceptor extends AbstractSoapInterceptor { public AuthInterceptor() { super(Phase.PRE_INVOKE); } @Override public void handleMessage(SoapMessage message) throws Fault { // TODO: Implement our header handling }}
这里我们有一个简单的 handlerMessage 函数需要实现。但在此之前,我们首先来关注填一下 Phase。在 CXF 中,各个 Interceptor 组成了 Interceptor Chains,CXF 将它们划分为几个阶段,用于精细化的控制各 interceptor 的执行时间。一个 interceptor 可以在请求刚刚被接收时执行,也就是说早于任何其他的解析或者编解码,这种情况比较适合端对端的性能监控。也可以让它在服务方法即将被调用时执行。后一种情况就是我们要使用的,在这里将 Phase 定义为 Phase.PRE_INVOKE。
handleMessage 的参数 SoapMessage 类有一个十分便捷的方法: getHeader ,其参数是一个 QName 对象,如果存在匹配此 QName 对象的 Header 的话则将其返回:
public class AuthInterceptor extends AbstractSoapInterceptor { private static final QName HEADER_TYPE = new QName("http://services.devsumo.com/cxfMessenger/v005", "AuthHeader"); public AuthInterceptor() { super(Phase.PRE_INVOKE); } @Override public void handleMessage(SoapMessage message) throws Fault { Header header = message.getHeader(HEADER_TYPE); if(header != null) { // TODO: process our header } }}
通过 Header 得到我们需要的数据不需要我们自己进行编解码,通过相关的 DataBinding,CXF 可以自动帮我们完成。得到所需数据后,就可以进行校验了:
@Overridepublic void handleMessage(SoapMessage message) throws Fault { Header header = message.getHeader(HEADER_TYPE); if (header == null) throws new Exception("无身份信息"); Service service = ServiceModelUtil.getService(message.getExchange()); DataReader<Node> dataReader = service.getDataBinding().createReader(Node.class); AuthHeader AuthHeader = (AuthHeader)dataReader.read(HEADER_TYPE, (Node)header.getObject(), AuthHeader.class); if (!AuthHeader.getUsername.equals("hello")) { throws new Exception("用户无权限"); } if (!AuthHeader.getPassword.equals("world")) { throws new Exception("密码错误"); }}
最后我们需要在 CXF 中对 interceptor 进行注册。Bus 为 CXF 的骨架类,提供了 CXF 运行时的资源共享,下面的配置使得此 Interceptor 对所有的服务接口生效:
<cxf:bus> <cxf:inInterceptors> <bean id="authInterceptor" class="com.devsumo.cxfmessenger.v005.AuthInterceptor"/> </cxf:inInterceptors></cxf:bus>
客户端
客户端可以使用如下代码将在请求信息中添加 Soap Header:
ApplicationContext cxt = new ClassPathXmlApplicationContext("classpath:applicationContext-client.xml"); CustomerService client = (CustomerService)cxt.getBean("customerServiceClient");AuthHeader authHeader = new AuthHeader();authHeader.setUsername("hello");authHeader.setPassword("world");Header header = new Header(new QName("http://services.devsumo.com/cxfMessenger/v001", "AuthHeader"), authHeader, new JAXBDataBinding(AuthHeader.class));List<Header> headers = new ArrayList<Header>();headers.add(header);((BindingProvider)client).getRequestContext().put(Header.HEADER_LIST, headers);
其中 Spring 配置文件内容如下。注意 serviceClass 属性的值为 SEI 接口的全限定名,address 属性的值为上述 WS 服务对外开放的 url。
<!-- 在客户端中,此接口类所在package可按需要放置 --><bean id="messenger" class="api.client.CXFMessenger" factory-bean="messengerClientFactory" factory-method="create"/> <bean id="messengerClientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="api.client.CXFMessenger"/> <property name="address" value="http://services.devsumo.com/cxfMessenger/v001/messenger"/></bean>
0 0
- CXF-使用interceptor处理Soap Headers
- CXF Logging Interceptor的使用
- 使用CXF Interceptor&Feature
- SOAP headers
- 使用 CXF 开发 SOAP 服务
- CXF拦截器(Interceptor)的使用
- 使用CXF 开发SOAP webservice 服务端实例
- 使用CXF和Spring发布Soap服务
- Adding SOAP headers【转】
- WebService 的Interceptor的使用以及SOAP消息形式
- apache cxf interceptor pre
- CXF中的Interceptor
- CXF Interceptor拦截器
- 使用 CXF、Spring、Maven 创建一个 SOAP 客户端
- 使用CXF框架发布SOAP格式的webservice
- 使用CXF 开发SOAP 的webService接口客户端
- 使用Apache CXF搭建基于SOAP的Web Service
- jaxws soap webservice 使用apache cxf tool ——wsdl2java
- vs使用任务快捷键
- 指针函数用法,参考u-boot1.1.6
- iOS 获取文件的目录路径的几种方法
- 路由器修改密码不懂的可以参考
- C程序设计week10作业
- CXF-使用interceptor处理Soap Headers
- iOS文件系统的管理
- Ubuntu 14.04 Android 使用Maven一 使用例子工程
- 究竟是测试重要,还是工程重要?
- ie网页分析(HttpWatch Pro) 中文版安装及使用方法
- 一文读懂大数据:Hadoop,大数据技术及相关应用
- centos中安装PyMongo库
- VC对字符串进行拆分
- Ant中SSH使用