Spring Web Services 中的 XPath 支援

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

接續我在WS-DuckTyping上的文章,我想展示 Spring Web Services 為 XPath 提供的支援。 其中一些功能現在已經可用,但大多數將成為本月稍後發布的 RC1 版本的一部分。 在這篇文章中,我將使用 第 35 項中定義的 contacts xml 檔案,該檔案位於 Rusty Harold 的 Effective XML

XPathExpression

其中一個已提供相當長一段時間的選項是 XPathExpression。 它是編譯後的 XPath 運算式的抽象,例如 Java 5 XPathExpression 和 Jaxen XPath

最近,我添加了 XPathExpressionFactoryBean,以便更輕鬆地將 XPath 運算式注入到您的 beans 中,如下所示


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

為了簡單起見,此運算式未使用命名空間,但我們可以使用 factory 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 映射 rows 一樣,每個結果節點都使用匿名內部類別進行映射。 在這種情況下,我們建立一個 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 註解才能將該類別標記為端點,@PayloadRoot 表示每當 SOAP 請求傳入並且以 Contact 作為根元素時,都會呼叫 handleContacts 方法。 最後,@XPathParam 執行參數綁定。 您可以綁定到 XPath 支援的所有資料類型:布林值、double、字串、節點和節點清單。 當然,將所有運算式保存在一個組態檔案中更易於維護,但對於較簡單的專案,這是一種合適的方法。

使用此註解的端點樣式只需要一點點 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 版本的一部分(其中還包括我們正在處理的更新的參考文件)。 但是,此版本的快照可在此處 here 獲得,因此請試試看,並在 forums 上回報。

取得 Spring 電子報

隨時關注 Spring 電子報

訂閱

領先一步

VMware 提供培訓和認證,以加速您的進度。

瞭解更多

獲得支援

Tanzu Spring 在一個簡單的訂閱中為 OpenJDK™、Spring 和 Apache Tomcat® 提供支援和二進位檔。

瞭解更多

即將舉行的活動

查看 Spring 社群中所有即將舉行的活動。

查看全部