使用ruby解析xml的简单例子

在使用hudson持续集成的工作中,我们会在构建完成后运行一个自动部署脚本。
自动部署脚本需要知道构建的模块信息,用ruby解析pom.xml是比较合适的选择。

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <artifactId>sample</artifactId>
        <version>0.1.9-SNAPSHOT</version>
...
</project>

ruby脚本片段如下:

#!/usr/bin/env ruby

require "rexml/document"
doc = REXML::Document.new(File.open('pom.xml'))

artifactId = doc.elements["project/artifactId"].text
version = doc.elements["project/version"].text

上面的脚本,使用rexml模块解析xml。
注意:如果版本号是通过继承得来(或是在profile里指定的),先使用maven生成实际生效的pom.xml才能获得正确的结果。
Tips:使用mvn help:effective-pom生成实际生效的pom。

Spring通过JNDI从Tomcat查询Datasource

首先,介绍下运行的软件环境:

  • tomcat 7.0
  • oracle 11.2
  • spring 3.0
  • c3p0 0.9.1

下面,我们开始配置。

1.准备好tomcat依赖的jar包
把下列的jar包拷贝到TOMCAT_HOME/lib/目录下(其他依赖可以放在web应用的lib目录下):

  • ojdbc6-11.2.0.jar: oracle jdbc驱动
  • c3p0-0.9.1.jar: c3p0连接池

2.在tomcat上下文里配置c3p0连接池
可以参考tomcat jndi datasource examples文档,和文档上不同的地方是这里使用了c3p0连接池。
在TOMCAT_HOME/conf/context.xml里添加下面的配置:

<Resource auth="Container"
          description="DB Connection"
          driverClass="oracle.jdbc.driver.OracleDriver"
          maxPoolSize="50"
          minPoolSize="3"
          acquireIncrement="3"
          name="jdbc/sample"
          user="user"
          password="password"
          factory="org.apache.naming.factory.BeanFactory"
          type="com.mchange.v2.c3p0.ComboPooledDataSource"
          jdbcUrl="jdbc:oracle:thin:@hostname:1521:sid" />

配置到这里,就可以使用JNDI查询到数据库连接池了。

3.在spring里注入数据源
使用JNDI查询数据源tomcat_DataSource:

<bean id="tomcat_DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
	<property name="jndiName" value="java:comp/env/jdbc/sample" />
</bean>

现在,可以配置web应用使用tomcat_DataSource数据源了。

java读取classpath下资源的2种方法比较

A.使用ClassLoader.getResourceAsStream()读取资源:

@Test
public void test_ClassLoader_getResourceAsStream() {
	InputStream works = getClass().getClassLoader().getResourceAsStream(
			filename);
	assertNotNull(works);

	InputStream doesnt_work = getClass().getClassLoader()
			.getResourceAsStream("/" + filename);
	assertNull(doesnt_work);
}

B.使用spring上下文来加载资源:

@Test
public void test_ApplicationContext_getResource() {
	ApplicationContext ctx = new ClassPathXmlApplicationContext();
	// !!! dosen't work within tomcat
	Resource may_works = ctx.getResource("classpath:" + filename);
	assertTrue(may_works.exists());

	Resource always_works = ctx.getResource("classpath:/" + filename);
	assertTrue(always_works.exists());
}

下面来分析两种方法的适用情况:

方法A:
pros:不依赖额外的包,干净。
cons:资源和调用类必须由同一个(或有继承关系的)Classloader加载,否则找不到资源文件。例如在tomcat环境中,若资源文件和调用类的jar包分离,有可能出现找不到资源的情况。

方法B:
pros:只要在classpath下,就可以找到资源。
cons:需要依赖spring的包。

对于我来说,简单的应用,使用方法A就可以。
复杂些的应用,一般会使用spring,很多资源文件都使用依赖注入,使用方法B的情况很少。