前言
本文以Tomcat为j2ee容器,数据库为oracle进行说明。
什么是JNDI
JNDI(Java Naming and DirectoryInterface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API。
JNDI是Java平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。JDNI通过绑定的概念将对象和名称联系起来。在一个文件系统中,文件名被绑定给文件。在DNS中,一个IP地址绑定一个URL。在目录服务中,一个对象名被绑定给一个对象实体。
通俗的讲,以数据库为例,JNDI就是提供一个接口,而我们在程序中获得这个接口就可以得到数据库连接对象。
JNDI的作用
一般地,我们在开发项目连接数据库时,一般进行JDBC直连的方式,这也是最原始的连接方式:
Connection conn=null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
conn=DriverManager.getConnection("jdbc:oracle:thin:@10.2.112.90:1521:orcl");
......
conn.close();
}
catch(Exception e){
e.printStackTrace();
}
finally{
if(conn!=null){
try{
conn.close();
}catch(SQLException e){}
}
}
这样做会存在以下问题:
1. 数据库服务器名称 、用户名和口令都可能需要改变,数据库可能改用别的产品,如改用mysql或者Sqlserver,引发JDBC驱动程序包和类名需要修改,由此引发驱动程序包、类名、JDBC URL需要修改;
2. 当多个子系统使用一套数据库时,需每个子系统都配置JDBC,数据库配置不方便统一管理;
3. 随着实际使用的用户增加,原配置的连接池参数可能需要调整;
4. ......
其实,程序员应该不需要关心“具体的数据库后台是什么?JDBC驱动程序是什么?JDBC URL格式是什么?访问数据库的用户名和口令是什么?”等等这些问题,程序员编写的程序应该没有对 JDBC 驱动程序的引用,没有服务器名称,没有用户名称或口令 —— 甚至没有数据库池或连接管理。而是把这些问题交给J2EE容器(如Tomcat、Weblogic、Websphere、Jboss等)来配置和管理,程序员只需要对这些配置和管理进行引用即可。
由此,就有了JNDI。
用了JNDI之后的做法:
首先,在在J2EE容器中配置JNDI参数,定义一个数据源,也就是JDBC引用参数,定义一些连接池初始大小、最大连接数等配置,给这个数据源设置一个名称;然后,在程序中,通过数据源名称引用数据源从而访问后台数据库。
Tomcat配置JNDI
参照Tomcat自带文档
以apache-tomcat-6.0.37为例,启动tomcat,访问http://localhost:8080/地址,进入“TomcatDocumentation”帮助文档,然后点击第8条“JNDIResources”,如下图所示
实际上,j2ee要求所有的j2ee容器必须实现JNDI规范,容器里面有配置JNDI的相关文档;Tomcat里面详细介绍了JNDI使用方法及操作步骤,我们完全可以依照此文档的介绍进行配置,如果因为英文不好而看不懂的话,那么请看以下介绍。
引入JDBC驱动包
将数据库的驱动jar包放入Tomcat安装目录下的lib目录下,我Tomcat目录的是:D:\EHL\apache-tomcat-6.0.37\lib;将oracle数据库驱动包odbc.jar拷入此文件夹下。
配置context.xml
打开apache-tomcat-6.0.37\conf\context.xml文件,在<Context>标签内配置JNDI。
<Context...>
...
<Resourcename="jdbc/framedb"
auth="Container"
type="javax.sql.DataSource"
username="atms2013"
password="ehl1234"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@10.2.112.90:1521:orcl"
maxActive="8"
maxIdle="4"/>
...
</Context>
jdbc/framedb就是我们配置的JNDI名称,程序中就是通过这个名称来获得数据库连接对象。以上配置参数具体详情如下:
l driverClassName – 数据库驱动类名
l username – 数据库连接用户名
l password – 数据库连接密码
l url – 数据库连接字符串
l initialSize – 数据库连接池初始大小,默认为0
l maxActive – 同一时间最大连接数,默认是8
l minIdle – 连接池中最小数,默认是0
l maxIdle – 连接池中最大数,默认是8
l maxWait -最大的毫秒数, 当没有可用的连接时,池将等待时间,超时连接将抛出异常,默认是-1(无限等待)
当然,还有一些更高级的参数配置,具体请参照Tomcat帮助文档,这里就不做獒述。
配置Web.xml
在eclipse中新建web 项目JNDI,注意在项目中引入数据库驱动包odbc.jar,在/WEB-INF/web.xml
下做如下声明。
<resource-ref>
<description>
description
</description>
<res-ref-name>
jdbc/framedb
</res-ref-name>
<res-type>
javax.sql.DataSource
</res-type>
<res-auth>
Container
</res-auth>
</resource-ref>
引用数据源
新建Servlet,名为JndiSerlet,编写代码如下。
publicvoid doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
publicvoid doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String message="JNDI connect success!";
Context initCtx;
try{
initCtx =new InitialContext();
Context envCtx =(Context) initCtx.lookup("java:comp/env");
//此处jdbc/framed即为tomcat中配置的jndi名称
DataSource ds =(DataSource) envCtx.lookup("jdbc/framedb");
Connection conn = ds.getConnection();
conn.close();
System.out.println("JNDI连接成功");
}catch(Exception e){
message="JNDI connect failed:"+e.getMessage();
e.printStackTrace();
}
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print(message);
out.flush();
out.close();
}
同时在web.xml中定义Servlet:
<servlet>
<servlet-name>JndiSerlet</servlet-name>
<servlet-class>org.jndi.JndiSerlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JndiSerlet</servlet-name>
<url-pattern>/servlet/JndiSerlet</url-pattern>
</servlet-mapping>
验证JNDI
将上述配置完成后,将项目部署至tomcat,启动tomcat,访问http://localhost:8080/JNDI/servlet/JndiSerlet,若出现
则配置成功。
结束语
关于JNDI要注意的重要一点是,它提供了应用编程接口。而J2ee容器实现了JNDI接口(很象JDBC驱动为各种具体的数据库系统实现了JDBC接口一样)。作为一个应用开发者,不必操心JNDI 。只需要确认要使用的每一个命名服务都有在j2ee容器中配置好了就可以了。
个人认为,在一般项目中,特别是只有一个系统用一个数据库的时候,就不需要JNDI了;当有多个系统共用一个或多个数据库时,建议使用JNDI。