【问题标题】:How can I prevent Apache CXF from sending a response message?如何防止 Apache CXF 发送响应消息?
【发布时间】:2011-11-21 22:53:08
【问题描述】:

如果给定的 SOAP 标头元素具有给定的值(例如,如果标头标记“响应”的值为“0”),我根本不希望 Apache CXF 返回响应。

我该怎么做? CXF 似乎假设所有调用都会收到响应。

(我知道这在 Web 服务上下文中看起来很奇怪,但如果您的传输是 JMS,它似乎不那么奇怪)。

【问题讨论】:

    标签: java web-services jms cxf


    【解决方案1】:

    我已经能够使用一个中止拦截器链的拦截器来做到这一点。

    我已经使用 HTTP 配置(WebSphere 返回空的 200)和 ActiveMQ 配置(没有响应返回响应队列)对此进行了测试。

    package my.super.interceptor;
    
    public final class Suppressor extends AbstractSoapInterceptor {
    
       public Suppressor() { super(Phase.SETUP); }
    
       @Override
       public void handleMessage(final SoapMessage message) throws Fault        
       {                       
    
         final boolean suppressResponse = this.suppressResponse(message);
    
         if(suppressResponse) {
             log.debug("-> Suppressing response");
             message.getInterceptorChain().abort();
         }
    
       //if you want to suppress both responses and faults, you need
       //to check them separately. 
       //Change this code to check headers for whatever criteria you want
       //(Note you may need to change the super(Phase...) )
       //The code's a bit messy here - just sketching out the idea for the answer
       private boolean suppressResponse(final Message message) {            
         final Fault fault = (Fault)message.getContent(Exception.class);
    
         if(fault != null) {
            final String faultMessage = fault.getMessage();
    
             return faultMessage.indexOf("Something-you-want-to-match") > 0;
    
         } else {
            final MessageInfo messageInfo = (MessageInfo)message.get("org.apache.cxf.service.model.MessageInfo");            
            final String operation = messageInfo.getOperation().getOutputName();            
    
            return operation.indexOf("Something-you-want-to-match") > 0;
         }
       }
    

    还有你的 applicationContext.xml:

    <jaxws:endpoint ...>
      <jaxws:outInterceptors>
         <bean class="my.super.interceptor.Suppressor"/>
       </jaxws:outInterceptors>
       <jaxws:outFaultInterceptors>
         <bean class="my.super.interceptor.Suppressor"/>
       </jaxws:outFaultInterceptors>
    </jaxws:endpoint>
    

    【讨论】:

      【解决方案2】:

      详细解释:从 SOAP 协议规范的角度考虑 SOAP Web 服务。 Web 服务不仅仅是 HTTP 之上的一个花哨的层,它实际上是一种描述双向通信的方式,实现了各种message exchange patterns。以下是最常见的模式:

      • request-response (In-Out):在 HTTP 环境中,这是一个典型的 HTTP 请求/响应调用,其中一些请求 message 从客户端发送到服务器和一些响应 message 被发回。在 JMS 环境中,您会收到两条独立且独立的消息。

      • 单向(In-Only):在此模型中,客户端发送请求但不期望也不关心响应。在 JMS 中,它相当于发送给代理的简单消息。另一方面,在 HTTP 中(至少这是在 Apache CXF 中实现单向方法的方式),您将在 SEI 上获得 void 方法。而且,CXF默认会使用一个单独的线程池来处理这个请求,所以客户端甚至不等待响应,服务器甚至无法发送响应(因为客户端可能已经断开连接)。

      现在是重要的部分:在 WSDL 中,您可以将方法定义为请求/响应(通过定义输入/输出消息)或单向(通过仅提供消息)。这在服务合同中是固定的。您不能创建一个方法一旦返回响应(out message 准确地说)而其他时候则不返回。

      显然你可以定义一个可以为空或包含一些内容的 out 消息,但你仍然需要返回一些东西。

      简短说明:SOAP 协议不够灵活,无法满足您的要求。您要么返回响应,要么不返回。创建两个方法并选择在客户端调用哪一个,而不是添加自定义标头。

      另一个提示:您可以使用 ESB 执行某种转换,以便在存在某些 SOAP 标头时丢弃响应。

      【讨论】:

      • 我考虑过使用重复的操作定义(请求-响应定义和单向定义),但这不能很好地扩展到数十或数百个服务(它会使您的服务数量翻倍必须实施)。
      • 我也考虑过基于 ESB 的解决方案,但重点是消除发布响应的额外开销。我仍然会将响应推送到 ESB 层,只是为了丢弃它们。
      【解决方案3】:

      对于您的特定场景,我认为正确的实现方法是使用两个操作。一个用于仅输入,另一个用于输入输出。

      您尝试实现它的方式也可能会导致客户端出现问题。现在客户端必须根据请求决定是否寻找响应。另一方面,由于该决定是根据客户端在客户端发送的值做出的,因此它可以决定调用仅输入或输入输出操作。

      【讨论】:

        【解决方案4】:

        @Jared:我基本同意 Tomasz 的解释。我能想到的一种解决方法可以说是否使用 ws-addressing。 ws-addressing 允许您指定&lt;ReplyTo&gt; and &lt;To&gt;。所以基本上,在您不希望将响应发送给已请求的客户端的情况下,服务器端代码可以更改 replyTo 字段的值并可以将响应发送到虚拟 URI。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多