更進一步
VMware 提供培訓和認證,以加速您的進步。
瞭解更多繼我關於 WS-DuckTyping 的帖子之後,我想展示一下 Spring Web Services 為 XPath 提供了什麼支援。 其中一些功能現在可用,但大多數將成為我們本月晚些時候釋出的 RC1 版本的一部分。 在這篇文章中,我將使用 item 35 中定義的 contacts xml 檔案,來自 Rusty Harold 的 Effective XML。
最近,我添加了 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,我們稍後只需列印它。
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。
@Endpoint
public class MyEndpoint {
@PayloadRoot("Contacts")
public void handleContacts(@XPathParam("/Contacts/Contact/Name")String name) {
// do something with name
}
}
需要 @Endpoint 註解才能將該類標記為端點,@PayloadRoot 指示每當 SOAP 請求到來時,都會呼叫 handleContacts 方法,該請求的根元素為 Contact。 最後,@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 版本的一部分(其中還將包括我們正在編寫的更新的參考文件)。 但是,此版本 此處提供了快照,因此請嘗試一下,並在論壇上報告。