You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chat-room/wechat-master/src/com/hyc/wechat/dao/impl/DataSourceImpl.java

272 lines
8.3 KiB

/*
* Copyright (c) 2019. 黄钰朝
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hyc.wechat.dao.impl;
import com.hyc.wechat.dao.DataSource;
import com.hyc.wechat.exception.DaoException;
import com.hyc.wechat.factory.proxy.ConnectionProxy;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @program wechat
* @description 负责向Dao层提供数据库连接
* @date 2019-05-01 16:40
*/
public class DataSourceImpl implements DataSource {
/*
**************************************************************
* 加载配置文件,注册数据库驱动
**************************************************************
*/
/**
* 配置文件路径
*/
private static final String PROP_PATH = "data_source.properties";
private static Properties prop = new Properties();
static {
try {
//加载配置文件
prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(PROP_PATH));
String driver = prop.getProperty("driver");
//注册驱动
Class.forName(driver);
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
throw new ExceptionInInitializerError(e);
}
}
/*
**************************************************************
* 初始化数据库连接池配置
**************************************************************
*/
/**
* 测试数据库连接的等待时长
*/
private static int TIMEOUT = Integer.parseInt(prop.getProperty("TIMEOUT"));
/**
* 初始数据库连接数
*/
private static int INIT_SIZE = Integer.parseInt(prop.getProperty("INIT_SIZE"));
/**
* 最大数据库连接数
*/
private static int MAX_SIZE = Integer.parseInt(prop.getProperty("MAX_SIZE"));
/**
* 当前已经创建的数据库连接数
*/
private static int currentCount = 0;
/**
* 数据库连接链接
*/
private static String url = prop.getProperty("url");
/**
* 数据库连接用户
*/
private static String user = prop.getProperty("user");
/**
* 数据库连接密码
*/
private static String password = prop.getProperty("password");
/*
**************************************************************
* 创建数据源和数据库连接池实例
**************************************************************
*/
/**
* 这里使用饿汉式单例模式
*/
private static DataSourceImpl instance = new DataSourceImpl();
/**
* 数据库连接池
*/
private final Queue<Connection> connPool = new LinkedBlockingQueue<>();
/**
* 负责提供数据库连接池实例
*
* @return com.hyc.www.dao.MyDataSource
* @name getInstance
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @date 2019/5/1
*/
public static DataSourceImpl getInstance() {
if (instance != null) {
return instance;
}else {
return new DataSourceImpl();
}
}
/**
* 创建连接池实例,初始化数据库连接池
*
* @name MyDataSource
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @date 2019/5/1
*/
private DataSourceImpl() {
for (int i = 0; i < INIT_SIZE; i++) {
this.connPool.add(this.createConnection());
}
}
/*
**************************************************************
* 提供接口中数据库连接的操作方法
**************************************************************
*/
/**
* 负责从数据库连接池中获取数据库连接
*
* @return java.sql.Connection
* @throws DaoException 如果数据库连接已经达到最大值时仍然调用此方法,则抛出此异常
* @name getConnection
* @notice 数据库连接的数量受到配置文件中最大值的限制
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @date 2019/5/1
*/
@Override
public Connection getConnection() throws DaoException {
Logger log = Logger.getLogger(DataSourceImpl.class);
log.info("连接池已创建连接数" + getCurrentCount() + "空闲连接数" + getfreeCount());
synchronized (connPool) {
if (connPool.size() > 0) {
/**
* 先检查连接是否可用,如果不可用,关闭该连接,返回一个新连接
*/
Connection conn = connPool.remove();
try {
if (conn.isValid(TIMEOUT)) {
return new ConnectionProxy(this).getProxyInstance(conn);
} else {
destroyConnection(conn);
return createConnection();
}
} catch (SQLException e) {
throw new DaoException("测试数据库连接产生异常", e);
}
} else if (currentCount < MAX_SIZE) {
Connection conn = createConnection();
return new ConnectionProxy(this).getProxyInstance(conn);
} else {
throw new DaoException("数据库连接数已达到最大值");
}
}
}
/**
* 用于将数据库连接放回连接池中
*
* @param conn 数据库连接
* @name freeConnection
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @date 2019/5/1
*/
@Override
public void freeConnection(Connection conn) {
this.connPool.add(conn);
}
/**
* 关闭数据库连接
*
* @return java.sql.Connection
* @name createConnection
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @date 2019/5/1
*/
@Override
public void destroyConnection(Connection conn) {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
throw new DaoException("关闭数据库连接异常", e);
}
}
/**
* 负责返回当前已经创建的连接数
*
* @return int 当前已经创建的连接数
* @name getCurrentCount
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @date 2019/5/1
*/
@Override
public int getCurrentCount() {
return currentCount;
}
/**
* 负责返回当前池中剩余的空闲连接数
*
* @return int 当前空闲连接数
* @name getfreeCount
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @date 2019/5/1
*/
@Override
public int getfreeCount() {
return this.connPool.size();
}
/*
**************************************************************
* 私有方法
**************************************************************
*/
/**
* 创建连接("协议+访问的数据库名”,“用户名”,“密码”)
*
* @return java.sql.Connection
* @name createConnection
* @author <a href="mailto:kobe524348@gmail.com">黄钰朝</a>
* @date 2019/5/1
*/
private Connection createConnection() throws DaoException {
currentCount++;
try {
return DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
throw new DaoException("无法创建数据库连接:" + e.getMessage(), e);
}
}
}