实习笔记 java之连接池与Druid

自己写连接池

事先设置好多条连接存储于LinkedList中,
private static LinkedList list = new LinkedList();
for (int i = 0; i < count; i++) {
// 建立count个连接并放入连接池
list.add(DriverManager.getConnection(url, username, password));
}
每次进行增删改查直接从list取,取完之后把连接进行回收,如果每次增删改查都先建立连接,每次耗时差不多需要半秒钟,而自己写的连接池先把连接建立好储存起来,能有效的降低增删改查时的响应时间。

import java.io.FileInputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;

public class MyConnPoll {
    private static LinkedList<Connection> list = new LinkedList<Connection>();
    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    /**
     * 静态代码块,只在类第一次加载执行
     */
    static {
        try {
            url = "jdbc:mysql://127.0.0.1:3306/qm?useUnicode=true&characterEncoding=utf-8";
            username = "root";
            password = "123";
            driver = "com.mysql.jdbc.Driver";
        } catch (Exception e) {
            e.getStackTrace();
        }
    }

    /**
     * 使用构造函数初始化
     */
    public MyConnPoll() {
        try {
            //注册驱动
            Class.forName(driver);
            initConnection(10);
        } catch (Exception e) {
            System.out.println("初始化连接池失败");
            e.printStackTrace();
        }
    }

    /**
     * 初始化连接池
     *
     * @param count
     * @throws SQLException
     */
    public void initConnection(int count) throws SQLException {
        for (int i = 0; i < count; i++) {
            //     建立count个连接并放入连接池
            list.add(DriverManager.getConnection(url, username, password));
        }
    }


    /**
     * 返回连接池中数量
     *
     * @return
     */
    public int size() {
        return list.size();
    }
    /**
     * 拿到连接
     * @return
     * @throws SQLException
     */
    public  Connection getConnection() throws SQLException {
        if (list.size()==0){
            //如果连接用完了,再初始化一些连接出来
            initConnection(10);
        }
        //list是链表,每次返回list的第一个连接
        return list.removeFirst();
    }

    /**
     * 使用代理模式修改conn对象的close方法
     *
     * @return
     * @throws SQLException
     */
   /* public Connection getConnection() throws SQLException {
        if (list.size()==0){
            initConnection(10);
        }
        final Connection conn=list.removeFirst();
        //代理模式
        return (Connection) Proxy.newProxyInstance(MyConnPoll.class.getClassLoader(),
                new Class[]{Connection.class},
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if (!"close".equals(method.getName())){
                            return method.invoke(conn,args);
                        }else {
                            closeConnection(conn);
                            System.out.println("回收了一个连接,当前连接数是:"+size());
                            return null;
                        }
                    }
                });
    }
*/
    /**
     * 用完回收连接
     *
     * @param conn
     */
    public void closeConnection(Connection conn) {
        list.add(conn);
    }

}

SQL注入

使用
Statement statement = conn.createStatement();
statement.executeQuery(“select * from user where username=’+username+’ “);时
当username的值为 ’ or 1=1 - 时,sql语句查询时会变成
select * from user where username=’’ or 1=1 -’
这条语句被拆分开来,
即username=’’
1=1 永久成立
-’ 这是把后面的全部注释掉
即便表里没有这个值,它的查询也是成功的。注入此类还有很多,比如加入分号;把前面的语句断掉,后面再加新语句。
解决办法是当用户输入时,把一些特殊字符给替换掉,比如:
String name = scanner.nextLine();
String replace = name.replace(”’”,"\’");

更有效的解决方法是不使用Statement,而是使用
String sql = "SELECT * FROM maillist where name like ? ";
//创建运行对象
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,mailList.getName());
去代替Statement,PreparedStatement是基于Statement的,
但在SQL语句中使用问号?去代替拼接的SQL,这样能提高程序的安全性。
且PreparedStatement有预编译的过程,已经绑定sql,之后无论执行多少遍,都不会再去进行编译,
而 statement 不同,如果执行多少遍,则相应的就要编译多少遍sql,所以从这点看,preStatement 的效率会比 Statement要高一些。

Druid

Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。
Maven:

	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid</artifactId>
		<version>1.1.22</version>
	</dependency>

一个连接池框架,能省去许多繁琐的东西。
Druid工具类:

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtils {

    private static DataSource dataSource = null;

    static {
        try {
        /*创建一个与src同级的目录,config,在其下创建一个properties类型文件
        文件中存放driverClassName这里使用的不是driver
                  username、password、url
                  然后用load加载进来。
         甚至在关闭连接时
         JDBCUtils.close();并不是直接关闭,而是回收。
        */
            Properties p = new Properties();
            p.load(JDBCUtils.class.getClassLoader().getResourceAsStream("config/druid.properties"));
            //工厂对象
            DruidDataSourceFactory druidDataSourceFactory = new DruidDataSourceFactory();
            dataSource = druidDataSourceFactory.createDataSource(p);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException {
    //连接
        return dataSource.getConnection();
    }

    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        // 代码的严谨性
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            if (statement != null) {
                statement.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            if (connection != null) {
                connection.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    
}

druid.properties文件中:

driverClassName=com.jdbc.mysql.
url=jdbc:mysql://127.0.0.1:3306/qm
username=root
password=123
#初始化连接数
initialSize=5
#最多连接数
maxActive=10
#...还有更多属性

使用Druid可以省略很多东西,方便开发,更深层次的目前还没掌握。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值