文中内容主要转自:http://www.open-open.com/lib/view/open1327478028639.html
http://www.open-open.com/lib/view/open1365991769687.html
http://blog.csdn.net/lzm1340458776/article/details/37901619
tomcat jdbc pool 可在 Tomcat 中直接使用,也可以在独立的应用中使用。
属性说明:
name | 数据源名称,这个随便,通常取为jdbc/XXX的格式 |
auth | Container容器 |
type | javax.sql.DataSource 注意是javax不是java |
username | 数据库用户名 |
password | 数据库用户密码 |
maxIdle |
连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限制(默认为8个,maxIdle不能设置太小,因为假如在高负载的情况下, 连接的打开时间比关闭的时间快,会引起连接池中idle的个数 上升超过maxIdle,而造成频繁的连接销毁和创建,类似于jvm参数中的Xmx设置) |
maxActive | 连接池的最大数据库连接数。设为0表示无限制。 |
maxWait | 等待连接的最大连接的时间。最大等待毫秒数, 单位为 ms, 超过时间会出错误信息 |
driverClassName | 数据库完整的驱动类全称。 |
url | 数据库链接 |
1. 在独立应用中使用:
1 import java.sql.Connection;
2 import java.sql.ResultSet;
3 import java.sql.Statement;
4
5 import org.apache.tomcat.jdbc.pool.DataSource;
6 import org.apache.tomcat.jdbc.pool.PoolProperties;
7
8 public class SimplePOJOExample {
9
10 public static void main(String[] args) throws Exception {
11 PoolProperties p = new PoolProperties();
12 p.setUrl("jdbc:mysql://localhost:3306/mysql");
13 p.setDriverClassName("com.mysql.jdbc.Driver");
14 p.setUsername("root");
15 p.setPassword("password");
16 p.setJmxEnabled(true);
17 p.setTestWhileIdle(false);
18 p.setTestOnBorrow(true);
19 p.setValidationQuery("SELECT 1");
20 p.setTestOnReturn(false);
21 p.setValidationInterval(30000);
22 p.setTimeBetweenEvictionRunsMillis(30000);
23 p.setMaxActive(100);
24 p.setInitialSize(10);
25 p.setMaxWait(10000);
26 p.setRemoveAbandonedTimeout(60);
27 p.setMinEvictableIdleTimeMillis(30000);
28 p.setMinIdle(10);
29 p.setLogAbandoned(true);
30 p.setRemoveAbandoned(true);
31 p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
32 "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
33 DataSource datasource = new DataSource();
34 datasource.setPoolProperties(p);
35
36 Connection con = null;
37 try {
38 con = datasource.getConnection();
39 Statement st = con.createStatement();
40 ResultSet rs = st.executeQuery("select * from user");
41 int cnt = 1;
42 while (rs.next()) {
43 System.out.println((cnt++)+". Host:" +rs.getString("Host")+
44 " User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
45 }
46 rs.close();
47 st.close();
48 } finally {
49 if (con!=null) try {con.close();}catch (Exception ignore) {}
50 }
51 }
52
53 }
2. 在 Tomcat 中直接使用
方式一、
1). 找到tomcat所在目录中的conf文件夹中的context.xml文件,在其中做修改(在Context结点里面添加):
1 <!—mysql数据源配置-->
2 <Resource
3 name="ds_mysql"
4 auth="Container"
5 type="javax.sql.DataSource"
6 maxActive="100"
7 maxIdel="30"
8 maxWait="10000"
9 username="root"
10 password="5982285"
11 driverClassName="com.mysql.jdbc.Driver"
12 url="jdbc:mysql://localhost/myblog"
13 />
14 <!—oracle数据源配置-->
15 <Resource
16 name="jdbc/oracleds"
17 auth="Container"
18 type="javax.sql.DataSource"
19 maxActive="100"
20 maxIdel="30"
21 maxWait="10000"
22 username="scott"
23 password="tiger"
24 driverClassName="oracle.jdbc.driver.OracleDriver"
25 url="jdbc:oracle:thin:@localhost:1521:sky"
26 />
注:上面为mysql和Oracle配置了数据源,看个人需求而定,二者选其一。
注:网上很多人都说需要在web.xml文件中再次配置,其实不配置也是可以的(本人就没有在web.xml配置,依然跑的很溜),另外有一个要
特别注意的是要将数据源的jar包和数据库的驱动包放到tomcat的lib包中。
JNDI技术简介
JNDI(Java Naming and Directory Interface)即Java命名和目录接口,它对应于Java EE中的javax.naming包,这套API的主要作用:它可以
把DataSource对象放在一个Tomcat容器中(JNDI容器),并为容器中的DataSource对象取一个名称,以后程序想获得DataSource对象,只需
要通过名称检索即可。
JNDI的核心API为Context,它代表JNDI容器,核心方法是lookup()它的功能是检索容器中对应名称的对象。
连接池工具类:
1 /**
2 * 获取数据库连接的工厂
3 * @author Liao
4 */
5 public class ConnectionFactory {
6
7 private static DataSource dataSource;
8
9 static {
10 try {
11 //初始化查找命名空间
12 Context context = new InitialContext();
13 //找到DataSource。 java:/comp/env为固定路径。 ds_mysql是tomcat中设置的数据源
14 dataSource = (DataSource) context.lookup("java:comp/env/ds_mysql");
15 } catch (Exception e) {
16 e.printStackTrace();
17 }
18 }
19
20 /**
21 * 获取数据库连接
22 */
23 public static Connection getConnection(){
24 try {
25 //通过数据源获取连接然后返回
26 return dataSource.getConnection();
27 } catch (Exception e) {
28 e.printStackTrace();
29 return null;
30 }
31 }
32
33 /**
34 * 关闭资源
35 * @param conn
36 * @param sta
37 * @param res
38 */
39 public static void closeConnection(Statement sta, ResultSet res) {
40 try {
41 if (res != null) {
42 res.close();
43 res = null;
44 }
45 if (sta != null) {
46 sta.close();
47 sta = null;
48 }
49
50 } catch (SQLException e) {
51 e.printStackTrace();
52 }
53 }
54 }
注:上述程序,没有关闭连接,是因为用完连接之后,连接又回到了连接池,处于空闲状态。
java:/comp/env为固定路径。 ds_mysql是tomcat中设置的数据源
连接池配置常见错误:
Invalid byte 1 of 1-byte UTF-8 sequence.
原因:
在context.xml文件中使用了中文的注释(这个确实比较坑爹,但确实是这样的)。
解决方案:
把中文的注释去掉即可。
方式二、
1). 在conf/server.xml下的<GlobalNamingResources>节点里配置resource,例如:
1 <Resource name="jdbc/ens"
2 auth="Container"
3 type="javax.sql.DataSource"
4 factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
5 testWhileIdle="true"
6 testOnBorrow="true"
7 testOnReturn="false"
8 validationInterval="30000"
9 timeBetweenEvictionRunsMillis="30000"
10 maxActive="100"
11 minIdle="10"
12 maxWait="10000"
13 initialSize="10"
14 removeAbandonedTimeout="60"
15 removeAbandoned="true"
16 logAbandoned="true"
17 minEvictableIdleTimeMillis="30000"
18 jmxEnabled="true"
19 jdbcInterceptors=
20 "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
21 username="root"
22 password="123"
23 driverClassName="com.mysql.jdbc.Driver"
24 url="jdbc:mysql://localhost:3306/ens"/>
然后,在context.xml文件的<Context></Context>节点中添加如下配置:
1 <ResourceLink global="jdbc/ens" name="jdbc/ens" type="javax.sql.DataSource"/>
global="jdbc/ens" 中的参数值("jdbc/ens")必须和上一段<Resource >配置中的name属性的值保持一样。name="jdbc/ens" 这个可以随便取,
但是在程序中调用的时候,就应该与name的值保持一致。到这里,连接池已经配置好啦。用JSP测试一下:
1 <%@ page language="java" pageEncoding="gbk"%>
2 <%@page import="java.sql.Connection"%>
3 <%@page import="javax.naming.Context"%>
4 <%@page import="javax.naming.InitialContext"%>
5 <%@page import="javax.sql.DataSource"%>
6 <%@page import="java.sql.Statement"%>
7 <%@page import="java.sql.ResultSet"%>
8 <%
9 //连接池的获取
10 Connection conn = null;
11 DataSource ds = null;
12 ResultSet rs =null;
13 Statement stmt = null;
14 Context initCtx = new InitialContext();
15 ds =(DataSource)initCtx.lookup("java:comp/env/jdbc/ens");
16 if(ds!=null){
17 out.println("已经获得DataSource!");
18 out.println("<br>");
19 conn = ds.getConnection();
20 try{
21 stmt = conn.createStatement();
22 String sql ="select * from ens_area";
23 rs = stmt.executeQuery(sql);
24 out.println("以下是从数据库中读取出来的数据:<br>");
25 while(rs.next()){
26 out.println("<br>");
27 out.println(rs.getString("area_name"));
28 }
29 }catch(Exception ex){
30 ex.printStackTrace();
31 }finally{
32 conn.close();
33 rs.close();
34 stmt.close();
35 }
36 }
37 %>
参数介绍:
1. initialSize :连接池启动时创建的初始化连接数量(默认值为0)
2. maxActive :连接池中可同时连接的最大的连接数(默认值为8,调整为20,高峰单机器在20并发左右,自己根据应用场景定)
3. maxIdle:连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限制(默认为8个,maxIdle不能设置太小,因为假如在高负载的情况下,
连接的打开时间比关闭的时间快,会引起连接池中idle的个数 上升超过maxIdle,而造成频繁的连接销毁和创建,类似于jvm参数中的Xmx设置)
4. minIdle:连接池中最小的空闲的连接数,低于这个数量会被创建新的连接(默认为0,调整为5,该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都是需要消耗资源的;
但是不能太大,因为在机器很空闲的时候,也会创建低于minidle个数的连接,类似于jvm参数中的Xmn设置)
5. maxWait :最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置-1表示无限等待(默认为无限,调整为60000ms,避免因
线程池不够用,而导致请求被无限制挂起)
6. poolPreparedStatements:开启池的prepared(默认是false,未调整,经过测试,开启后的性能没有关闭的好。)
7. maxOpenPreparedStatements:开启池的prepared 后的同时最大连接数(默认无限制,同上,未配置)
8. minEvictableIdleTimeMillis :连接池中连接,在时间段内一直空闲, 被逐出连接池的时间
9.(默认为30分钟,可以适当做调整,需要和后端服务端的策略配置相关)
10. removeAbandonedTimeout :超过时间限制,回收没有用(废弃)的连接(默认为 300秒,调整为180)
11. removeAbandoned :超过removeAbandonedTimeout时间后,是否进 行没用连接(废弃)的回收(默认为false,调整为true)
数据库重连机制,参考文章:
http://agapple.iteye.com/blog/791943