在我们的应用程序中,我们有一些用于访问路由的静态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>
在多个场合,我们需要检索路由的值,给定参数value
,progress
和destination
(所有可选的,根本没有参数应返回所有路由)。
我知道如何使用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代码来获得最终结果)?
答案 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;
查询中不包含省略的参数。