java 是否有保证的方法可以在自定义肥皂处理程序中获取操作名称?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13535277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:07:59  来源:igfitidea点击:

Is there a guaranteed way to get operation name in a custom soap handler?

javaweb-servicessoapjax-wssoaphandler

提问by FrustratedWithFormsDesigner

I have a custom SOAP message handler for incoming messages that will run different code based on which operation is being called. My first try to get the operation name looked something liket this:

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

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

This failed because the property MessageContext.WSDL_OPERATIONappears to never be set. I then tried using this:

这失败了,因为该属性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]);

This works, but I'm concerned there could be situations where the header property "SOAPAction" isn't set (or doesn't even exist), or does not have the value that I'm expecting it to. I'm also a little concerned because I don't know if this is an "official" way to get the operation name - I figured it out by looking at the contents of contextin the debugger.

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

Is there any better way to get the operation name when handling incoming SOAP messages?

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

采纳答案by kolossus

You could call body.getElementName().getLocalName()to retrieve the name of SOAP body element of the message payload. It's a little bit verbose and manual but it works. You could have the following in your handler

您可以调用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();
}

The result of the above code is guaranteed to carry the name of the operation as specified in your WSDL

上面代码的结果保证携带在你的 WSDL 中指定的操作名称

EDIT: This solution is based solely on the condition that the web service is implemented as document/literal-wrapped or RPC/literal

编辑:此解决方案仅基于将 Web 服务实现为 document/literal-wrapped 或 RPC/literal 的条件

回答by Alex Barnes

I'm very late to this party but I tried to do this over the past week. The accepted answer doesn't actually work for every JAX-WS implementation (at least not that I tried).

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

I have been trying to make this work on standalone Metro in my development environment but also using Axis2 bundled with WebSphere 7 in a real environment.

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

I found the following works on Metro:

我在地铁上找到了以下作品:

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

and the following works on Axis2:

以及以下适用于 Axis2:

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

What is happening is that Axis2 inserts a Node of type Textinto the Body as the first child but Metro doesn't. This text node returns a null local name. My solution was to do the following:

发生的事情是 Axis2 将一个类型Text为Node 的 Node作为第一个孩子插入到 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();
  }
}

As described in the comments we're actually looking for the first node of type SOAPBodyElement. Hopefully that will help out anyone else looking at this in the future.

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

回答by dsutherland

The SOAPMessageContext contains this information and can be retrieved super easily like this:

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;
}

回答by Didar Burmaganov

in case if someone searches for "elegant" way to get needed properties use

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

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

then decide what info you need and get it!

然后决定您需要什么信息并获取它!

soapMessageContext.get(YOUR_DESIRED_KEY);