Java中的Tomcat数据源JNDI示例
欢迎使用Tomcat DataSource JNDI示例教程。
我们在上一教程中查看了JDBC DataSource,并学习了如何在独立的Java应用程序中使用它。
Tomcat数据源JNDI
当我们将其与JNDI上下文一起使用时,DataSource的实际好处就来了。
例如,Web应用程序中的连接池部署在Servlet容器中。
大多数流行的servlet容器通过资源配置和JNDI上下文提供对DataSource的内置支持。
这有助于我们通过几行配置来创建和使用DataSource连接池。
本教程旨在提供Tomcat DataSource JNDI配置示例。
Apache Tomcat提供了三种在JNDI上下文中配置DataSource的方法。
应用程序context.xml –这是配置DataSource的最简单方法,我们需要的是META-INF目录中的context.xml文件。
我们必须在上下文文件中定义Resource元素,容器将负责加载和配置它。
这种方法很简单,但是也有一些缺点;由于上下文文件与WAR文件捆绑在一起,因此我们需要为每个小的配置更改构建并部署新的WAR。
如果您的应用程序在分布式环境中运行,或者您的应用程序需要部署在不同的测试环境(例如QA,IT,PROD等)中,也会出现同样的问题。数据源是由容器创建的,仅供应用程序使用,因此不能在全球范围内使用。
我们无法在多个应用程序之间共享数据源。如果存在使用相同名称定义的全局数据源(server.xml),则将忽略应用程序数据源。
服务器context.xml –如果服务器中有多个应用程序,并且您希望在它们之间共享数据源,我们可以在服务器context.xml文件中对其进行定义。
该文件位于" apache-tomcat/conf"目录中。
服务器context.xml文件的范围是application,因此,如果您定义一个100个连接的DataSource连接池,并且有20个应用程序,则将为每个应用程序创建数据源。
这将导致2000个连接,这些连接显然将消耗所有数据库服务器资源,并损害应用程序性能。server.xml和context.xml –我们可以通过在server.xml
GlobalNamingResources
元素中定义它们来在全局级别定义DataSource。
如果使用这种方法,则需要从特定于服务器或者应用程序的context.xml文件中定义一个" ResourceLink"。
当您希望在服务器上运行的多个应用程序之间共享公用资源池时,这是首选方法。
关于资源链接,是在服务器级别的上下文xml文件还是在应用程序级别定义它取决于您的要求。
让我们来看一下Java Web应用程序中的Tomcat DataSource JNDI示例。
对于测试数据设置,请参考我关于JDBC数据源示例的上一篇文章。
Tomcat数据源JNDI配置示例– server.xml
在tomcat server.xml文件中添加以下代码。
该代码应添加到" GlobalNamingResources"元素中。
还要确保tomcat lib目录中存在数据库驱动程序,因此在这种情况下,tomcat lib中必须存在mysql jdbc jar。
<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="hyman" password="hyman123" maxActive="100" maxIdle="20" minIdle="5" maxWait="10000"
其中我们正在创建名称为jdbc/MyDB
的JNDI上下文,这是一种数据源。
我们通过url,用户名,密码和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的动态Web应用程序,然后使用以下代码创建一个Servlet。
package com.theitroad.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 DataSource,切换数据库服务器有多么容易。
您只需要更改数据库属性。
因此,如果必须切换到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"
重新启动服务器并运行该应用程序.