一、用途

  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拦截器的更多相关文章

  1. Web Service学习-CXF开发Web Service实例demo(一)

    Web Service是什么? Web Service不是框架.更甚至不是一种技术. 而是一种跨平台,跨语言的规范 Web Service解决什么问题: 为了解决不同平台,不同语言所编写的应用之间怎样 ...

  2. CXF拦截器(Interceptor)LoggingInInterceptor

    Interceptor是CXF架构中一个重要的功能.你可以在不对核心模块进行修改的情况下,动态添加很多功能(你可以想象Struts2拦截器的优点).这对于CXF这个以处理消息为中心的服务框架来说是非常 ...

  3. springMVC学习(12)-使用拦截器

    一.拦截器配置和测试: 1)定义两个拦截器,(要实现HandlerInterceptor接口) HandlerInterceptor1: package com.cy.interceptor; imp ...

  4. CXF 入门:创建一个基于SOAPHeader的安全验证(CXF拦截器使用)

    CXF拦截器使用,创建一个使用SOAPHeader的安全验证xml格式: <soap:Header> <auth:authentication xmlns:auth="ht ...

  5. Web Service学习笔记:动态调用WebService

    原文:Web Service学习笔记:动态调用WebService 多数时候我们通过 "添加 Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我 ...

  6. SpringMVC学习08(拦截器)

    8.拦截器 概述 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.开发者可以自己定义一些拦截器来实现特定的功能. 过滤器与拦截器的区别: ...

  7. Web Service学习-CXF开发Web Service的权限控制(二)

    Web Service怎样进行权限控制? 解决思路:server端要求input消息总是携带实username.password信息,假设没实username和password信息.直接拒绝调用 解决 ...

  8. Web Service学习之六:CXF解决无法处理的数据类型

    CXF不能够处理像Map复杂的数据类型,需要单独转换处理. 总体思路:创建一个转换器和一个对应的可以处理的数据结构类型,将不能处理的类型转换成可以处理的类型: 步骤: 一.创建一个可以处理的类型 举例 ...

  9. CXF - 拦截器获取调用方法

    没想到要弄这么一个东西. 起初只是想用interceptor记录一下webservice调用日志,后来却被要求在页面展示. 展示容易,但只是展示webservice的地址无法让用户从中明白什么. 那么 ...

随机推荐

  1. Github欢乐多 PHP神级代码引发吐槽热

    前日,github的PHP板块惊现一段能够提升70%运行效率的代码,引发了全世界众多网友的吐槽和调侃,“awesome!”.“well done!”.“PHP是世界第一语言!”平时不苟言笑,埋头苦干的 ...

  2. nyoj-291 互素数个数 欧拉函数

    LK的数学题 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 LK最近遇到一个问题,需要你帮她一下.一个整数n,求[1,n)中,和n互素的数的个数.   输入 多组测 ...

  3. C#使用sharppcap实现网络抓包

    sharppcap dll的下载地址: http://sourceforge.net/directory/os:windows/?q=sharppcap 具体使用详细步骤: http://www.co ...

  4. CTO俱乐部下午茶:技术团队管理中的那些事儿

    摘要:"CTO下午茶"是一种有效的集体对话的模式,参加活动的成员在真诚互动和共同学习的宗旨下齐聚一堂,在喝茶聊天氛围下交流工作心得.本期"CTO下午茶"的主题是 ...

  5. Lucas定理学习小记

    (1)Lucas定理:p为素数,则有: (2)证明: n=(ak...a2,a1,a0)p = (ak...a2,a1)p*p + a0 =  [n/p]*p+a0,m=[m/p]*p+b0其次,我们 ...

  6. Android Touch事件分发机制

    参考:http://blog.csdn.net/xiaanming/article/details/21696315 参考:http://blog.csdn.net/wangjinyu501/arti ...

  7. 转 intent常用功能

    1.从google搜索内容Intent intent = new Intent();intent.setAction(Intent.ACTION_WEB_SEARCH);intent.putExtra ...

  8. tahoma字体对中文字的影响

    一提到tahoma字体大家都会想到,它是一个英文字体,对中文不会有影响. 但是今天就遇到一个问题,tahoma字体会影响中文字的显示,如: html代码: <div class="bo ...

  9. SGU 187 - Twist and whirl -- want to cheat

    原题地址:http://acm.sgu.ru/problem.php?contest=0&problem=187 太开心啦!!!!这道题从2013年开始困扰我!!今天晚上第四次下定决心把它写一 ...

  10. Akka的Actor模型及使用实例

    本文的绝大部分内容转载自rerun.me这一blog,老外写的东西就是好啊. ACTORS介绍 Anyone who has done multithreading in the past won't ...