有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在自定义soap处理程序中是否有一种获得操作名的保证方法?

我有一个用于传入消息的自定义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) 个答案

  1. # 1 楼答案

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

    我一直在尝试在我的开发环境中的独立Metro上实现这一点,但也在实际环境中使用与WebSphere 7捆绑的Axis2

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

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

    Axis2上的工作如下:

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

    Axis2将Text类型的节点作为第一个子节点插入到主体中,但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();
      }
    }
    

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

  2. # 2 楼答案

    您可以调用body.getElementName().getLocalName()来检索消息负载的SOAP body元素的名称。虽然有点冗长,也有点手工操作,但它确实有效。你可以在你的处理器中有以下内容

    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服务实现为document/literal wrapped或RPC/literal

  3. # 3 楼答案

    如果有人寻找“优雅”的方式来获得所需的财产,请使用

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

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

    soapMessageContext.get(YOUR_DESIRED_KEY);
    
  4. # 4 楼答案

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