Spring Web Services 中的 XPath 支持

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

继我关于 WS-DuckTyping 的帖子之后,我想展示一下 Spring Web Services 为 XPath 提供了什么支持。 其中一些功能现在可用,但大多数将成为我们本月晚些时候发布的 RC1 版本的一部分。 在这篇文章中,我将使用 item 35 中定义的 contacts xml 文件,来自 Rusty Harold 的 Effective 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 注解才能将该类标记为端点,@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 版本的一部分(其中还将包括我们正在编写的更新的参考文档)。 但是,此版本 此处提供了快照,因此请尝试一下,并在论坛上报告。

获取 Spring 新闻简报

通过 Spring 新闻简报保持联系

订阅

更进一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中为 OpenJDK™、Spring 和 Apache Tomcat® 提供支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部