处理spring bean中的xml配置文档

时间:2014-07-25 10:10:54

标签: java xml spring xpath

在我们的应用程序中,我们有一些用于访问路由的静态xml配置。 xml文件的示例如下所示:

 <configuration>
   <level value="1" progress="1">
     <route destination="a">ba</route>
   </level>
   <level value="1" progress="2">
     <route destination="a">caba</route>
     <route destination="b">cabb</route> 
   </level>
   .. etc ..
 </configuration>

在多个场合,我们需要检索路由的值,给定参数valueprogressdestination(所有可选的,根本没有参数应返回所有路由)。

我知道如何使用XPath实现这一点,但我想在一个spring bean中使用它,它可以连接到其他spring bean服务。

我在想像

这样的东西
 @Service
 Class RouteConfiguration implements IRouteConfiguration {
      Document xmlRoutes = null;
      XPath xPath =  XPathFactory.newInstance().newXPath();
      // Constructor
      public RouteConfiguration() {
          try {
              DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
              DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
              xmlRoutes = docBuilder.parse (this.getClass().getResourceAsStream(url));
          } catch AndAll...



      // method
      public List<String> getRoutes(Integer level, Integer progress, String destination) {
            String expression = String.format("/configuration/level[@value='%d' and @progress='%d']/route[@destination='%s']", level, progress, destination);
            NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlRoutes, XPathConstants.NODESET);
            // Of course some more plumbing needed to cater for optional arguments and to get result List.
      } 

我想知道这是正确的做法吗?我知道Spring支持XML,但据我所知,这适用于xml(webservice)消息。我还担心并发性和可能的​​性能问题?是否有更好的解决方案来解决这个问题(我可以用xsd创建一个Object Graph并使用jxpath或普通的java代码来获得最终结果)?

4 个答案:

答案 0 :(得分:2)

您应该查看Spring参考中的Marshalling XML using O/X Mappers。也许你会找到答案。

另一种选择是使用java Pojo将Jaxb与spring结合使用。

答案 1 :(得分:2)

“我想知道这是正确的方法吗?”

要完全回答您的问题,我相信需要更多信息。有多少个配置文件?他们多大?它们是否需要以XML格式存储?如果没有这些信息,很难说这是否是正确的方法。

如果您只关心Spring方法,我建议使用InitializingBean来加载XML配置。这是最近的一篇文章(不是我的,但看起来很健全)http://www.journaldev.com/2637/spring-bean-life-cycle-methods-initializingbean-disposablebean-postconstruct-predestroy-aware-interfaces

至于并发性和性能,我建议(取决于有多少)在app启动时使用InitializingBean将它们全部加载到内存中,然后你的性能很好,并发性和其他Spring一样豆。

答案 2 :(得分:1)

Jaxb是一个很好的功能强大的工具,主要是为你的xml文件创建一个xsd。正如它目前所声明的那样,你可以有类似的东西:

<schema version="1.0"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:conf="http://my/schemas/Config"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        targetNamespace="http://my/schemas/Config"
        elementFormDefault="qualified"
        xsi:schemaLocation="http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd">
    <complexType name="route">
        <simpleContent>
            <extension base="string">
                <attribute name="destination" type="string"/>
            </extension>
        </simpleContent>
    </complexType>
    <complexType name="level">
        <sequence>
            <element name="route" type="conf:route" minOccurs="1" maxOccurs="unbounded"/>
        </sequence>
        <attribute name="value" type="integer"/>
        <attribute name="progress" type="integer"/>
    </complexType>
    <complexType name="configuration" mixed="true">
        <sequence>
            <element name="level" type="conf:level" minOccurs="1" maxOccurs="unbounded"/>
        </sequence>
    </complexType>
    <element name="configuration" type="conf:configuration"/>
</schema>

然后您的xml文件可以是:

<configuration
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://my/schemas/Config'
        xsi:schemaLocation='http://my/schemas/Config conf.xsd'>>
   <level value="1" progress="1">
     <route destination="a">ba</route>
   </level>
   <level value="1" progress="2">
     <route destination="a">caba</route>
     <route destination="b">cabb</route> 
   </level>
   ...
</configuration>

Jaxb将通过

生成您的pojos和支持类
xjc -d directory -p package conf.xsd

你可以通过以下方式加载xml:

    Configuration configuration;
    try {
        JAXBContext ctx = JAXBContext.newInstance(Configuration.class.getPackage().getName());
        JAXBElement<Configuration> elt = (JAXBElement<Configuration>) ctx
                .createUnmarshaller().unmarshal(rsrc.getInputStream());
        configuration = elt.getValue();
    } catch (JAXBException ex) {
        throw ex;
    }

答案 3 :(得分:1)

一种选择是使用内存数据库(例如H2)并读取,展平并将XML数据插入到包含列(值,进度,目标,路由)的表中,然后只运行SQL查询的是:

select route from table where value = 1 and progress = 2;

查询中不包含省略的参数。