Tomcat数据库连接池的配置方法总结

内容目录

 数据库连接是一种关键的有限的昂贵的资源,这在多用户网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标,数据库连接池正是针对这个问题提出的.

数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏,这样可以明显提高对数据库操作的性能.


据库连接池在初始化的时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是又最小数据库连接数来设定的,无论这些数据库连接是否被使用,连
接池都将一直保证至少拥有这么多的连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中.

数据库连接池的最小连接数和最大连接数的设置要考虑到下列几个因素:

1.最小连接数是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.

2.最大连接数是连接池申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待对了中,这回影响之后的数据库操作

如果最小连接数与最大连接数相差太大,那么最先的连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接,不过,这些小于最小连接数的数据库连接在使用完不会马上被释放,它将被放到连接池中等待重复使用或是空闲超时被释放.

实例使用的Tomcat版本为6.0

方法一: 在Tomcat的conf/context.xml中配置
在Tomcatapache-tomcat-6.0.33conf目录下的context.xml文件中配置默认值如下:

<?xml version='1.0' encoding='utf-8'?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>

配置连接池:

<?xml version='1.0' encoding='utf-8'?>
 

<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>

    <!--配置oracle数据库的连接池-->
    <Resource name="jdbc/oracleds"
        author="Container"
        type="javax.sql.DataSource"
        maxActive="100"
        maxIdle="30"
        maxWait="10000"
        username="scott"
        password="tiger"
        driverClassName="oracle.jdbc.dirver.OracleDriver"
        url="jdbc:oracle:thin:@127.0.0.1:1521:ora9" />

    <!--配置mysql数据库的连接池, 
        需要做的额外步骤是将mysql的Java驱动类放到tomcat的lib目录下        
        maxIdle 连接池中最多可空闲maxIdle个连接 
        minIdle 连接池中最少空闲maxIdle个连接 
        initialSize 初始化连接数目 
        maxWait 连接池中连接用完时,新的请求等待时间,毫秒 
        username 数据库用户名
        password 数据库密码
        -->
    <Resource name="jdbc/mysqlds" 
        auth="Container" 
        type="javax.sql.DataSource" 
        username="root" 
        password="root" 
        maxIdle="30" 
        maxWait="10000" 
        maxActive="100"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://127.0.0.1:3306/db_blog" />

</Context>

配置好后需要注意的两个步骤
 

1.将对应数据库的驱动类放到tomcat的lib目录西安

2.重新启动tomcat服务器,让配置生效

在web应用程序的web.xml中设置数据源参考,如下:

在<web-app></web-app>节点中加入下面内容

<resource-ref>
 

<description>mysql数据库连接池</description>
      <!-- 参考数据源名字,同Tomcat中配置的Resource节点中name属性值"jdbc/mysqlds"一致 -->
      <res-ref-name>jdbc/mysqlds</res-ref-name>
      <!-- 资源类型 -->
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
      <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

错误解决:
 

javax.naming.NoInitialContextException:
Need to specify class name in environment or system property, or as an
applet parameter, or in an application resource file:
java.naming.factory.initial
 

at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at com.iblog.util.DBPoolUtil.<clinit>(DBPoolUtil.java:34)

解决方案:
 

上面的异常信息是配置文件中JNDI没有初始化造成的

如果下面的问题都不存在

1.要去检查下配置文件中连接数据库的URL参数是否正确2.以及是否导入了正常的包3.检查在Tomcat中conf/server.xml文件,检查是否设置useNaming="false",如果是,去掉

2.那就是通过main方法测试的,这个数据源不支持这样的测试方法,程序要运行在Tomcat中才能找到相应的数据源.[我在测试时犯这样的错导致上面错误出现]

<%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>     
 

<%@ page import="java.sql.*" %>     
<%@ page import="javax.naming.*" %>     
<%@ page import="javax.sql.DataSource" %>
<html>     
<head>     
<title>Tomcat6.0 JNDI!</title>    
</head>    
  <body>      
   Tomcat连接池测试,获取数据源 <br>     
    <%     
        try {      
            //初始化查找命名空间
            Context ctx = new InitialContext();  
            //参数java:/comp/env为固定路径   
            Context envContext = (Context)ctx.lookup("java:/comp/env"); 
            //参数jdbc/mysqlds为数据源和JNDI绑定的名字
            DataSource ds = (DataSource)envContext.lookup("jdbc/mysqlds"); 
            Connection conn = ds.getConnection();     
            conn.close();     
            out.println("<span style='color:red;'>JNDI测试成功<span>");     
        } catch (NamingException e) {     
            e.printStackTrace();     
        } catch (SQLException e) {     
            e.printStackTrace();     
        }     
    %>     
  </body>     
</html>

运行效果:
 

方法二:在Tomcat的conf/server.xml中配置

打开tomcat的conf/server.xml文件,找到<GlobalNamingResources></GlobalNamingResources>节点,默认的内容如下

<GlobalNamingResources>
 

<Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>

在该节点中加入相关的池配置信息,如下
 

  <GlobalNamingResources>
 

<Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />

             <!--配置mysql数据库的连接池, 
                需要做的额外步骤是将mysql的Java驱动类放到tomcat的lib目录下        
               -->
             <Resource name="jdbc/mysqlds" 
              auth="Container" 
              type="javax.sql.DataSource" 
              username="root" 
              password="root" 
              maxIdle="30" 
              maxWait="10000" 
              maxActive="100"
              driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://127.0.0.1:3306/db_blog" />
  </GlobalNamingResources>

在tomcat的conf/context.xml文件中的<Context></Context>节点中加入如下内容
 

<ResourceLink name="jdbc/mysqlds" global="jdbc/mysqlds" type="javax.sql.DataSource"/>

然后在web项目中的WEB-INF目录下的web.xml中配置

<resource-ref>
 

<description>mysql数据库连接池</description>
      <!-- 参考数据源名字,同Tomcat中配置的Resource节点中name属性值"jdbc/mysqlds"一致 -->
      <res-ref-name>jdbc/mysqlds</res-ref-name>
      <!-- 资源类型 -->
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
      <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

同样配置好后,需要重新启动服务器,让配置生效.
 

方法三:在Tomcat的conf/server.xml中配置虚拟目录时配置 

在配置虚拟目录时,也就是在配置conf下面的server.xml时,在context标签内添加池配置.

在说该方法之前,先说一下,如何用tomcat配置虚拟目录

在tomcatconf下server.xml中找到

<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">
</Host>

在其中添加:

<Context path="/website" docBase="F:/myweb" reloadable="true"></Context>

注意:

docBase要改成你的项目目录。

path为虚拟路径,访问时的路径,注意:一定要加“/” debug建议设置为0

reloadable设置为true。  

这样重新启动tomcat

实例中如下配置

<Context path="/website" docBase="D:/program files/Tomcat/apache-tomcat-6.0.33/webapps/iblog.war" reloadable="true">
</Context>

接下来添加池配置,如下

<!--配置虚拟目录-->
 

<Context path="/website" docBase="D:/program files/Tomcat/apache-tomcat-6.0.33/webapps/iblog.war" reloadable="true">
            <Resource name="jdbc/mysqlds" 
            auth="Container" 
            type="javax.sql.DataSource" 
            username="root" 
            password="root" 
            maxIdle="30" 
            maxWait="10000" 
            maxActive="100"
            driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://127.0.0.1:3306/db_blog"
            />
</Context>

启动服务器,测试,注意因为我们配置了path值为”/website”,所以访问的路径应该为website.如下图:
 

方法四:在Web项目中的META-INF目录下新建一个文件context.xml,写入配置

注意:是META-INF目录下,不是WEB-INF目录下

<?xml version='1.0' encoding='utf-8'?>
 

<Context>
    <Resource name="jdbc/mysqlds" 
        auth="Container" 
        type="javax.sql.DataSource" 
        username="root" 
        password="root" 
        maxIdle="30" 
        maxWait="10000" 
        maxActive="100"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://127.0.0.1:3306/db_blog"
        logAbandoned="true" />
</Context>

连接测试

第一步:实现一个Java类:

package com.logistic.data;

import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.sql.Date;
//import java.text.SimpleDateFormat;

public class DataConnect {
 private Connection
con;
 private Statement stmt;
 private ResultSet rs;
 private PreparedStatement pstmt;
 public static int error=0;

 
 public static synchronized Connection
getCon()throws Exception{
  Context ctx;
  DataSource ds;
  try{
   ctx = new
InitialContext();
   ds
=
(DataSource)ctx.lookup("java:comp/env/jdbc/DBPool");
   if(ds==null){
   System.err.println();
   System.err.println("数据连接打开+"+(++error));
   }
   return
ds.getConnection();
   
  }catch(SQLException e){
   System.out.print(e);
   throw
e;
  }
  catch(NamingException e){
   System.out.print(e);
   throw
e;
  }
 }
 
 public Statement getStmtread(){
  try{
   con=getCon();
   stmt=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
  }catch(Exception e){
   System.out.println("getStmtread");
   System.out.println(e.getMessage());
  }
  return stmt;
 }
 
 public int getRowCount(String sql){
  int count=0;;
  try{
   stmt=this.getStmtread();
   rs=stmt.executeQuery("SELECT
COUNT(*) FROM "+sql);
   rs.getMetaData();
   if(rs.next()){
    count=rs.getInt(1);
   }else{
    count=-1;
   }
  }catch(Exception e){
   System.out.println("getRowCount");
   System.out.println(e.getMessage());
   count=-2;
  }finally{
   this.close();
  }
  return count;
 }
 
 public Statement getStmt(){
  try{
   con=getCon();
   stmt=con.createStatement();
  }catch(Exception e){
   System.out.println("getStmt");
   System.out.println(e.getMessage());
  }
  return stmt;
 }

 
 public PreparedStatement getPstmt(String
sql){
  try{
   con=getCon();
   pstmt=con.prepareStatement(sql);
  }catch(Exception e){
   System.out.println("getPstmt");
   System.out.println(e.getMessage());
  }
  return pstmt;
 }
 
 public void close(){
  try{
   if(rs!=null)rs.close();
  }catch(Exception e){
  }
  try{
   if(stmt!=null)stmt.close();
  }catch(Exception e){
  }
  try{
   if(con!=null){
   con.close();
   con=null;
   System.err.println();
   System.err.println("数据连接关闭-"+(--error));
   }
  }catch(Exception e){
   System.out.println("close");
   System.out.println(e.getMessage());
  }
 }
 
 public String inStr(String str){
  String tempstr=null;
  if(str==null){
   str="";
  }else{
   try{
    
    tempstr=new
String(str.getBytes("ISO-8859-1"),"GB2312");
    //tempstr=str.replace('\'',(char)1);
    
    
   }catch(Exception
e){
    System.out.println("inStr");
    System.out.println(e.getMessage());
   }
  }
  return tempstr;
  
 }
 
 public String outStr(String str){
  if(str==null){
   str="";
  }else{
   try{
    str=str.replace((char)1,'\'');
   }catch(Exception
e){
    System.out.println("outStr");
    System.out.println(e.getMessage());
   }
  }
  return str;
 }
 
 
 
 public int selectdata(String sqls){
  
  int k=-10;
  try{
   k=0;
   rs=this.getStmtread().executeQuery(sqls);
   while(rs.next()){
    k++;
   }
  }catch(Exception ex){
   k=-1;
   System.out.println("select");
   System.out.println(ex.getMessage());
   this.close();
  }finally{
  this.close();}
  return k;
 }
 
 
 
 public int updata(String sqls){
  
  int k=-10;
  try{
   k=0;
   k=this.getStmt().executeUpdate(sqls);
  }catch(Exception ex){
   k=-1;
   System.out.println("updata");
   System.out.println(ex.getMessage());
   this.close();
  }finally{this.close();}
  return k;
 }
 
 
 public Date StrConvertDate(String strdate)
  

     Date convertdate=null;
     try{    
             
           convertdate= Date.valueOf(strdate);
         
          System.out.print("打印日期");
          System.out.print(convertdate.toString());
          
     }catch(Exception ex){ex.printStackTrace();}
      return convertdate;
 }
 
 
}

 

通过getCon()就可以获取到连接了,其他是多余的

 

接下来是重点,也就是getCon()是如何获取到连接的

 

第二步:

配置web.xml文件

 

<!-- JNDI
-->
 <resource-ref>
   <description>MySQL DB Connection
Pool</description>
   <res-ref-name>jdbc/DBPool</res-ref-name>
   <res-type>javax.sql.DataSource</res-type>
   <res-auth>Container</res-auth>
   <res-sharing-scope>Shareable</res-sharing-scope>
 </resource-ref>

 

红色字体与Java文件中的必需一致,编译时时通过这些描述符来实现映射

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

单单这样子还是不够的,在Tomcat中还需要和该web.xml文件建立连接

 

第三步:配置Tomcat目录下conn文件夹中的context.xml配置文件

在<Context>

 <Resource
   name="jdbc/DBPool"
   type="javax.sql.DataSource"
   password=""
   driverClassName="com.mysql.jdbc.Driver"
   maxIdle="20"
   maxWait="5000"
   username="root"
   url="jdbc:mysql://localhost:3306/logistic"
  />

</Context>

 

以上是以MySql作为数据库,如果用其他数据库,改变url和driverClassName即可,但必需保证用户名、密码正确。

 

完成以后,还要将连接数据库的jar包,放在   Tomcat6/lib   目录下,而 Tomcat6/bin 下不需要放此jar包 

 

可能有的网友调试的时候会报这个错误:

javax.naming.NoInitialContextException:
Need to specify class name in environment or system property, or as
an applet parameter, or in an application resource
file: java.naming.factory.initialException in
thread "main" javax.naming.NoInitialContextException: Need to
specify class name in environment or system property, or as an
applet parameter, or in an application resource
file: java.naming.factory.initial
 at
javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
 at
javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
 at
javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
 at
javax.naming.InitialContext.lookup(InitialContext.java:392)
 at
gzgl.DataConnect.getCon(DataConnect.java:31)
 at
gzgl.DataConnect.main(DataConnect.java:23)

 

这是因为通过JNDI获取连接,程序必须通过Tomcat容器来加载连接,即通过web.xml来建立连接,如果只是在Java代码里面测试,是无法获取到连接的,因此,可以通过JSP(如index,jsp里面)进行如下测试:

<%@ page language="java" pageEncoding="UTF-8"%>    
<%@pagecontentType="text/html;
charset=UTF-8"%>    
<%@pageimport="java.sql.*"
%>    
<%@pageimport="javax.naming.*"
%>    
<%@pageimport="javax.sql.DataSource"
%>  
<%@pageimport="com.logistic.data.*"
%>  
<head>    
<title>Tomcat6.0
JNDI!</title>   
</head>   
     
 <body>    
   This is my
JSP page.
<br>    
   JNDI ...
<br>    
<%    
try
    
  DataConnect.getCon();
  out.println("连接成功...");
} catch (Exception e)
   
   e.printStackTrace();    
}
%>    
 </body>    
</html>  

 

在浏览器输入地址,可以看到运行结果:

OK,连接成功!

发表回复