如何覆盖 cxf MessageSenderEndingInterceptor 并控制 handleMessage 方法

How to override the cxf MessageSenderEndingInterceptor and take control over handleMessage method

我使用 jaxws:client 标签和 spring 来使用网络服务。 在上面的过程中,我想在调用一个webservice之前和之后使用cxf拦截器。

iam 能够与 cxf 拦截器一起工作,web 服务返回正确的 soap 错误和成功响应,但 inFaultInterceptor 在以下情况下不会被调用 Http 状态代码:404 还有当服务中断时...连接异常..

分析错误后..我发现从 https://cxf.apache.org/javadoc/latest/org/apache/cxf/interceptor/MessageSenderInterceptor.MessageSenderEndingInterceptor.html

 /**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
  * regarding copyright ownership. The ASF licenses this file
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License. You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */

 package org.apache.cxf.interceptor;

 import java.io.IOException;
 import java.util.ResourceBundle;

 import org.apache.cxf.common.i18n.BundleUtils;
 import org.apache.cxf.message.Exchange;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.transport.Conduit;

 /**
  * Takes the Conduit from the exchange and sends the message through it.
  */
  public class MessageSenderInterceptor extends AbstractPhaseInterceptor<Message> {
  private static final ResourceBundle BUNDLE = BundleUtils.getBundle(MessageSenderInterceptor.class);
  private MessageSenderEndingInterceptor ending = new MessageSenderEndingInterceptor();


  public MessageSenderInterceptor() {
       super(Phase.PREPARE_SEND);
  }

  public void handleMessage(Message message) {
      try {
           getConduit(message).prepare(message);
      } catch (IOException ex) {
        throw new Fault(new org.apache.cxf.common.i18n.Message("COULD_NOT_SEND", BUNDLE), ex);
         }    

          // Add a final interceptor to close the conduit
          message.getInterceptorChain().add(ending);
   }

      public class MessageSenderEndingInterceptor extends AbstractPhaseInterceptor<Message> {
        public MessageSenderEndingInterceptor() {
              super(Phase.PREPARE_SEND_ENDING);
          }

    public void handleMessage(Message message) throws Fault {
            try {
                getConduit(message).close(message);
            } catch (IOException e) {
                throw new Fault(new org.apache.cxf.common.i18n.Message("COULD_NOT_SEND", BUNDLE), e);
                }
        }
        }

    private Conduit getConduit(Message message) {
        Exchange exchange = message.getExchange();
        Conduit conduit = exchange.getConduit(message);
        if (conduit == null
            && (exchange.getOutMessage() != null
                || exchange.getOutFaultMessage() != null)) {
            conduit = OutgoingChainInterceptor.getBackChannelConduit(message);
        }
        return conduit;
    }

 }

我的问题:如何在我们的项目中覆盖这个class,以便可以自定义内部class的handleMessage? 在抛出无法发送消息的 cxf 故障之前,我必须在故障拦截器中获得控制...

您可以使用添加到 CXF 总线的 FaultListener。侦听器还将捕获 http 异常(例如 404),允许您在代码引发调用方法之前执行代码。

例如

public class CxfFaultListenerImpl implements FaultListener{
    public boolean faultOccurred(final Exception exception,final String description,final Message message) {

        //return false to avoid standard CXF logging of exception
        return false;
    }
}

Spring CXF 配置

<cxf:bus>
 <cxf:properties>
    <entry key="org.apache.cxf.logging.FaultListener">
        <bean id="cxfFaultListener" class="CxfFaultListenerImpl" />
    </entry>
 </cxf:properties>
</cxf:bus>