您的位置:首页 > 其它

第十八天 “恰到好处”与“好中择优”—JNDI的使用

2014-05-12 11:46 387 查看
5月12日,晴天。“纷纷红紫已成尘,布谷声中夏令新。夹路桑麻行不尽,始知身是太平人。”

1、恰到好处的JDBC

在学生的练习、案例和小规模的开发,JDBC使用的很多。配置简单,规范,一眼就能明白是主要原因。但也存在问题,所以企业的实际开发时,多用JNDI。

主要问题:

(1)数据库服务器名称 、用户名和口令都可能需要改变,由此引发JDBC URL需要修改;

(2)数据库可能更换产品,比如开发使用MySQL,实际部署改为DB2或者Oracle,引发JDBC驱动程序包和类名需要修改;

(3)随着实际使用终端的增加,原配置的连接池参数可能需要调整。而JDBC的API中没有提供连接池的方法。

2、DataSource对象

在Java语言中,DataSource对象就是一个代表数据源实体的对象。应用程序通过一个连接来访问数据源,那么一个DataSource对象就是用于提供连接数据源的工具。DataSource接口提供了两个方法用于建立和数据源的连接,使用DataSource对象建立和数据库的连接比起使用DriverManager接口更加高效,虽然两者的使用范围都很相似,并且都提供了方法用于建立和数据库的连接。

但两者之间的区别更加明显,和DriverManager不同,一个DataSource对象能够识别和描述它所代表的数据源的属性,而DataSource对象的工作和JNDI(Javatm Naming and Directory Interface)具有密切的关系, DataSource的建立、发布、独立于应用程序的管理都依靠JNDI技术。

JDBC2.0提供了javax.sql.DataSource接口,它负责建立与数据库的连接,在应用程序访问数据库时不需要编写连接数据库的代码,可以直接从数据源获得数据库连接。在DataSource中事先建立了多个数据库连接,这些数据库连接保存在连接池(Connect Pool)中。Java程序访问数据库时,只需要从连接池中取出空闲状态的数据库连接;当程序访问数据库结束,再将数据库连接放回连接池。

3、好中择优的JNDI

可以简单地把JNDI理解为一种将对象和名字绑定的技术,对象工厂负责生产出对象,这些对象都和惟一的名字绑定。外部程序可以通过名字来获取对某个对象的引用。

DataSource对象是由Tomcat提供的,因此不能在程序中采用创建一个实例的方式来生产DataSource对象,而需要采用Java的另一个技术JNDI,来获得DataSource对象的引用。

Tomcat把DataSource作为一种可以配置的JNDI资源来处理。生成DataSource对象的工厂为org.apache.commons.dbcp.BasicDataSourceFactory。

在javax.naming包中提供了Context接口,该接口提供了将对象和名字绑定,以及通过名字检索对象的方法。Context中的主要方法有:

bind(String name,Object object):将对象与一个名字绑定。

lookup(String name):返回与指定的名字绑定的对象。

4、Tomcat中数据源的配置

自tomcat 5.5起数据库连接池的配置和以前的不同了,不推荐在server.xml中进行配置,而是在%Tomcat_Home%\webapps\yourApp\META-INF\context.xml中进行配置才是更好的方法。

而不是以前版本%Tomcat_Home%\conf\context.xml文件。这样就可以在不同的web应用下单独配置连接池了,且Tomcat会自动重载。当然你也可以更改%Tomcat_Home%\conf下的context.xml文件,将所有web应用下的连接池进行统一配置。

因为server.xml是不可动态重加载的资源,服务器一旦启动了以后,要修改这个文件,就得重启服务器才能重新加载。而context.xml文件则不然,tomcat服务器会定时去扫描这个文件。一旦发现文件被修改(时间戳改变了),就会自动重新加载这个文件,而不需要重启服务器。

注:这一步容易报错:Cannot create JDBC driver of class for connect URL null 一定要记得把你的MYSQL5.0驱动jar包考到Tomcat6.0 的lib文件下。


5、Web应用中使用数据源

javax.naming.Context提供了查找JNDI Resource的接口,可以通过三个步骤来使用数据源对象:

A.获得对数据源的引用:

    Context ctx = new InitalContext();

DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/BookDb");

B.获得数据库连接对象:

Connection con = ds.getConnection();

  C.返回数据库连接到连接池:

con.close();

在连接池中使用close()方法和在非连接池中使用close()方法的区别是:前者仅仅是把数据库连接对象返回到数据库连接池中,是连接对象又恢复到空闲状态,而非关闭数据库连接,而后者将直接关闭和数据库的连接。

6、实例说明

(1)使用MySQL建个数据库jsp_db,供测试之用。

drop database IF EXISTS jsp_db;
create database if not exists jsp_db;

USE jsp_db;
DROP TABLE IF EXISTS student;
CREATE TABLE student (
sid varchar(20) NOT NULL,
name varchar(30) default NULL,
sex int(1) default NULL,
phone varchar(16) default NULL,
birth date default NULL,
Constraint primary key pk_student(sid)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

(2)编写context.xml。

context.xml的位置:在Eclipse中放的位置,如下图



如果直接放在在Tomcat下面,就放在\conf文件夹下。
<?xml version="1.0" encoding="UTF-8"?>
<Context >
<Resource name="jdbc/bn"
auth="Container"
type="javax.sql.DataSource"
maxActive="30"
maxIdle="10"
maxWait="10000"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jsp_db?characterEncoding=gb2312"
username="root" password="root" />
</Context>
相关说明:name 为当前数据源JNDI的名字,可以随意设定;

auth 为验证方式;

type 资源类型;

maxActiv 为连接池最大激活的连接数,设为0表示无限制;

maxIdle 为连接池最大空闲的连接数,数据库连接的最大空闲时间。超过空闲时间,

数据库连接将被标记为不可用,然后被释放。设为0表示无限制;

maxWait 为连接最大的等待时间,单位毫秒,如果超过此时间将接到异常。设为-1表示无限制;

driverClassName 为驱动引用;

url 为连接数据库的连接地址;

username 为数据库的一个用户名;

password 为username的密码;

(3)编写测试代码

<!--测试连接池-->
<%@ page contentType="text/html; charset=gb2312"%>
<%@ page import="javax.naming.Context"%>
<%@ page import="javax.sql.DataSource"%>
<%@ page import="javax.naming.InitialContext"%>
<%@ page import="java.sql.*"%>

<%
//request.setCharacterEncoding("UTF-8");
DataSource ds = null;
try {
Context initCtx = new InitialContext();
//从Context中查找数据源
ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/bn");
if (ds != null) {
out.println("已经获得DataSource!");
out.println("<br>");
Connection conn = ds.getConnection();
java.sql.Statement stmt = conn.createStatement();
stmt.executeUpdate("insert into student(sid,name,sex,phone,birth) values('034','王五',1,'8725698','1986/06/01')");
out.println("数据:'034','王五',1,'8725698','1986/06/01' 添加成功");
//关闭连接、释放资源
stmt.close();
conn.close();
} else
out.println("连接失败!");
} catch (Exception ne) {
out.println(ne);
}
%>
(4)运行结果



说明:1、java:comp/env 是环境命名上下文(environment naming context(ENC)),是在EJB规范1.1以后引入的,引入这个是为了解决原来JNDI查找所引起的冲突问题,也是为了提高EJB或者J2EE应用的移植性。

2、java:comp/env/jdbc/bn(虚地址) ------> 映射描述符 ------> jdbc/bn (实际的地址)。

3、逻辑名jdbc/bn作为数据源名称的好处是为了提高可移植性,移植的时候只需要把配置文件改一下就可以,而应用程序可不用改动,JNDI名字其实说白了就是把JNDI名放到配置文件里。


4、通过jndi配置多个数据源。

<?xml version="1.0" encoding="UTF-8"?>
<Context >
<Resource name="jdbc/bn"
auth="Container"
type="javax.sql.DataSource"
maxActive="30"
maxIdle="10"
maxWait="10000"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jsp_db?characterEncoding=gb2312"
username="root" password="root" />
<Resource name="jdbc/biz"
auth="Container"
type="javax.sql.DataSource"
maxActive="30" maxIdle="10" maxWait="10000"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/bizdemo"
username="root" password="root" />
</Context>
5、再编写一个测试代码

<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@page import="java.sql.*"%>
<%@page import="javax.naming.*"%>
<%@page import="javax.sql.DataSource"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Tomcat6.0 JNDI 测试</title>
</head>
<body>
This is my JSP page.
<br> JNDI配置测试开始 ...
<br>
<%
try {
//初始化 Context 上下文对象;
Context ctx = new InitialContext();
//Context envContext = (Context) ctx.lookup("java:/comp/env");
//DataSource ds = (DataSource) envContext.lookup("jdbc/biz"); //查找配置
//方法二:
DataSource ds = (DataSource) ctx
.lookup("java:comp/env/jdbc/biz");
Connection conn = ds.getConnection();
conn.close();
out.println("JNDI数据源配置成功了!");
} catch (NamingException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
%>
</body>
</html>

运行结果



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: