CXF对Interceptor的支持

本文介绍了CXF Interceptor的基本概念及其使用方法。通过客户端和服务端的实际案例,展示了如何利用Interceptor进行请求和响应的日志记录,并自定义Interceptor来增强应用程序的功能。

CXF的Interceptor就和Axis的Handler的功能类似。在每个请求响应之前或响应之后,做一些事情。这里的Interceptor就和Filter、Struts的Interceptor很类似,提供它的主要作用就是为了很好的降低代码的耦合性,提供代码的内聚性。下面我们就看看CXF的Interceptor是怎么样工作的。

1、 我们就用上面的HelloWorldService,客户端的调用代码重新写一份,代码如下:

package com.hoo.client;
 
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.phase.Phase;
import com.hoo.interceptor.MessageInterceptor;
import com.hoo.service.IHelloWorldService;
 
/**
 * <b>function:</b>CXF WebService客户端调用代码
 * @author hoojo
 * @createDate 2011-3-16 上午09:03:49
 * @file HelloWorldServiceClient.java
 * @package com.hoo.client
 * @project CXFWebService
 * @blog http://blog.youkuaiyun.com/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class ServiceMessageInterceperClient {
    
    public static void main(String[] args) {
        //调用WebService
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(IHelloWorldService.class);
        factory.setAddress("http://localhost:9000/helloWorld");
        factory.getInInterceptors().add(new LoggingInInterceptor());
        factory.getOutInterceptors().add(new LoggingOutInterceptor());
        
        IHelloWorldService service = (IHelloWorldService) factory.create();
        System.out.println("[result]" + service.sayHello("hoojo"));
    }
}
上面的CXF的拦截器是添加在客户端,同样在服务器端也是可以添加拦截器Interceptor的。运行后结果如下:
2011-3-18 7:34:00 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
信息: Creating Service {http://service.hoo.com/}IHelloWorldServiceService from class com.hoo.service.IHelloWorldService
2011-3-18 7:34:00 org.apache.cxf.interceptor.AbstractLoggingInterceptor log
信息: Outbound Message
---------------------------
ID: 1
Address: http://localhost:9000/helloWorld
Encoding: UTF-8
Content-Type: text/xml
Headers: {SOAPAction=[""], Accept=[*/*]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns1:sayHello xmlns:ns1="http://service.hoo.com/"><name>hoojo</name></ns1:sayHello></soap:Body></soap:Envelope>
--------------------------------------
2011-3-18 7:34:01 org.apache.cxf.interceptor.AbstractLoggingInterceptor log
信息: Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {content-type=[text/xml;charset=UTF-8], Content-Length=[230], Server=[Jetty(7.2.2.v20101205)]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns1:sayHelloResponse xmlns:ns1="http://service.hoo.com/"><return>hoojo say: Hello World </return></ns1:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------
[result]hoojo say: Hello World 

上面的部分信息是LoggingInterceptor输出的日志信息,分别在请求和响应的时候输出日志信息,还有输出请求的时候参数的信息以及响应的时候返回值的信息。


2、 刚才是客户端添加Interceptor,现在我们自己编写一个Interceptor,这个Interceptor需要继承AbstractPhaseInterceptor,实现handleMessage和一个带参数的构造函数。然后在服务器端添加这个Interceptor。

Interceptor代码如下:

package com.hoo.interceptor;
 
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
 
/**
 * <b>function:</b> 自定义消息拦截器
 * @author hoojo
 * @createDate Mar 17, 2011 8:10:49 PM
 * @file MessageInterceptor.java
 * @package com.hoo.interceptor
 * @project CXFWebService
 * @blog http://blog.youkuaiyun.com/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class MessageInterceptor extends AbstractPhaseInterceptor<Message> {
    
    //至少要一个带参的构造函数
    public MessageInterceptor(String phase) {
        super(phase);
    }
 
    public void handleMessage(Message message) throws Fault {
        System.out.println("############handleMessage##########");
        System.out.println(message);
        if (message.getDestination() != null) {
            System.out.println(message.getId() + "#" + message.getDestination().getMessageObserver());
        }
        if (message.getExchange() != null) {
            System.out.println(message.getExchange().getInMessage() + "#" + message.getExchange().getInFaultMessage());
            System.out.println(message.getExchange().getOutMessage() + "#" + message.getExchange().getOutFaultMessage());
        }
    }
}
下面看看发布服务和添加自定义拦截器的代码:
package com.hoo.service.deploy;
 
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.phase.Phase;
import com.hoo.interceptor.MessageInterceptor;
import com.hoo.service.HelloWorldService;
 
/**
 * <b>function:</b>在服务器发布自定义的Interceptor
 * @author hoojo
 * @createDate 2011-3-18 上午07:38:28
 * @file DeployInterceptorService.java
 * @package com.hoo.service.deploy
 * @project CXFWebService
 * @blog http://blog.youkuaiyun.com/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class DeployInterceptorService {
 
    public static void main(String[] args) throws InterruptedException {
        //发布WebService
        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
        //设置Service Class
        factory.setServiceClass(HelloWorldService.class);
        factory.setAddress("http://localhost:9000/helloWorld");
        //设置ServiceBean对象
         factory.setServiceBean(new HelloWorldService());
        
        //添加请求和响应的拦截器,Phase.RECEIVE只对In有效,Phase.SEND只对Out有效
         factory.getInInterceptors().add(new MessageInterceptor(Phase.RECEIVE));
        factory.getOutInterceptors().add(new MessageInterceptor(Phase.SEND));
        
        factory.create();
        
        System.out.println("Server start ......");
        Thread.sleep(1000 * 60);
        System.exit(0);
        System.out.println("Server exit ");
    }
}

值得说的是,以前发布WebService是用Endpoint的push方法。这里用的是JaxWsServerFactoryBean和客户端调用的代码JaxWsProxyFactoryBean有点不同。
客户端调用代码:

package com.hoo.client;
 
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.hoo.service.IHelloWorldService;
 
/**
 * <b>function:</b>CXF WebService客户端调用代码
 * @author hoojo
 * @createDate 2011-3-16 上午09:03:49
 * @file HelloWorldServiceClient.java
 * @package com.hoo.client
 * @project CXFWebService
 * @blog http://blog.youkuaiyun.com/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class HelloWorldServiceClient {
    
    public static void main(String[] args) {
        //调用WebService
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(IHelloWorldService.class);
        factory.setAddress("http://localhost:9000/helloWorld");
        
        IHelloWorldService service = (IHelloWorldService) factory.create();
        System.out.println("[result]" + service.sayHello("hoojo"));
    }
}

The end.
since  http://www.cnblogs.com/hoojo/archive/2011/03/30/1999499.html 
writer hoojo




### Java 中 `org.apache.cxf.interceptor` 包不存在的解决方案 如果在开发过程中遇到 `org.apache.cxf.interceptor` 包缺失的问题,通常是因为项目中缺少 Apache CXF 的相关依赖项。以下是详细的分析和解决方法: #### 1. 检查 Maven 或 Gradle 配置 对于基于 Maven 构建的项目,确保项目的 `pom.xml` 文件中包含了以下依赖项: ```xml <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-core</artifactId> <version>3.4.7</version> <!-- 版本号可以根据实际需求调整 --> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.4.7</version> <!-- 确保版本一致 --> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>3.4.7</version> <!-- 确保版本一致 --> </dependency> ``` 如果是基于 Gradle 构建的项目,则应在 `build.gradle` 文件中添加如下内容: ```gradle implementation 'org.apache.cxf:cxf-core:3.4.7' implementation 'org.apache.cxf:cxf-rt-frontend-jaxws:3.4.7' implementation 'org.apache.cxf:cxf-rt-transports-http:3.4.7' ``` 这些依赖项提供了核心功能以及 JAX-WS 和 HTTP 支持,能够满足大多数场景下的 Web Service 调用需求。 #### 2. 使用正确的类路径加载机制 如果项目运行环境是 Spring Boot 或其他框架集成的应用程序,请确认已正确配置了类路径扫描范围。例如,在 Spring Boot 应用中可以通过以下方式引入 CXF 功能模块: ```java import org.apache.cxf.Bus; import org.apache.cxf.bus.spring.SpringBus; import org.springframework.context.annotation.Bean; @Configuration public class CxfConfig { @Bean public Bus springBus() { return new SpringBus(); } } ``` 此配置会初始化 CXF 总线并将其注册到 Spring 容器中[^1]。 #### 3. 排查网络或代理问题 当尝试下载 Maven 或 Gradle 所需的依赖时,可能会因为网络连接不稳定或者公司内部防火墙设置而导致失败。可以采取以下措施来解决问题: - **本地仓库缓存**:手动从中央仓库或其他可信源获取所需 jar 文件,并放置于 `.m2/repository/org/apache/cxf/...` 下对应的目录结构中。 - **镜像站点替换**:修改 `settings.xml` (位于用户主目录下的 `.m2` 文件夹内),指定国内可用的镜像地址作为默认源。例如阿里云 Nacos 提供的服务端口支持加速访问国外资源[^3]。 #### 4. 日志调试与验证 启用 CXF 的详细日志记录可以帮助定位具体错误发生的位置及其上下文信息。通过调整 logging.properties 文件中的级别至 FINER 或更高级别即可实现这一点。例如: ```properties org.apache.cxf.level=FINEST org.apache.cxf.logger=java.util.logging.ConsoleHandler ``` 完成以上操作后重新编译部署应用程序,观察控制台输出是否恢复正常行为模式[^2]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值