Spring Web Services中的XPath支援

工程 | Arjen Poutsma | 2007年4月23日 | ...

繼我關於WS-DuckTyping的帖子之後,我認為展示Spring Web Services為XPath提供的支援會很有趣。其中一些功能現在可用,但大部分將包含在本月晚些時候釋出的RC1版本中。在整篇文章中,我將使用Rusty Harold的《Effective XML》中第35項定義的contacts xml檔案。

XPathExpression

其中一個長期可用的選項是XPathExpression。它是對已編譯XPath表示式的抽象,例如Java 5的XPathExpression和Jaxen的XPath

最近,我添加了XPathExpressionFactoryBean,以便更輕鬆地將XPath表示式注入到您的bean中,例如


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <bean id="myEndpoint" class="com.mycompany.ws.MyEndpoint">
        <constructor-arg ref="nameExpression"/>
    </bean>

    <bean id="nameExpression" class="org.springframework.xml.xpath.XPathExpressionFactoryBean">
        <property name="expression" value="/Contacts/Contact/Name"/>
    </bean>

</beans>

為簡單起見,此表示式未使用名稱空間,但我們可以使用工廠 Bean 的 namespaces 屬性來設定它們。

可以在程式碼中像這樣使用該表示式:


public class MyEndpoint extends AbstractDomPayloadEndpoint {
    
    private XPathExpression nameExpression;

    public MyEndpoint(XPathExpression nameExpression) {
        this.nameExpression = nameExpression;
    }

    // Gets invoked for every incoming request
    protected Element invokeInternal(Element requestElement, Document responseDocument) throws Exception {
        String name = nameExpression.evaluateAsString(requestElement);
        // do something with name
        return null; // no response
    }

}

最近 XPathExpression 的一個新功能是 NodeMapper。如果我們把表示式改為 /Contacts/Contact,就可以像這樣使用它:


public class MyEndpoint extends AbstractDomPayloadEndpoint {

    private XPathExpression nameExpression;

    public MyEndpoint(XPathExpression nameExpression) {
        this.nameExpression = nameExpression;
    }

    protected Element invokeInternal(Element requestElement, Document responseDocument) throws Exception {
        List contacts = nameExpression.evaluate(requestElement,
                new NodeMapper() {
                    public Object mapNode(Node node, int nodeNum) throws DOMException {
                        Element contactElement = (Element) node;
                        Element nameElement = (Element) contactElement.getElementsByTagName("Name").item(0);
                        Element phoneElement = (Element) contactElement.getElementsByTagName("Phone").item(0);
                        return new Contact(nameElement.getTextContent(), phoneElement.getTextContent());
                    }
                } );
        for (Iterator iterator = contacts.iterator(); iterator.hasNext();) {
            Contact contact = (Contact) iterator.next();
            System.out.println(contact);
        }
        return null; // no response
    }

}

就像我們使用 Spring JDBC 的 RowMapper 來對映行一樣,每個結果節點都使用匿名內部類進行對映。在這種情況下,我們建立一個 Contact 物件,然後稍後列印它。

XPathTemplate

另一個最近新增的功能是 XPathTemplate。該類遵循 Spring 中使用的通用模板模式(JdbcTemplate、JmsTemplate 等)。此模板可以這樣使用:

public class MyEndpoint implements PayloadEndpoint {

    private XPathOperations template = new Jaxp13XPathTemplate();

    public Source invoke(Source request) throws Exception {
        String name = template.evaluateAsString("/Contacts/Contact/Name", request);
        // do something with name
        return null; // no response
    }

}

當然,可以將模板透過建構函式引數或 setter 進行注入。

XPath 模板不使用預編譯的 XPath 表示式,因此速度稍慢一些。但是,模板更靈活,因為您可以將其用於多個表示式。它還支援上面描述的 NodeMapper

@XPathParam

最後,Java 5 使用者有一個新功能:@XPathParam 註解。您可以在方法引數上使用此註解,XPath 評估將直接注入到方法中。用法如下:

@Endpoint
public class MyEndpoint {

    @PayloadRoot("Contacts")
    public void handleContacts(@XPathParam("/Contacts/Contact/Name")String name) {
        // do something with name
    }

}

為了將類標記為端點,需要使用 @Endpoint 註解;當收到根元素為 Contact 的 SOAP 請求時,@PayloadRoot 會指示呼叫 handleContacts 方法。最後,@XPathParam 執行引數繫結。您可以繫結到 XPath 支援的所有資料型別:布林值、雙精度值、字串、節點和節點列表。當然,將所有表示式放在一個配置檔案中會更易於維護,但對於更簡單的專案,這是一種可行的方法。

使用這種帶註解的端點風格只需要一點點 XML 配置,只需讓 Spring-WS 知道端點的存在並使用註解即可。其餘的都會自動處理。


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping"/>

    <bean class="org.springframework.ws.server.endpoint.adapter.XPathParamAnnotationMethodEndpointAdapter"/>

    <bean id="myEndpoint" class="com.mycompany.ws.MyEndpoint"/>

</beans>

這些功能中的大多數都將包含在本月晚些時候釋出的 RC1 版本中(該版本還將包含我們正在編寫的更新的參考文件)。然而,此版本有快照可供下載 此處,請嘗試一下,並在 論壇 上報告您的反饋。

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有