在Java中的Tomcat DataSource JNDI示例
欢迎来到Tomcat DataSource JNDI示例教程。在上一篇教程中,我们讨论了JDBC DataSource,并学习了如何在独立的Java应用程序中使用它。
“Tomcat数据源JNDI”
当我们将DataSource与JNDI上下文一起使用时,它的实际好处就显现出来了。例如,在部署在Servlet容器中的Web应用程序中使用连接池。大多数流行的Servlet容器通过资源配置和JNDI上下文提供了内置的DataSource支持。这帮助我们通过只需少量配置来创建和使用DataSource连接池。本教程旨在提供Tomcat DataSource JNDI配置示例。Apache Tomcat提供了三种在JNDI上下文中配置DataSource的方式。
-
- 应用程序context.xml – 这是配置DataSource最简单的方法,我们只需要在META-INF目录中有一个context.xml文件。我们必须在context文件中定义Resource元素,容器会负责加载和配置它。这种方法很简单,但是它有一些缺点;
由于context文件与WAR文件捆绑在一起,所以每次进行小的配置更改都需要构建和部署新的WAR文件。如果你的应用程序在分布式环境中运行,或者你的应用程序需要部署在不同的测试环境(如QA、IT、PROD等)中,都会遇到同样的问题。
datasource是由容器为应用程序使用而创建的,因此无法全局共享。我们不能在多个应用程序之间共享datasource。
如果全局datasource(server.xml)使用相同的名称定义,则会忽略应用程序的datasource。
服务器context.xml – 如果服务器中有多个应用程序,而您希望在它们之间共享DataSource,我们可以在服务器context.xml文件中定义。此文件位于apache-tomcat/conf目录中。服务器context.xml文件的范围是应用程序级别,因此如果您定义了一个拥有100个连接的DataSource连接池,并且有20个应用程序,那么将为每个应用程序创建一个datasource。这将导致2000个连接,显然会消耗所有数据库服务器资源,并且会影响应用程序的性能。
server.xml和context.xml – 我们可以通过在server.xml的GlobalNamingResources元素中定义它们,在全局级别定义DataSource。如果我们使用这种方法,那么我们需要在服务器或应用程序特定的context.xml文件中定义一个ResourceLink。当您希望在服务器上运行的多个应用程序之间共享一个公共资源池时,这是首选的方法。至于资源链接,是在服务器级别的context xml文件中定义还是应用程序级别,这取决于您的要求。
让我们转到Java Web应用程序中的Tomcat DataSource JNDI示例。对于测试数据设置,请参考我上一篇关于JDBC DataSource示例的文章。
Tomcat 数据源 JNDI 配置示例 – server.xml
在tomcat的server.xml文件中添加下面的代码。代码应该添加在GlobalNamingResources元素中。还需要确保数据库驱动程序存在于tomcat的lib目录中,这种情况下mysql jdbc jar必须存在于tomcat lib中。
<Resource name="jdbc/MyDB"
global="jdbc/MyDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/UserDB"
username="scdev"
password="scdev123"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
在这里,我们通过名为“jdbc/MyDB”的JNDI上下文创建了一个DataSource类型的对象。我们在url、username、password和driverClassName属性中传递了数据库的配置信息。连接池的属性在maxActive、maxIdle和minIdle属性中进行了定义。
Tomcat数据源JNDI资源链接配置- context.xml
在服务器的context.xml文件中添加下面的代码。
<ResourceLink name="jdbc/MyLocalDB"
global="jdbc/MyDB"
auth="Container"
type="javax.sql.DataSource" />
请注意,资源链接名称与全局链接名称不同,我们必须在我们的Java程序中使用该名称来获取数据源。
Tomcat数据源JNDI示例
创建一个名为JDBCDataSourceTomcat的动态网页应用程序,然后使用以下代码创建一个Servlet。
package com.Olivia.jdbc.datasource;
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;
@WebServlet("/JDBCDataSourceExample")
public class JDBCDataSourceExample extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Context ctx = null;
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try{
ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/MyLocalDB");
con = ds.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery("select empid, name from Employee");
PrintWriter out = response.getWriter();
response.setContentType("text/html");
out.print("<html><body><h2>Employee Details</h2>");
out.print("<table border=\"1\" cellspacing=10 cellpadding=5>");
out.print("<th>Employee ID</th>");
out.print("<th>Employee Name</th>");
while(rs.next())
{
out.print("<tr>");
out.print("<td>" + rs.getInt("empid") + "</td>");
out.print("<td>" + rs.getString("name") + "</td>");
out.print("</tr>");
}
out.print("</table></body><br/>");
//lets print some DB information
out.print("<h3>Database Details</h3>");
out.print("Database Product: "+con.getMetaData().getDatabaseProductName()+"<br/>");
out.print("Database Driver: "+con.getMetaData().getDriverName());
out.print("</html>");
}catch(NamingException e){
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
rs.close();
stmt.close();
con.close();
ctx.close();
} catch (SQLException e) {
System.out.println("Exception in closing DB resources");
} catch (NamingException e) {
System.out.println("Exception in closing Context");
}
}
}
}
请注意我正在使用基于Servlet 3的注解配置,它适用于Tomcat 7或更高版本。如果您使用的是较低版本的Tomcat,则需要对Servlet代码进行一些修改,以删除WebServlet注解并在web.xml文件中进行配置。我们感兴趣的是Servlet代码的一部分。
ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/MyLocalDB");
这是获取应用程序使用的JNDI资源定义的方式。我们也可以以这种方式写出来。
ctx = new InitialContext();
Context initCtx = (Context) ctx.lookup("java:/comp/env");
DataSource ds = (DataSource) initCtx.lookup("jdbc/MyLocalDB");
我还在打印一些数据库信息来检查我们连接的是哪个数据库。现在当你运行应用程序时,你会看到以下的输出。让我们看看切换数据库服务器有多简单,因为我们正在使用Tomcat数据源。你只需要修改数据库属性即可。所以如果我们需要切换到Oracle数据库,我的资源配置将如下所示。
<Resource name="jdbc/MyDB"
global="jdbc/MyDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@localhost:1521:orcl"
username="hr"
password="oracle"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
当我们重新启动服务器并运行应用程序时,它将连接到Oracle数据库并生成以下结果。这就是Tomcat DataSource JNDI配置示例教程的全部内容,您也可以在context.xml文件中以类似的方式定义资源。