如何创建JNDI资源,它代表着在Tomcat中的JDBC数据源。
以及如何配置一个java web app 来使其能够访问JNDI数据源。
1-使用由container提供的数据库连接池,(tomcat能使用Commons DBCP和 Commons Pool作为实现-tomcat-dbcp.jar);
2-将数据库连接分工作从web应用程序中分离出来;
3-使得在container中部署的应用之间能够分享数据库连接;
下面的实例在Tomcat7,Mysql5.5中进行测试。
create database usersdb;
use usersdb;
CREATE TABLE `users` ( `user_id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(45) NOT NULL, `password` varchar(45) NOT NULL, `email` varchar(45) NOT NULL, PRIMARY KEY (`user_id`) );
这个表创建了一个usersdb 和一个表 users.
切记插入一些数据到这个表中。
use usersdb;
INSERT INTO users (username, password, email) VALUES ('Wilson', 'docd', '[email protected]');
INSERT INTO users (username, password, email) VALUES ('Willims', 'docd', '[email protected]');
INSERT INTO users (username, password, email) VALUES ('jordan', 'docd', '[email protected]');
INSERT INTO users (username, password, email) VALUES ('kobe', 'docd', '[email protected]');
INSERT INTO users (username, password, email) VALUES ('tlyson', 'docd', '[email protected]');
INSERT INTO users (username, password, email) VALUES ('kimi', 'docd', '[email protected]');
为了使mysql数据库和java应用程序之间能够交互,一定要确保MySQL Connector/J 的library包加入到
calsspath中。这里我们需要将mysql-connector-java-VERSION-bin.jar文件复制到 $CATALINA_BASE/lib
目录下。如果你只在你的电脑上安装了一个Tomcat,那么$CATALINA_BASE就是tomcat的安装目录。
例如在我的windows中,是D:\apache-tomcat-7.0.61。
这么做能够帮助Tomcat加载MySQL JDBC driver,当它发现有JNDI数据源配置时。
为了声明刚才创建的数据库的JNDI数据源,需要创建一个带有如下内容的 Resource XML元素
<Resource
name="jdbc/UsersDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/usersDB"
username="root"
password="secret"
/>
将这个元素加入到一个context.xml文件的根元素之中,有两个地方可以放置context.xml文件。
1 在web应用程序的 /META-INF目录中: JNDI数据源只有应用程序本身能够使用,不能在应用程序之间共享。
这个配置将是依着这个程序来设定的。
2 在 $CATALINA_BASE/conf 目录中:这是首选的地方,因为这样JNDI数据源将能够在程序间共享,同时也是独立于应用程序而设置的。
这里,我们将采用第二种做法。
参数说明:
注意:
1-如果你使用的Tomcat在Eclipse IDE中,你需要修改的是 Servers project 下的 context.xml 文件,
因为Eclipse使用的是复制来的Tomcat配置。
2-如果两个同名资源都定义在context.xml文件中,并分别放置在META-INF目录和$CATALINA_BASE/conf目录中,
那么内部版本优先。
在web.xml文件中加入以下声明:
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/UsersDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
这一声明是为了使得JNDI数据源在特定的命名空间jdbc/UsersDB下在应用程序中可用。
内容如下:
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<sql:query var="listUsers" dataSource="jdbc/UsersDB">
select username, email from users;
</sql:query>
<!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>Users List</title>
</head>
<body>
<div align="center">
<table border="1" cellpadding="5">
<caption><h2>List of users</h2></caption>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
<c:forEach var="user" items="${listUsers.rows}">
<tr>
<td><c:out value="${user.username}" /></td>
<td><c:out value="${user.email}" /></td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
查找配置好的数据源的java代码如下:
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/UsersDB");
Connection conn = ds.getConnection();
得到连接(connection)后我们可以像在JDBC中一样检索。
Statement statement = conn.createStatement();
String sql = "select username, email from users";
ResultSet rs = statement.executeQuery(sql);
// iterates over the result set...
一下是完整的代码:
package net.codejava.jdbc;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
/** * This servlet class demonstrates how to access a JNDI DataSource that * represents a JDBC connection. * @author www.codejava.net */
@WebServlet("/listUsers")
public class UsersListServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
try {
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/UsersDB");
Connection conn = ds.getConnection();
Statement statement = conn.createStatement();
String sql = "select username, email from users";
ResultSet rs = statement.executeQuery(sql);
int count = 1;
while (rs.next()) {
writer.println(String.format("User #%d: %-15s %s", count++,
rs.getString("username"), rs.getString("email")));
}
} catch (NamingException ex) {
System.err.println(ex);
} catch (SQLException ex) {
System.err.println(ex);
}
}
}
可选的,我们还可以使用@Resource注解,(javax.annotation.Resource)来替代上面的查找代码。
例如,可以像下面一样声明一个dataSource:
@Resource(name = "jdbc/UserDb")
private DataSource dataSource;
当Tomcat发现这个注解符号,Tomcat将查找对应的资源并注入程序中。
完整的测试代码如下:
@WebServlet("/listUsers")
public class UsersListServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Resource(name = "jdbc/UsersDB")
private DataSource dataSource;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
try {
Connection conn = dataSource.getConnection();
Statement statement = conn.createStatement();
String sql = "select username, email from users";
ResultSet rs = statement.executeQuery(sql);
int count = 1;
while (rs.next()) {
writer.println(String.format("User #%d: %-15s %s", count++,
rs.getString("username"), rs.getString("email")));
}
} catch (SQLException ex) {
System.err.println(ex);
}
}
}
翻自http://www.codejava.net