Web Service学习之七:CXF拦截器
一、用途
CXF拦截器类似Struts2的拦截器,后者是拦截和处理请求,前者是对发送和接收的sope消息进行处理,一般用于WS请求响应中的权限验证、日志记录,Soap消息处理,消息的压缩处理等;
这个拦截器可以直接访问和修改sope消息。
拿权限验证举例:
二、服务端添加拦截器
三种方式:JaxWsServerFactoryBean、Endpoint都可以通过getInInterceptors方法,向WebService服务添加拦截器,还可以自定义拦截器
1、Endpoint方式
- package ws;
- import javax.xml.ws.Endpoint;
- import org.apache.cxf.interceptor.LoggingInInterceptor;
- import org.apache.cxf.interceptor.LoggingOutInterceptor;
- import org.apache.cxf.jaxws.EndpointImpl;
- import ws.impl.HelloWordImpl;
- public class ServerMain
- {
- public static void main(String[] args)
- {
- HelloWordI hw = new HelloWordImpl();
- EndpointImpl ep = (EndpointImpl)Endpoint.publish("http://192.168.0.105/test", hw);
- //添加In拦截器
- ep.getInInterceptors().add(new LoggingInInterceptor());
- //添加Out拦截器
- ep.getOutInterceptors().add(new LoggingOutInterceptor());
- System.out.println("WebService 暴露成功!");
- }
- }
2、JaxWsServerFactoryBean方式
- package ws;
- import org.apache.cxf.interceptor.LoggingInInterceptor;
- import org.apache.cxf.interceptor.LoggingOutInterceptor;
- import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
- import ws.impl.HelloWordImpl;
- public class ServerMain
- {
- public static void main(String[] args)
- {
- HelloWordImpl hw = new HelloWordImpl();
- //EndpointImpl ep = (EndpointImpl)Endpoint.publish("http://192.168.0.105/test", hw);
- //添加In拦截器
- //ep.getInInterceptors().add(new LoggingInInterceptor());
- //添加Out拦截器
- //ep.getOutInterceptors().add(new LoggingOutInterceptor());
- JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
- factory.setAddress("http://192.168.0.105/test");
- factory.setServiceClass(HelloWordI.class);
- factory.setServiceBean(hw);
- factory.getInInterceptors().add(new LoggingInInterceptor());
- factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.create();- System.out.println("WebService 暴露成功!");
- }
- }
以上两种方式 实现了接口InterceptorProvider:拦截器链InterceptorChain由许多Interceptor组成,Cxf中定义了一个接口InterceptorProvider,通过该接口可以获取到与当前对象绑定的拦截器链里面的所有拦截器,当我们需要往某对象现有的拦截器链里面添加拦截器的时候我们就可以往通过InterceptorProvider获取到的对应拦截器列表中添加相应的拦截器来实现。InterceptorProvider的定义如下。
public interface InterceptorProvider {
List<Interceptor<?extends Message>>getInInterceptors();
List<Interceptor<?extends Message>>getOutInterceptors();
List<Interceptor<?extends Message>>getInFaultInterceptors();
List<Interceptor<?extends Message>>getOutFaultInterceptors();
}
3、创建自定义拦截器
CXF已经实现了很多种拦截器,很多已经在发布、访问Web 服务时已经默认添加到拦截器链。一般情况下, 我们自己的拦截器只要继承AbstractPhaseInterceptor<T extends org.apache.cxf.message.Message>类即可(也可以实现PhaseInterceptor<T>接口),这个类可以指定继承它的拦截器在什么阶段被启用,阶段属性可以通过org.apache.cxf.phase.Phase 中的常量指定值。
- package ws.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;
- /**
- * 类说明
- * @author wangjunyu
- * @createDate 2016-10-20 下午8:34:24
- * @version V1.0
- */
- public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage>
- {
//构造方法指定拦截器在什么地方生效
//Phase中常量指定生效位置 如PRE_INVOKE表示调用之前拦截
//RECEIVE 接收消息阶段有效 即使配置在OutInterceptor 的集合中也无效
- public AuthInterceptor()
- {
- super(Phase.PRE_INVOKE);
- }
- /**
- * 自定义拦截器需要实现handleMessage方法,该方法抛出Fault异常,可以自定义异常继承自Fault,
- * 也可以new Fault(new Throwable())
- */
- public void handleMessage(SoapMessage sope) throws Fault
- {
- System.out.println("开始验证用户信息!");
- List<Header> headers = sope.getHeaders();
- if (headers == null || headers.size() < 1)
- {
- throw new Fault(new IllegalArgumentException("找不到Header,无法验证用户信息"));
- }
- Header header = headers.get(0);
- Element el = (Element)header.getObject();
- NodeList users = el.getElementsByTagName("username");
- NodeList passwords = el.getElementsByTagName("password");
- if (users.getLength() < 1)
- {
- throw new IllegalArgumentException("找不到用户信息");
- }
- String username = users.item(0).getTextContent().trim();
- if (passwords.getLength() < 1)
- {
- throw new IllegalArgumentException("找不到用户密码");
- }
- String password = passwords.item(0).getTextContent().trim();
- //检查用户名和密码是否正确
- if(!"admin".equals(username) || !"admin".equals(password))
- {
- throw new Fault(new IllegalArgumentException("用户名或密码不正确"));
- }
- else
- {
- System.out.println("用户名密码正确允许访问");
- }
- }
- }
三、客户端添加拦截器
- package ws.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;
- /**
- * 类说明
- * @author wangjunyu
- * @createDate 2016-10-20 下午8:53:16
- * @version V1.0
- */
- public class ClientLoginInterceptor extends AbstractPhaseInterceptor<SoapMessage>
- {
- public ClientLoginInterceptor(String username, String password)
- {
- super(Phase.PREPARE_SEND);
- this.username = username;
- this.password = password;
- }
- private String username;
- private String password;
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public void handleMessage(SoapMessage soap) throws Fault
- {
- List<Header> headers = soap.getHeaders();
- Document doc = DOMUtils.createDocument();
- Element auth = doc.createElement("authrity");
- Element username = doc.createElement("username");
- Element password = doc.createElement("password");
- username.setTextContent(this.username);
- password.setTextContent(this.password);
- auth.appendChild(username);
- auth.appendChild(password);
- headers.add(0, new Header(new QName("tiamaes"),auth));
- }
- }
- package ws;
- import org.apache.cxf.endpoint.Client;
- import org.apache.cxf.interceptor.LoggingInInterceptor;
- import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
- import ws.interceptor.ClientLoginInterceptor;
- /**
- * 类说明
- * @author wangjunyu
- * @createDate 2016-7-10 上午11:24:09
- * @version V1.0
- */
- public class ClientMain {
- /**
- * 获取客户端的两种方式*/
- public static void main(String[] args)
- {
- /*
- HelloWordImpl hwproxy = new HelloWordImpl();
- HelloWordI hw= hwproxy.getHelloWordImplPort();
Client client = ClientProxy.getClient(hw);
client.getInInterceptors().add(new LoggingInInterceptor());
client.getOutInterceptors().add(new LoggingOutInterceptor());
- User a = new User();
- a.setName("哈哈");
- List<User> t = hw.getUsers(a);
- //System.out.println(t.get(0).getName());
- StringUser u = hw.getSecUsers();
- System.out.println(u.getValues().get(0).getValue().getName());
- System.out.println(u.getValues().get(1).getValue().getName());
- */
- JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
- Client client = dcf.createClient("http://192.168.0.104/test?wsdl");
- client.getInInterceptors().add(new LoggingInInterceptor());
- client.getOutInterceptors().add(new ClientLoginInterceptor("admin","admin"));
- try
- {
- Object[] objs = client.invoke("syaHello", "Tom");
- System.out.println(objs[0].toString());
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
四、SpringMVC中配置拦截器
1、cxf配置文件方式
1.1 单个拦截器配置
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
- xsi:schemaLocation=" http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
- <import resource="classpath:META-INF/cxf/cxf.xml" />
- <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
- <!-- 单个拦截器 -->
- <bean id="inMessageInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
- <bean id="outMessageInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
- <bean id="authorInterceptor" class="com.buss.app.interceptor.AuthInterceptor"/>
- <!-- 登录验证服务 -->
- <jaxws:endpoint id="LoginServiceI" implementor="com.buss.app.login.LoginServiceImpl" address="/LoginService">
- <!-- 输入日志拦截器 -->
- <jaxws:inInterceptors>
- <ref bean="inMessageInterceptor"/>
- <ref bean="authorInterceptor"/>
- </jaxws:inInterceptors>
- <!-- 输出日志拦截器 -->
- <jaxws:outInterceptors>
- <ref bean="outMessageInterceptor"/>
- </jaxws:outInterceptors>
- </jaxws:endpoint>
- <!-- APP首页服务 -->
- <jaxws:endpoint id="HomeServiceI" implementor="com.buss.app.home.HomeServiceImpl" address="/HomeService" />
- </beans>
1.2 捆绑拦截器打包配置
由于不光CXF内置有拦截器,而且还可以自定义拦截器。这样WebServcie的SEI可能配置多个、一大堆拦截器,这样很不方便。在Struts2中可以自定义拦截器,他还提供了自定义拦截器堆栈的功能,将多个拦截器捆绑在一起使用。这样不必要一个一个的去注册拦截器。在CXF中也有类似功能,可以将拦截器捆绑在一起,你就可以将它注册到你要使用的地方,而不必一个一个拦截器的注册使用。 实现拦截器的捆绑过程非常的简单,继承AbstractFeature 类来实现一个新的特征, 只需要覆盖initializeProvider 方法即可。其实Feature 就是将一组拦截器放在其中,然后一并注册使用。
具体如下:
首先定义一个捆绑拦截器类
- package com.buss.app.interceptor;
- import org.apache.cxf.Bus;
- import org.apache.cxf.feature.AbstractFeature;
- import org.apache.cxf.interceptor.InterceptorProvider;
- import org.apache.cxf.interceptor.LoggingInInterceptor;
- import org.apache.cxf.interceptor.LoggingOutInterceptor;
- public class PackageInterceptorFeature extends AbstractFeature
- {
- protected void initializeProvider(InterceptorProvider provider, Bus bus)
- {
- provider.getInInterceptors().add(new LoggingInInterceptor());
- provider.getInInterceptors().add(new AuthInterceptor());
- provider.getOutInterceptors().add(new LoggingOutInterceptor());
- }
- }
然后再在配置文件使用<jaxws:features>一起配置
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
- xsi:schemaLocation=" http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
- <import resource="classpath:META-INF/cxf/cxf.xml" />
- <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
- <!-- 登录验证服务 -->
- <jaxws:endpoint id="LoginServiceI" implementor="com.buss.app.login.LoginServiceImpl" address="/LoginService">
- <!-- 捆绑拦截器 -->
- <jaxws:features>
- <bean class="com.buss.app.interceptor.PackageInterceptorFeature"></bean>
- </jaxws:features>
- </jaxws:endpoint>
- <!-- APP首页服务 -->
- <jaxws:endpoint id="HomeServiceI" implementor="com.buss.app.home.HomeServiceImpl" address="/HomeService" />
- </beans>
2、注解配置拦截器
Cxf为四种类型的拦截器都提供了对应的注解,以方便用户直接在SEI上进行配置,对应的注解如下。
- org.apache.cxf.interceptor.InInterceptors
- org.apache.cxf.interceptor.InFaultInterceptors
- org.apache.cxf.interceptor.OutInterceptors
- org.apache.cxf.interceptor.OutFaultInterceptors
每个注解都对应有两个属性,String[]类型的interceptors和Class<? extends Interceptor<? extendsMessage>>[]类型的classes,其中interceptors用来指定需要配置的拦截器的全名称,而classes则用来指定需要配置的拦截器的类。以下是一个在SEI上通过@InInterceptor配置了入拦截器LogInterceptor的示例。
@InInterceptors(classes={LogInterceptor.class})
@WebService
public interface HelloWorld {
public String sayHi(String who);
}
如果在配置的时候既使用了classes属性配置,又使用了interceptors属性配置,那么两个配置都会生效。如下代码就相当于我们配置了两个自定义的拦截器LogInterceptor到HelloWorld服务的入拦截器链中。
@InInterceptors(classes={LogInterceptor.class}, interceptors={"com.tiantian.cxftest.interceptor.LogInterceptor"})
@WebService
public interface HelloWorld {
public String sayHi(String who);
}
使用注解的方式配置其它拦截器的方式是类似的。使用注解在服务端的SEI上配置的拦截器会作用在服务端,如果客户端与服务端不在一起,需要单独在客户端上配置拦截器,也可以直接在客户端对应的SEI上通过上述四个注解进行配置,方法是一样的。
五、常用内置拦截器
日志拦截器:LoggingInInterceptor 入拦截器日志 LoggingOutInterceptor 出拦截器日志
参考:
CXF-API http://cxf.apache.org/javadoc/latest/
http://elim.iteye.com/blog/2248620#_Toc431737706
http://yufenfei.iteye.com/blog/1688133
http://blog.csdn.net/jaune161/article/details/25602655
Web Service学习之七:CXF拦截器的更多相关文章
- Web Service学习-CXF开发Web Service实例demo(一)
Web Service是什么? Web Service不是框架.更甚至不是一种技术. 而是一种跨平台,跨语言的规范 Web Service解决什么问题: 为了解决不同平台,不同语言所编写的应用之间怎样 ...
- CXF拦截器(Interceptor)LoggingInInterceptor
Interceptor是CXF架构中一个重要的功能.你可以在不对核心模块进行修改的情况下,动态添加很多功能(你可以想象Struts2拦截器的优点).这对于CXF这个以处理消息为中心的服务框架来说是非常 ...
- springMVC学习(12)-使用拦截器
一.拦截器配置和测试: 1)定义两个拦截器,(要实现HandlerInterceptor接口) HandlerInterceptor1: package com.cy.interceptor; imp ...
- CXF 入门:创建一个基于SOAPHeader的安全验证(CXF拦截器使用)
CXF拦截器使用,创建一个使用SOAPHeader的安全验证xml格式: <soap:Header> <auth:authentication xmlns:auth="ht ...
- Web Service学习笔记:动态调用WebService
原文:Web Service学习笔记:动态调用WebService 多数时候我们通过 "添加 Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我 ...
- SpringMVC学习08(拦截器)
8.拦截器 概述 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.开发者可以自己定义一些拦截器来实现特定的功能. 过滤器与拦截器的区别: ...
- Web Service学习-CXF开发Web Service的权限控制(二)
Web Service怎样进行权限控制? 解决思路:server端要求input消息总是携带实username.password信息,假设没实username和password信息.直接拒绝调用 解决 ...
- Web Service学习之六:CXF解决无法处理的数据类型
CXF不能够处理像Map复杂的数据类型,需要单独转换处理. 总体思路:创建一个转换器和一个对应的可以处理的数据结构类型,将不能处理的类型转换成可以处理的类型: 步骤: 一.创建一个可以处理的类型 举例 ...
- CXF - 拦截器获取调用方法
没想到要弄这么一个东西. 起初只是想用interceptor记录一下webservice调用日志,后来却被要求在页面展示. 展示容易,但只是展示webservice的地址无法让用户从中明白什么. 那么 ...
随机推荐
- 创建高安全性PHP网站的几个实用要点
大家都知道PHP已经是当前最流行的Web应用编程语言了.但是也与其他脚本语言一样,PHP也有几个很危险的安全漏洞.所以在这篇教学文章中,我们将大致看看几个实用的技巧来让你避免一些常见的PHP安全问题. ...
- Support Library官方教程(2)各支援包的特性详介(含表)*
快速阅读 包名 作用 位置 是否有资源 v4 提供了最多的api <sdk>/extras/android/support/v4/ y Multidex 把DEX文件生成apk < ...
- npm在项目目录安装插件需要使用sudo
今天使用node的npm安装插件的时候遇到一个问题,那就是在项目目录里面安装插件的时候,必须使用超级用户(sudo)执行才会安装成功,否则会报如下错误: 以安装 gulp-uglify 为例 $ np ...
- 配置IIS服务器,APK文件下载
解决方法:在IIS的MIME类型中添加扩展名.apk,MIME类型application/vnd.android即可
- jQuery Ajax通用js封装
第一步:引入jQuery库 <script type="text/javascript" src="<%=path%>/resources/js/jqu ...
- Java [Leetcode 169]Majority Element
题目描述: Given an array of size n, find the majority element. The majority element is the element that ...
- 分析一下FastDFS_java_client中TestClient.java这个文件以及跟它关联的这条线
本来先打算上个图来说明一下这条线的,可是我的画图工具还没有安装好,我先把跟TestClient.java相关的几个文件代码贴上来,但是由于代码行数还是不少的,所以请大家阅读文章的时候先不要展开代码,等 ...
- <六>面向对象分析之UML核心元素之业务实体
一:基本概念
- <二>面向对象分析之几个关键的概念
一:建模 --->建模,是指通过对[客观事物]建立一种抽象的方法用以表征事物并获得对事物本身的理解.同时把这种理解概念化,将这些逻辑概念组织起来,构成一种对所观察对象的内部结构和工 ...
- HDU 5734 Acperience
Acperience Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...