zoukankan      html  css  js  c++  java
  • JavaWeb之数据库连接池

    时间:2016-12-2 23:56

    ——DBCP连接池

    连接池参数(所有连接池参数都有默认值):
        初始大小
        最小空闲连接数
        增量
        最大空闲连接数
        最大连接数
        最长等待时间

    四大连接参数:
        连接池也是使用四大连接参数来完成创建连接对象的。

    实现的接口:
        连接池必须实现:javax.sql.DataSource接口。

    连接池返回的Connection对象,它的close()方法并不是关闭连接,而是把连接归还给连接池,使用的是装饰设计模式。

    dbcp.properties配置:

    #基本配置
    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mydb
    username=root
    password=root

    #初始化池大小,即一开始池中连接对象的数量
    #默认值为0
    initialSize=0

    #最大连接数,如果设置maxActive=50时,表示池中最多可以有50个连接,包含使用和未使用的连接
    #默认为8,如果设置为非正数,表示无限大
    maxActive=8

    #最大空闲连接数
    #默认为8,如果设置为非正数,表示无限大
    maxIdle=8

    #最小空闲连接数
    #默认值为0
    minIdle=0

    #最大等待时间
    #当设置maxWait=5000时,表示等待5秒,超时会抛出异常
    #默认值为-1,表示无期限等待,超时不会抛异常
    maxWait=-1

    #连接属性
    #就是之前放在url之后的参数,现在可以使用connectionPreperties来指定
    #userServerPrepStmts=true,表示MySQL开启预编译功能。
    #cachePrepStmts=true,表示MySQL开启缓存PrepareStatement功能。
    #prepStmtCacheSize=50,表示缓存PreparedStatement的上限。
    #prepStmtCacheSqlLimit=300,当SQL模板长度大于200时,就不再缓存它。

    #连接的默认提交方式
    #默认值为true,表示自动提交事务
    defaultAutoCommit=true

    #连接是否为只读连接
    #Connection有一对方法,setReadOnly(boolean)和isReadOnly()
    #如果是只读连接,那么只能用这个连接来做查询
    #指定连接为只读是为了优化,这个优化与并发事务相关
    defaultReadOnly=false

    #指定事务的事务隔离级别
    #可选值:NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
    #如果没有指定,那么由驱动中的Connection类自己来决定。
    defaultTransactionIsolation=REPEATABLE_READ

    import java.sql.Connection;
    import java.sql.SQLException;
     
    import org.apache.commons.dbcp.BasicDataSource;
    import org.junit.Test;
     
    /**
     * DBCP连接池
     * 
     * @author 31067
     * 
     */
    public class Demo01 {
        @Test
        public void fun1() throws Exception {
            /*
             * 1、创建连接池对象 2、配置四大参数 3、配置连接池 4、得到连接池对象
             */
            BasicDataSource dataSource = new BasicDataSource();
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost:3306/mydb3");
            dataSource.setUsername("root");
            dataSource.setPassword("Admin123");
            // 最大活动连接数
            dataSource.setMaxActive(20);
            // 最小空闲连接
            dataSource.setMinIdle(3);
            // 最大不活动时间
            dataSource.setMaxWait(1000);
     
            Connection conn = dataSource.getConnection();
            System.out.println(conn.getClass().getName());
     
            /**
             * 连接池内部使用四大参数创建了连接对象,即MySQL驱动提供的Connection
             * 连接池使用MySQL的连接对象进行了装饰,只对close()方法进行了增强。
             * 原close()调用之后会关闭连接,装饰之后的close()方法会把当前连接归还给连接池
             */
            conn.close();
        }
    }




    ——装饰设计模式

    对象增强的手段:
        1)继承
            *   被增强的对象是固定的
            *   增强的内容也是固定的

        2)装饰设计模式
            *   被增强的对象是可以切换的
            *   增强的内容时固定的

        3)动态代理
            *   被增强的对象可以切换
            *   增强的内容也可以切换


    是你还有你,一切拜托你。
    是你:继承或实现要装饰类的接口
    还有你:内部使用构造方法保存要修饰类的对象
    一切拜托你:

    class MyConnection implements Connection {    //是你
        //还有你
        private  Connection conn;    //底层对象,也是被增强对象

        //通过构造器传递底层对象
        public MyConnection(Connection conn){    //使用父类接口接受参数,保证能够接收任意参数
            this.conn = conn;
        }

        //一切拜托你,表示使用底层对象来调用全部方法
        public Statement createStatement() {
            return conn.createStatement();
        }

        //被装饰(增强)方法
        public void close() {
            将当前连接归还给连接池,而不是关闭。
        }
    }



    ——C3P0连接池

    C3P0是开源免费的连接池。


    import java.sql.Connection;
     
    import org.junit.Test;
     
    import com.mchange.v2.c3p0.ComboPooledDataSource;
     
    /**
     * 演示C3P0
     * 手动配置参数
     * @author 31067
     * 
     */
    public class Demo01 {
        @Test
        public void fun1() throws Exception {
            // 创建连接池对象
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
     
            // 对连接池进行四大参数配置
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb3");
            dataSource.setUser("root");
            dataSource.setPassword("Admin123");
     
            // 配置连接池参数
            dataSource.setAcquireIncrement(5); // 增量
            dataSource.setInitialPoolSize(20); // 初始化连接
            dataSource.setMinPoolSize(2); // 最小连接数
            dataSource.setMaxPoolSize(50); // 最大连接数
     
            Connection conn = dataSource.getConnection();
            System.out.println(conn);
            conn.close();
        }
    }

    输出结果:com.mchange.v2.c3p0.impl.NewProxyConnection@6adca536
    可以看到实现的是c3p3接口,并且创建了一个新的动态代理,而非装饰类。

    ——使用C3P0配置文件创建连接池
     
    配置文件要求:
        1、文件名称:必须是 c3p0-config.xml
        2、文件位置:必须在src目录下。

    c3p0也可以指定配置文件,而且配置文件可以是properties,也可以是XML文件,当然,XML更高级一些。但是c3p0的配置文件名必须为c3p0-config.xml,并且必须放在类路径下。



    配置文件信息:

    <?xml version="1.0" encoding="UTF-8"?>
     
    <c3p0-config>
        <!-- 默认配置 -->
        <default-config>
            <!-- 连接四大参数配置 -->
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb3</property>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="user">root</property>
            <property name="password">Admin123</property>
            <!-- 连接池参数配置 -->
            <property name="acquireIncrement">3</property>
            <property name="initialPoolSize">10</property>
            <prpperty name="minPoolSize">2</prpperty>
            <property name="maxPoolSize">10</property>
        </default-config>
     
        <!-- 指定名称的配置参数 -->
        <name-config name="oracle-config">
            <!-- 连接四大参数配置 -->
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="user">root</property>
            <property name="password">Admin123</property>
            <!-- 连接池参数配置 -->
            <property name="acquireIncrement">3</property>
            <property name="initialPoolSize">10</property>
            <prpperty name="minPoolSize">2</prpperty>
            <property name="maxPoolSize">10</property>
        </name-config>
    </c3p0-config>

    程序代码:

    import java.sql.Connection;
    import java.sql.SQLException;
     
    import org.junit.Test;
     
    import com.mchange.v2.c3p0.ComboPooledDataSource;
     
    /**
     * 演示C3P0 手动配置参数
     * 
     * @author 31067
     * 
     */
    public class Demo01 {
        @Test
        public void fun1() throws Exception {
            // 创建连接池对象
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
     
            // 对连接池进行四大参数配置
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb3");
            dataSource.setUser("root");
            dataSource.setPassword("Admin123");
     
            // 配置连接池参数
            dataSource.setAcquireIncrement(5); // 增量
            dataSource.setInitialPoolSize(20); // 初始化连接
            dataSource.setMinPoolSize(2); // 最小连接数
            dataSource.setMaxPoolSize(50); // 最大连接数
     
            Connection conn = dataSource.getConnection();
            System.out.println(conn);
            conn.close();
        }
     
        /**
         * 使用配置文件的默认配置
         * 
         * @throws Exception
         */
        @Test
        public void fun2() throws Exception {
            /*
             * 在创建连接池对象时,这个对象就会自动加载配置文件,不需要手动指定(无参构造方法)
             */
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            Connection conn = dataSource.getConnection();
            System.out.println(conn);
            conn.close();
        }
     
        /**
         * 使用命名配置信息 <name-config name="oracle-config">
         * 
         * @throws Exception
         */
        @Test
        public void fun3() throws Exception {
            /*
             * 构造器的参数指定了命名配置元素的名称,用来加载指定的配置信息
             */
            ComboPooledDataSource dataSource = new ComboPooledDataSource("oracle-config");
            Connection conn = dataSource.getConnection();
            System.out.println(conn);
            conn.close();
        }
    }

    ——使用C3P0创建JDBCUtils

    import java.sql.Connection;
    import java.sql.SQLException;
     
    import javax.sql.DataSource;
     
    import com.mchange.v2.c3p0.ComboPooledDataSource;
     
    public class JDBCUtils2 {
        //使用的是配置文件的默认配置,即必须给出c3p0-config.xml配置文件
        private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
     
        /*
         * 使用连接池返回一个连接对象
         */
        public static Connection getConnection() throws SQLException{
            return dataSource.getConnection();
        }
     
        /*
         * 返回连接池对象
         */
        public static DataSource getDataSource(){
            return dataSource;
        }
    }
     
    ——Tomcat配置连接池
     
    1、Tomcat配置JNDI资源
        JNDI(Java Naming and Directory Interface),Java命名和目录接口。
        JNDI的作用就是:在服务器上配置资源,然后通过统一的方式来获取配置的资源。

        这里要配置的资源当然是连接池了,这样项目中就可以通过统一的方式来获取连接池对象了。

    2、下面的配置是Tomcat文档提供的:

    <Context .>
        ...
        <Resource name="bean/MyBeanFactory" auth="Container"
            type="com.mycompany.MyBean" factory="org.apache.naming.factory.BeanFactory"
            bar="23" />
    </Context>

    配置JNDI资源需要到<Context>元素中配置<Resource>子元素:
        *   name:指定资源的名称,这个名称可以随便给,在获取资源时需要这个名称。
        *   factory:用来创建资源的工厂,这个值基本是固定的。
        *   type:资源的类型,我们要给出的类型当然是我们连接池的类型了。
            用于生成该类的对象,例如“com.mchange.v2.c3p0.ComboPooledDataSource”。
        *   bar:表示资源的属性,如果资源存在名为bar的属性,那么就配置bar的信息。对于DBCP连接池而言,需要配置的不是bar,因为它没有bar这个属性,而是应该去配置url、username等属性。

    <?xml version="1.0" encoding="UTF-8"?>
     
    <Context>
        <!-- 
            name:指定资源的名称
            factory:指定资源由谁创建
            type:指定资源的类型
            其他相关内容都是资源的参数
         -->
        <Resource name="myc3p0"
            factory="org.apache.naming.factory.BeanFactory"
            type="com.mchange.v2.c3p0.ComboPooledDataSource"
            jdbcUrl="jdbc:mysql://localhost:3306/mydb3"
            driverClass="com.mysql.jdbc.Driver"
            user="root"
            password="Admin123"
            acquireIncrement="5"
            initialPoolSize="10"
            ......
        />
    </Context>

    3、获取资源
        配置资源的目的当然是为了获取资源,只要一启动Tomcat,那么就可以在项目中任何类中通过JNDI获取资源的方式来获取资源了。
        与上面Tomcat文档提供的配置信息对应的获取资源代码如下:

        Context cxt= new InitialContext();
        Context envCxt = (Context)cxt.lookup("java:comp/env");
        MyBean bean = (MyBean)envCxt.lookup("bean/MyBeanFactory");

        Connection conn = bean.getConnection();

        writer.print("foo = " + bean.getFoo() + ", bar = " + bean.getBar());

        获取资源:
            *   Context:javax.naming.Context
            *   InitialContext:javax.naming.InitalContext
            *   lookup(String):获取资源的方法,其中“java:comp/env”是资源的入口(这是固定的名称),获取的对象是一个Context,这说明需要在获取到的Context上进一步进行获取。“bean/MyBeanFactory”对应<Resource>中配置的name的值,通过该name值获取到的就是资源对象了。

    import java.io.IOException;
    import java.sql.Connection;
     
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.sql.DataSource;
     
    /**
     * 获取JNDI资源(数据库连接对象)
     * 
     * @author 31067
     * 
     */
    public class AServlet extends HttpServlet {
     
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
     
     
            try {
                // 1、创建JNDI的上下文对象 
                Context cxt = new InitialContext();
                // 2、查询出入口
                // Context envContext = (Context) cxt.lookup("java:comp/env");
                // 3、再进行第二次查询,找到要查找的资源
                // 使用的名称与<Resource>元素的name属性对应
                // DataSource dataSource = (DataSource)
                // envContext.lookup("jdbc/dataSource");
     
                // 合并代码
                DataSource dataSource = (DataSource) cxt.lookup("java:comp/env/jdbc/dataSource");
     
                // 4、得到连接
                Connection conn = dataSource.getConnection();
                System.out.println(conn);
                conn.close();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }
    }
  • 相关阅读:
    Struts2再曝高危漏洞(S2-020补丁绕过)
    JavaWeb学习总结(十三)——使用Session防止表单重复提交
    JavaWeb学习总结(十二)——Session
    javaweb学习总结(十一)——使用Cookie进行会话管理
    如何做个好员工(转载)
    剖析云计算中的“共享型数据库”(转载)
    云计算的基本概念(转载)
    javaweb学习总结(十)——HttpServletRequest对象(一)
    javaweb学习总结(九)—— 通过Servlet生成验证码图片
    javaweb学习总结(八)——HttpServletResponse对象(二)
  • 原文地址:https://www.cnblogs.com/wwwwyc/p/6375311.html
Copyright © 2011-2022 走看看