Java程序中的数据源与JNDI
JNDI 即Java 命名与目录接口(Java Naming and Directory Interface)
获取数据源最原始的方案
不用JNDI,我们完成一个带有数据库的工程,可能就要这么写
Connection conn=null;
Class.forName("com.mysql.jdbc.Driver",Thread.currentThread().getContextClassLoader());
conn=DriverManager.getConnection("jdbc:mysql://demo01?user=root&password=root");
//对数据库的操作
//..
conn.close();
这种写法在修改数据库,修改账号密码时都需要重新修改代码。通常情况发布,开发,测试用的应该是不同的数据库。也就是说,当开发完程序以后,发布和开发并不是完全相同的版本。
使用配置文件
稍微好一点,可以把这些类似user
,password
之类的信息写到诸如xml,properties之类的配置文件中
user=root
password=root
然后在加载数据库的时候去解析配置文件
Map<String, String> properties = Properties.parse("datasource.properties");
conn=DriverManager.getConnection("jdbc:mysql://demo01?user=" +
properties.get("user") +
"&password=" +
properties.get("password"));
这样再发布的时候可以直接替换配置文件,不需要修改源代码。
另一种情况,比如在spring的bean配置中可以通过profile
来控制使用那个数据源。
<bean name='mysqlDataSource' profile='dev'>
<props>...</props>
</bean>
<bean name='orclDataSource' profile='QA'>
<props>...</props>
</bean>
在编译和发布的时候控制当前的profile属于开发或者是测试,以选择不同的数据源。
使用JNDI
我们在开发测试和过程中可能使用的是不同的环境(也许是同样版本的tomcat,但开发测试可能在两台电脑上),那为什么我们不把数据源直接配置在开发和测试的服务器上。
比如在开发的tomcat上配置(为了看起来方便,删去了一些配置)
<Resource name="jdbc/MySQL" auth="Container" type="javax.sql.DataSource"
username="dev_li" password="dev" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://192.168.101.4:3306/demo" removeAbandoned="true"
removeAbandonedTimeout="60" logAbandoned="true"/>
在测试的tomcat上配置
<Resource name="jdbc/MySQL" auth="Container" type="javax.sql.DataSource"
username="qa_li" password="qa" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://44.130.16.128:3306/qa01" removeAbandoned="true"
removeAbandonedTimeout="60" logAbandoned="true"/>
两者的name都一样,在项目中只要通过相同的name就可以获取数据源。
这种配置的方式使用的就是所谓的JNDI。
在Java代码中,我们大概可以通过:
Context ctx = new InitialContext();
Object datasourceRef = ctx.lookup("java/MySQL");
DataSource ds = (Datasource)datasourceRef;
conn = ds.getConnection();
去获取数据源,而关键的ctx.lookup("java/MySQL")
加载JNDI的方式。
程序中的JNDI
在程序中,我们可以通过naming包获取当前环境下的JNDI
import javax.naming.Context;
import javax.naming.InitialContext;
Context ctx = new InitialContext();
Object obj = ctx.lookup("JNDI的名称");
接口X demo = (接口X)obj;
接下来就可以通过接口X使用JNDI