我已经做了一段时间了,运气不好。
我正在从Spring 3.2.9升级到4.2.6。我的第一步是升级到cxf核心3.1.6,这对应用程序没有任何问题。
不过,在升级所有spring依赖项时,我遇到了拦截器设置的问题。以下是基本信息:
拦截器
public class MyInterceptor extends AbstractPhaseInterceptor<Message>{
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(MyInterceptor.class);
public MyInterceptor() {
super(Phase.PRE_INVOKE);
addAfter(HolderInInterceptor.class.getName());
}
@PostConstruct
public void display() {
logger.warn(this.getPhase());
}
@Override
public void handleMessage(Message message) throws Fault {
....
cxfContext.xml
<bean id="contentInInterceptor" class="com.MyInterceptor">
</bean>
<cxf:bus>
<cxf:inInterceptors>
<ref bean="contentInInterceptor"/>
</cxf:inInterceptors>
</cxf:bus>
以及它被添加到web.xml中。当运行时,我看到记录的信息显示拦截器是用预调用阶段创建的(我添加这个是为了验证我没有疯掉)。但在调用服务时,PhaseInterceptor链会跳过拦截器,因为它没有声明阶段:
日志:
2016-05-31 16:08:28208〔localhost-startStop-1〕〔〕警告c.MyInterceptor-预调用
2016年5月31日16:10:14552[http-bio-8080-exec-1][]警告o.a.c.p.PhaseInterceptor Chain-正在跳过拦截器com.MyInterceptor$$EnhancerBySpringCGLIB$$1afa70e1:阶段声明缺少。
这是在拦截jaxws服务器调用。同样,我所做的改变导致了这些问题,就是更新到最新版本的Spring。cxf似乎使用了一个从未从bean生成的独立拦截器。
编辑
我相信我已经发现了这个问题,但我再次不确定修复方法在哪里。Spring 4代理在创建代理时不会调用构造函数两次(即,它使用构造函数创建原始bean,但CGLIB创建的bean代理不调用构造函数)。这会导致拦截器的阶段为null。
我在课堂上更改了@PostContsruct以确认这一点:
@PostConstruct
public void display() {
logger.warn(this.getPhase());
MyInterceptor myInterceptor = (MyInterceptor) appContext.getBean("contentInInterceptor");
logger.warn("Bean phase is: " + myInterceptor.getPhase());
}
日志显示bean的创建阶段与代理的阶段:
2016-06-01 10:36:52829〔localhost-startStop-1〕〔〕WARN c.MyInterceptor-预调用
2016-06-01 10:36:52839〔localhost-startStop-1〕〔〕WARN c.MyInterceptor-Bean阶段为:空
好吧,我现在已经找到了解决这个问题的方法,但它不是最好的实现。
基本上,我最终要做的是创建一个实现PhaseInterceptor的抽象类,并且所有这些实现的方法都被设置为抽象的。
然后,我的拦截器从那个类扩展而来,并有自己的phase/id/fore/after变量。当变量在bean的直接类中不可用时,Spring的bean代理设置似乎存在问题。至少这就是我在这个案例中的发现。
同样,不确定这是否是最好的解决方案,但这会使拦截器再次工作。
您说过拦截器正在拦截jaxws服务器调用。所以我的假设是,这是一个呼出电话。
Phase.PRE_INVOKE
用于传入消息。对传出消息使用其他阶段,如Phase.PRE_STREAM
有关阶段文件,请参阅
http://cxf.apache.org/docs/interceptors.html