是否有保证的方法来获取自定义soap处理程序中的操作名称?

Fru*_*ner 7 java soap web-services jax-ws soaphandler

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

public boolean handleMessage(SOAPMessageContext context)
{
    String op = context.get(MessageContext.WSDL_OPERATION);
    ...
Run Code Online (Sandbox Code Playgroud)

此操作失败,因为该属性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]);
Run Code Online (Sandbox Code Playgroud)

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

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

kol*_*sus 5

您可以调用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();
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 您确定该代码是正确的吗?我尝试了一下,得到“Body”作为“operationName”的值。`msg` 的字符串值为: *&lt;soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:head=(namespaces delcared here)&gt; &lt;b:CancelOperationRequest&gt; &lt;head:messageHeader&gt;...* 因此,如果我要获取 `body` 的下一个子级,并获取其名称,它可能是“CancelOperationRequest”,但这*不是*操作的名称,它是*请求类型*的名称(在本例中,操作的名称为“cancelOperation”)。 (2认同)

Ale*_*nes 5

我参加这个派对的时间已经很晚了,但过去一周我试图这样做.接受的答案实际上并不适用于每个JAX-WS实现(至少不是我尝试过的).

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

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

String operationName = body.getChildNodes().item(0).getLocalName();
Run Code Online (Sandbox Code Playgroud)

以下是Axis2的工作原理:

String operationName = body.getChildNodes().item(1).getLocalName();
Run Code Online (Sandbox Code Playgroud)

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

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

正如评论中所描述的那样,我们实际上正在寻找类型的第一个节点SOAPBodyElement.希望这将有助于将来看待这个的任何人.