com.alibaba.druid.pool.DruidDataSourceFactory实现了javax.naming.spi.ObjectFactory,可以作为JNDI数据源来配置。
一、下载Druid的jar包
下载地址: http://mvnrepository.com/artifact/com.alibaba/druid/1.0.9 ,如下图所示:
druid.jar依赖log4j的jar包,所以还需要下载log4j的jar包。
log4j的下载地址如下: http://mvnrepository.com/artifact/log4j/log4j/1.2.17 ,如下图所示:
二、使用Druid配置JNDI数据源
2.1、前期准备工作
创建一个Web测试项目Druid_JNDI_Config, 将下载下来druid-1.0.9.jar和log4j-1.2.17.jar添加到项目中,在项目的META-INF目录下创建一个context.xml文件
目录结构如下图所示:
在tomcat服务器的lib目录下添加Oracle、MySQL、SQLServer三种数据库的驱动jar包,如下图所示:
2.2、 在context.xml文件中加入JNDI的配置信息
在context.xml文件中加入如下配置信息
1
<
Context
>
2
<!--
使用阿里巴巴的DruidDataSource配置针对Oracle数据库的JNDI数据源
-->
3
<
Resource
4
name
="jdbc/OracleDataSource"
5
factory
="com.alibaba.druid.pool.DruidDataSourceFactory"
6
auth
="Container"
7
type
="javax.sql.DataSource"
8
driverClassName
="oracle.jdbc.OracleDriver"
9
url
="jdbc:oracle:thin:@192.168.1.229:1521:lead"
10
username
="lead_oams"
11
password
="p"
12
maxActive
="50"
13
maxWait
="10000"
14
removeabandoned
="true"
15
removeabandonedtimeout
="60"
16
logabandoned
="false"
17
filters
="stat"
/>
18
19
<!--
使用阿里巴巴的DruidDataSource配置针对MySQL数据库的JNDI数据源
-->
20
<
Resource
21
name
="jdbc/MysqlDataSource"
22
factory
="com.alibaba.druid.pool.DruidDataSourceFactory"
23
auth
="Container"
24
type
="javax.sql.DataSource"
25
driverClassName
="com.mysql.jdbc.Driver"
26
url
="jdbc:mysql://192.168.1.233:3306/lead_oams?useUnicode=true&characterEncoding=utf-8"
27
username
="lead_system"
28
password
="password"
29
maxActive
="50"
30
maxWait
="10000"
31
removeabandoned
="true"
32
removeabandonedtimeout
="60"
33
logabandoned
="false"
34
filters
="stat"
/>
35
36
<!--
使用阿里巴巴的DruidDataSource配置针对SQLServer数据库的JNDI数据源
-->
37
<
Resource
38
name
="jdbc/SqlServerDataSource"
39
auth
="Container"
40
factory
="com.alibaba.druid.pool.DruidDataSourceFactory"
41
type
="javax.sql.DataSource"
42
driverClass
="com.microsoft.sqlserver.jdbc.SQLServerDriver"
43
url
="jdbc:sqlserver://192.168.1.61:1433;DatabaseName=gaclTest"
44
username
="sa"
45
password
="p@ssw0rd"
46
maxActive
="50"
47
maxWait
="10000"
48
removeabandoned
="true"
49
removeabandonedtimeout
="60"
50
logabandoned
="false"
51
filters
="stat"
/>
52
</
Context
>
配置项中指定了各个参数后,在连接池内部是这么使用这些参数的。数据库连接池在初始化的时候会创建initialSize个连接,当有数据库操作时,会从池中取出一个连接。如果当前池中正在使用的连接数等于maxActive,则会等待一段时间,等待其他操作释放掉某一个连接,如果这个等待时间超过了maxWait,则会报错;如果当前正在使用的连接数没有达到maxActive,则判断当前是否空闲连接,如果有则直接使用空闲连接,如果没有则新建立一个连接。在连接使用完毕后,不是将其物理连接关闭,而是将其放入池中等待其他操作复用。同时连接池内部有机制判断,如果当前的总的连接数少于miniIdle,则会建立新的空闲连接,以保证连接数得到miniIdle。如果当前连接池中某个连接在空闲了timeBetweenEvictionRunsMillis时间后任然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制(mysql连接在8小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候设置一个testWhileIdle参数为true,可以保证连接池内部定时检测连接的可用性,不可用的连接会被抛弃或者重建,最大情况的保证从连接池中得到的Connection对象是可用的。当然,为了保证绝对的可用性,你也可以使用testOnBorrow为true(即在获取Connection对象时检测其可用性),
不过这样会影响性能。
2.3、在web.xml引用JDNI数据源
在web.xml文件中加入如下的配置引用JNDI数据源
1
<?
xml version="1.0" encoding="UTF-8"
?>
2
<
web-app
version
="2.5"
3
xmlns
="http://java.sun.com/xml/ns/javaee"
4
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
5
xsi:schemaLocation
="http://java.sun.com/xml/ns/javaee
6
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
>
7
<
welcome-file-list
>
8
<
welcome-file
>
index.jsp
</
welcome-file
>
9
</
welcome-file-list
>
10
11
<!--
12
JNDI配置的资源引用:
13
• res-ref-name:表示引用资源的名称
14
• res-type:此资源对应的类型为javax.sql.DataSource
15
• res-auth:容器授权管理
16
-->
17
<!--
Oracle数据库JNDI数据源引用
-->
18
<
resource-ref
>
19
<
description
>
Oracle DB Connection
</
description
>
20
<
res-ref-name
>
jdbc/OracleDataSource
</
res-ref-name
>
21
<
res-type
>
javax.sql.DataSource
</
res-type
>
22
<
res-auth
>
Container
</
res-auth
>
23
</
resource-ref
>
24
25
<!--
MySQL数据库JNDI数据
-->
26
<
resource-ref
>
27
<
description
>
MySQL DB Connection
</
description
>
28
<
res-ref-name
>
jdbc/MysqlDataSource
</
res-ref-name
>
29
<
res-type
>
javax.sql.DataSource
</
res-type
>
30
<
res-auth
>
Container
</
res-auth
>
31
</
resource-ref
>
32
33
<!--
SQLServer数据库JNDI数据源引用
-->
34
<
resource-ref
>
35
<
description
>
SQLServer DB Connection
</
description
>
36
<
res-ref-name
>
jdbc/SqlServerDataSource
</
res-ref-name
>
37
<
res-type
>
javax.sql.DataSource
</
res-type
>
38
<
res-auth
>
Container
</
res-auth
>
39
</
resource-ref
>
40
</
web-app
>
2.4、 测试JNDI数据源
部署Druid_JNDI_Config Web应用到Tomcat服务器测试JNDI数据源,如下图所示:
部署到tomcat服务器的webapps目录之后,tomcat服务器就会自动在\conf\Catalina\localhost目录下生成一个Druid_JNDI_Config.xml文件,如下图所示:
Druid_JNDI_Config.xml文件中的内容就是我们在META-INF目录的context.xml文件中配置的那些内容。
jsp测试页面如下:
1
<%
@ page language
=
"
java
"
import
=
"
java.util.*
"
pageEncoding
=
"
UTF-8
"
%>
2
<%
--
引入JSTL标签库
--
%>
3
<%
@ taglib uri
=
"
http://java.sun.com/jsp/jstl/core
"
prefix
=
"
c
"
%>
4
<%
@ taglib uri
=
"
http://java.sun.com/jsp/jstl/sql
"
prefix
=
"
sql
"
%>
5
<!
DOCTYPE HTML
>
6
<
html
>
7
<
head
>
8
<
title
>
DRUID配置JNDI数据源连接测试
</
title
>
9
</
head
>
10
11
<
body
>
12
<
h3
>
针对MySQL数据库JNDI数据源测试
</
h3
>
13
<%
--
使用sql:query标签发送SQL语句去数据库查询数据,查询的结果集保存到rs变量当中,dataSource属性指明使用的数据源
--
%>
14
<
sql:query
var
="rs"
dataSource
="jdbc/MysqlDataSource"
>
15
<%
--
MySQL JNDI数据源测试 SQL
--
%>
16
select * from lead_oams_applications
17
</
sql:query
>
18
<%
--
使用c:forEach标签遍历查询结果集rs中的每一行
--
%>
19
<
c:forEach
var
="row"
items
="${rs.rows}"
>
20
<%
--
${row.字段名}获取字段的值
--
%>
21
${row.resourceid}---${row.app_name}
<
br
/>
22
</
c:forEach
>
23
<
hr
/>
24
<
h3
>
针对Oracle数据库JNDI数据源测试
</
h3
>
25
<%
--
使用sql:query标签发送SQL语句去数据库查询数据,查询的结果集保存到rs变量当中,dataSource属性指明使用的数据源
--
%>
26
<
sql:query
var
="rs"
dataSource
="jdbc/OracleDataSource"
>
27
<%
--
Oracle JNDI数据源测试 SQL
--
%>
28
SELECT * FROM LEAD_OAMS_DBSOURCES
29
</
sql:query
>
30
<%
--
使用c:forEach标签遍历查询结果集rs中的每一行
--
%>
31
<
c:forEach
var
="row"
items
="${rs.rows}"
>
32
<%
--
${row.字段名}获取字段的值
--
%>
33
${row.RESOURCEID}---${row.DBSOURCE_NAME}---${row.DBSOURCE_TYPE}
<
br
/>
34
</
c:forEach
>
35
<
hr
/>
36
<
h3
>
SQLServer JNDI数据源测试
</
h3
>
37
<%
--
使用sql:query标签发送SQL语句去数据库查询数据,查询的结果集保存到rs变量当中,dataSource属性指明使用的数据源
--
%>
38
<
sql:query
var
="rs"
dataSource
="jdbc/SqlServerDataSource"
>
39
<%
--
SQLServer JNDI数据源测试 SQL
--
%>
40
select * from t_demo
41
</
sql:query
>
42
<%
--
使用c:forEach标签遍历查询结果集rs中的每一行
--
%>
43
<
c:forEach
var
="row"
items
="${rs.rows}"
>
44
<%
--
${row.字段名}获取字段的值
--
%>
45
${row.id}---${row.name}
<
br
/>
46
</
c:forEach
>
47
</
body
>
48
</
html
>
运行结果如下:
三、在Java代码中获取JNDI中的数据源
3.1、获取JNDI中的数据源
编写一个JdbcUtil工具类,JdbcUtil工具类负责从JNDI容器中获取DataSource,再通过DataSource获取数据库连接。
代码如下:
1
package
me.gacl.util;
2
3
/**
4
* <p>ClassName: JdbcUtil<p>
5
* <p>Description: 从JNDI容器中获取DataSource,再通过DataSource获取数据库连接<p>
6
*/
7
import
java.sql.Connection;
8
import
java.sql.ResultSet;
9
import
java.sql.SQLException;
10
import
java.sql.Statement;
11
import
javax.naming.Context;
12
import
javax.naming.InitialContext;
13
import
javax.naming.NamingException;
14
import
com.alibaba.druid.pool.DruidDataSource;
15
16
public
class
JdbcUtil {
17
18
/*
19
web.xml文件中的JNDI数据源引用配置
20
21
<!--Oracle数据库JNDI数据源引用 -->
22
<resource-ref>
23
<description>Oracle DB Connection</description>
24
<res-ref-name>jdbc/OracleDataSource</res-ref-name>
25
<res-type>javax.sql.DataSource</res-type>
26
<res-auth>Container</res-auth>
27
</resource-ref>
28
29
<!--MySQL数据库JNDI数据 -->
30
<resource-ref>
31
<description>MySQL DB Connection</description>
32
<res-ref-name>jdbc/MysqlDataSource</res-ref-name>
33
<res-type>javax.sql.DataSource</res-type>
34
<res-auth>Container</res-auth>
35
</resource-ref>
36
37
<!--SQLServer数据库JNDI数据源引用 -->
38
<resource-ref>
39
<description>SQLServer DB Connection</description>
40
<res-ref-name>jdbc/SqlServerDataSource</res-ref-name>
41
<res-type>javax.sql.DataSource</res-type>
42
<res-auth>Container</res-auth>
43
</resource-ref>
44
*/
45
46
//
Oracle数据库配置的JNDI数据源连接名,后面跟的是DataSource名,DataSource名在web.xml文件中的<res-ref-name></res-ref-name>进行了配置
47
private
static
final
String ORACLE_DB_JNDINAME = "java:comp/env/jdbc/OracleDataSource"
;
48
//
MySQL数据库配置的JNDI数据源连接名,java:comp/env是必须加的,后面跟的是DataSource名
49
private
static
final
String MYSQL_DB_JNDINAME = "java:comp/env/jdbc/MysqlDataSource"
;
50
//
SQLServer数据库配置的JNDI数据源连接名,java:comp/env是必须加的,后面跟的是DataSource名
51
private
static
final
String SQLSERVER_DB_JNDINAME = "java:comp/env/jdbc/SqlServerDataSource"
;
52
53
private
static
DruidDataSource dsOracle =
null
;
54
private
static
DruidDataSource dsMySql =
null
;
55
private
static
DruidDataSource dsSqlServer =
null
;
56
57
static
{
58
try
{
59
//
1、初始化名称查找上下文
60
Context ctx =
new
InitialContext();
61
//
2、通过JNDI名称找到DataSource
62
dsOracle =
(DruidDataSource) ctx.lookup(ORACLE_DB_JNDINAME);
63
dsMySql =
(DruidDataSource) ctx.lookup(MYSQL_DB_JNDINAME);
64
dsSqlServer =
(DruidDataSource) ctx.lookup(SQLSERVER_DB_JNDINAME);
65
}
catch
(NamingException e) {
66
e.printStackTrace();
67
}
68
}
69
70
/**
71
* MethodName: getOracleConnection
72
* Description: 获取Oracle数据库连接
73
*
@author
xudp
74
*
@return
75
*
@throws
SQLException
76
*/
77
public
static
Connection getOracleConnection()
throws
SQLException {
78
return
dsOracle.getConnection();
79
}
80
81
/**
82
* MethodName: getMySqlConnection
83
* Description: 获取MySQL数据库连接
84
*
@author
xudp
85
*
@return
86
*
@throws
SQLException
87
*/
88
public
static
Connection getMySqlConnection()
throws
SQLException {
89
return
dsMySql.getConnection();
90
}
91
92
/**
93
* MethodName: getSqlServerConnection
94
* Description: 获取SQLServer数据库连接
95
*
@author
xudp
96
*
@return
97
*
@throws
SQLException
98
*/
99
public
static
Connection getSqlServerConnection()
throws
SQLException {
100
return
dsSqlServer.getConnection();
101
}
102
103
/**
104
* @Method: release
105
* @Description: 释放资源,
106
* 要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
107
* @Anthor:孤傲苍狼
108
*
109
*
@param
conn
110
*
@param
st
111
*
@param
rs
112
*/
113
public
static
void
release(Connection conn,Statement st,ResultSet rs){
114
if
(rs!=
null
){
115
try
{
116
//
关闭存储查询结果的ResultSet对象
117
rs.close();
118
}
catch
(Exception e) {
119
e.printStackTrace();
120
}
121
rs =
null
;
122
}
123
if
(st!=
null
){
124
try
{
125
//
关闭负责执行SQL命令的Statement对象
126
st.close();
127
}
catch
(Exception e) {
128
e.printStackTrace();
129
}
130
}
131
132
if
(conn!=
null
){
133
try
{
134
//
关闭Connection数据库连接对象
135
conn.close();
136
}
catch
(Exception e) {
137
e.printStackTrace();
138
}
139
}
140
}
141
}
3.2、测试JNDI数据源
编写一个测试的Servlet,测试代码如下:
1
package
me.gacl.test;
2
3
import
java.io.IOException;
4
import
java.sql.Connection;
5
import
java.sql.PreparedStatement;
6
import
java.sql.ResultSet;
7
import
java.sql.SQLException;
8
import
java.util.ArrayList;
9
import
java.util.LinkedHashMap;
10
import
java.util.List;
11
import
java.util.Map;
12
import
javax.servlet.ServletException;
13
import
javax.servlet.http.HttpServlet;
14
import
javax.servlet.http.HttpServletRequest;
15
import
javax.servlet.http.HttpServletResponse;
16
import
me.gacl.util.JdbcUtil;
17
18
/**
19
* <p>ClassName: JNDITestServlet<p>
20
* <p>Description: <p>
21
* <p>Company:广州利迪网络科技有限公司 <p>
22
*
@author
xudp
23
*
@version
1.0 V
24
* @createTime 2014-10-23 上午09:32:52
25
*/
26
public
class
JNDITestServlet
extends
HttpServlet {
27
28
public
void
doGet(HttpServletRequest request, HttpServletResponse response)
29
throws
ServletException, IOException {
30
31
//
Oracle数据库连接
32
Connection oracleConnection =
null
;
33
//
MySql数据库连接
34
Connection mySqlConnection =
null
;
35
//
SQLServer数据库连接
36
Connection sqlServerConnection =
null
;
37
38
//
负责执行SQL的PreparedStatement对象
39
PreparedStatement pstmtOracle =
null
;
40
PreparedStatement pstmtMySQL =
null
;
41
PreparedStatement pstmtSqlServer =
null
;
42
43
//
查询出来的结果集
44
ResultSet rsOracle =
null
;
45
ResultSet rsMySQL =
null
;
46
ResultSet rsSqlServer =
null
;
47
48
//
存储查询出来的数据,每一行数据映射成一个Map,字段名作为key,字段的值作为value
49
List<Map<String, String>> oracleDataList =
new
ArrayList<Map<String, String>>
();
50
List<Map<String, String>> mySqlDataList =
new
ArrayList<Map<String, String>>
();
51
List<Map<String, String>> sqlServerDataList =
new
ArrayList<Map<String, String>>
();
52
53
try
{
54
55
//
获取Oracle数据库连接
56
oracleConnection =
JdbcUtil.getOracleConnection();
57
//
获取MySql数据库连接
58
mySqlConnection =
JdbcUtil.getMySqlConnection();
59
//
获取SQLServer数据库连接
60
sqlServerConnection =
JdbcUtil.getSqlServerConnection();
61
62
String oracleDb_Sql = "SELECT * FROM LEAD_OAMS_DBSOURCES"
;
63
String mySqlDb_Sql = "SELECT * FROM LEAD_OAMS_APPLICATIONS"
;
64
String sqlServerDb_Sql = "SELECT * FROM T_DEMO"
;
65
66
pstmtOracle =
oracleConnection.prepareStatement(oracleDb_Sql);
67
pstmtMySQL =
mySqlConnection.prepareStatement(mySqlDb_Sql);
68
pstmtSqlServer =
sqlServerConnection.prepareStatement(sqlServerDb_Sql);
69
70
//
执行查询,查询结果存储到ResultSet结果集中
71
rsOracle =
pstmtOracle.executeQuery();
72
rsMySQL =
pstmtMySQL.executeQuery();
73
rsSqlServer =
pstmtSqlServer.executeQuery();
74
75
//
循环结果集中的数据
76
while
(rsOracle.next()){
77
Map<String, String> oracleDataMap =
new
LinkedHashMap<String, String>
();
78
//
取出结果集中的数据,每一行数据映射成一个map集合
79
oracleDataMap.put("resourceid", rsOracle.getString("RESOURCEID"
));
80
oracleDataMap.put("dbsource_name", rsOracle.getString("DBSOURCE_NAME"
));
81
oracleDataMap.put("dbsource_type", rsOracle.getString("DBSOURCE_TYPE"
));
82
//
将代表每一行数据的Map集合添加到List集合中
83
oracleDataList.add(oracleDataMap);
84
}
85
86
while
(rsMySQL.next()){
87
Map<String, String> mySqlDataMap =
new
LinkedHashMap<String, String>
();
88
mySqlDataMap.put("resourceid", rsMySQL.getString("resourceid"
));
89
mySqlDataMap.put("app_name", rsMySQL.getString("app_name"
));
90
mySqlDataList.add(mySqlDataMap);
91
}
92
93
while
(rsSqlServer.next()){
94
Map<String, String> sqlServerDataMap =
new
LinkedHashMap<String, String>
();
95
sqlServerDataMap.put("id", rsSqlServer.getString("id"
));
96
sqlServerDataMap.put("name", rsSqlServer.getString("name"
));
97
sqlServerDataList.add(sqlServerDataMap);
98
}
99
100
//
将数据集合存储到request对象发送到页面进行显示
101
request.setAttribute("oracleDataList"
, oracleDataList);
102
request.setAttribute("mySqlDataList"
, mySqlDataList);
103
request.setAttribute("sqlServerDataList"
, sqlServerDataList);
104
//
跳转到JNDITest.jsp页面显示数据
105
request.getRequestDispatcher("/JNDITest.jsp"
).forward(request, response);
106
107
}
catch
(SQLException e) {
108
e.printStackTrace();
109
}
finally
{
110
//
释放资源
111
JdbcUtil.release(oracleConnection, pstmtOracle, rsOracle);
112
JdbcUtil.release(mySqlConnection, pstmtMySQL, rsMySQL);
113
JdbcUtil.release(sqlServerConnection, pstmtSqlServer, rsSqlServer);
114
}
115
}
116
117
public
void
doPost(HttpServletRequest request, HttpServletResponse response)
118
throws
ServletException, IOException {
119
doGet(request,response);
120
}
121
}
JNDITest.jsp页面代码如下:
1
<%
@ page language
=
"
java
"
import
=
"
java.util.*
"
pageEncoding
=
"
UTF-8
"
%>
2
<%
--
引入JSTL标签库
--
%>
3
<%
@ taglib uri
=
"
http://java.sun.com/jsp/jstl/core
"
prefix
=
"
c
"
%>
4
<!
DOCTYPE HTML
>
5
<
html
>
6
<
head
>
7
<
title
>
JNDI测试
</
title
>
8
</
head
>
9
10
<
body
>
11
<
h3
>
从Oracle数据库中取出来的数据
</
h3
>
12
<%
--
使用c:forEach标签遍历List集合
--
%>
13
<
c:forEach
var
="oracleDataMap"
items
="${oracleDataList}"
>
14
${oracleDataMap.resourceid}---${oracleDataMap.dbsource_name}---${oracleDataMap.dbsource_type}
<
br
/>
15
</
c:forEach
>
16
<
hr
/>
17
<
h3
>
从mySql数据库中取出来的数据
</
h3
>
18
<%
--
使用c:forEach标签遍历List集合
--
%>
19
<
c:forEach
var
="mySqlDataMap"
items
="${mySqlDataList}"
>
20
${mySqlDataMap.resourceid}---${mySqlDataMap.app_name}
<
br
/>
21
</
c:forEach
>
22
<
hr
/>
23
<
h3
>
从sqlServer数据库中取出来的数据
</
h3
>
24
<%
--
使用c:forEach标签遍历List集合
--
%>
25
<
c:forEach
var
="sqlServerDataMap"
items
="${sqlServerDataList}"
>
26
${sqlServerDataMap.id}---${sqlServerDataMap.name}
<
br
/>
27
</
c:forEach
>
28
</
body
>
29
</
html
>
运行结果如下:

