8

我有一个用于传入消息的自定义 SOAP 消息处理程序,这些消息将根据调用的操作运行不同的代码。我第一次尝试获取操作名称看起来像这样:

public boolean handleMessage(SOAPMessageContext context)
{
    String op = context.get(MessageContext.WSDL_OPERATION);
    ...

这失败了,因为该属性MessageContext.WSDL_OPERATION似乎从未被设置。然后我尝试使用这个:

public boolean handleMessage(SOAPMessageContext context)
{
    Map<?, ?> headers = (Map<?, ?>)context.get(MessageContext.HTTP_REQUEST_HEADERS);    
    ArrayList<String> SOAPAction = ((ArrayList<String>) headers.get("SOAPAction"));
    String opName = SOAPAction.get(0);
    //opName will be formatted like "urn#myOperation", so the prefix must be removed
    opName = ((opName.replace("\"","").split("#"))[1]);

这可行,但我担心可能存在未设置标头属性“SOAPAction”(或什至不存在)或不具有我期望的值的情况。我也有点担心,因为我不知道这是否是获取操作名称的“官方”方式——我是通过查看context调试器中的内容来弄清楚的。

在处理传入的 SOAP 消息时,有没有更好的方法来获取操作名称?

4

4 回答 4

5

我参加这个聚会很晚了,但在过去的一周里我试着这样做了。接受的答案实际上并不适用于每个 JAX-WS 实现(至少不是我尝试过的)。

我一直在尝试在我的开发环境中的独立 Metro 上进行这项工作,但也在真实环境中使用与 WebSphere 7 捆绑的 Axis2。

我在 Metro 上发现了以下作品:

String operationName = body.getChildNodes().item(0).getLocalName();

以及以下在 Axis2 上的工作:

String operationName = body.getChildNodes().item(1).getLocalName();

正在发生的事情是 Axis2 将类型节点Text作为第一个孩子插入到 Body 中,但 Metro 没有。此文本节点返回一个空本地名称。我的解决方案是执行以下操作:

NodeList nodes = body.getChildNodes();

// -- Loop over the nodes in the body.
for (int i=0; i<nodes.getLength(); i++) {
  Node item = nodes.item(i);

  // -- The first node of type SOAPBodyElement will be
  // -- what we're after.
  if (item instanceof SOAPBodyElement) {
    return item.getLocalName();
  }
}

如评论中所述,我们实际上是在寻找 type 的第一个节点SOAPBodyElement。希望这将帮助其他任何人在未来看到这个。

于 2014-02-21T19:03:42.657 回答
4

您可以调用body.getElementName().getLocalName()以检索消息有效负载的 SOAP 正文元素的名称。它有点冗长和手动,但它有效。您的处理程序中可能有以下内容

if ((boolean) context.get(MessageContext.MESSAGE_INBOUND_PROPERTY){ //for requests only
            SOAPEnvelope msg = context.getMessage().getSOAPPart().getEnvelope(); //get the SOAP Message envelope
                SOAPBody body = msg.getBody();
            String operationName = body.getChildNodes().item(1).getLocalName();
}

上述代码的结果保证带有您的 WSDL 中指定的操作名称

编辑:此解决方案仅基于将 Web 服务实现为文档/文字包装或 RPC/文字的条件

于 2012-11-24T16:42:44.913 回答
3

SOAPMessageContext 包含此信息,可以像这样超级轻松地检索:

public boolean handleMessage(SOAPMessageContext msgContext) {
    QName svcn = (QName) smc.get(SOAPMessageContext.WSDL_SERVICE);      
    QName opn = (QName) smc.get(SOAPMessageContext.WSDL_OPERATION);
    System.out.prinln("WSDL Service="+ svcn.getLocalPart());
    System.out.prinln("WSDL Operation="+ opn.getLocalPart());

    return true;
}
于 2013-05-16T17:22:47.243 回答
1

如果有人搜索“优雅”的方式来获得所需的属性,请使用

    for(Map.Entry e : soapMessageContext.entrySet()){
            log.info("entry:"+ e.getKey() + " = " + e.getValue());
    }

然后决定你需要什么信息并得到它!

soapMessageContext.get(YOUR_DESIRED_KEY);
于 2015-12-12T12:04:12.080 回答