首先调用Class.forName()方法加载数据库驱动,然后调用DriverManager.getConnection()方法建立连接.
连接池解决方案是在应用程序启动时就预先建立多个数据库连接对象,然后将连接对象保存到连接池中。当客户请求到来时,从池中取出一个连接对象为客户服务。当请求完成时,客户程序调用close()方法,将连接对象放回池中.对于多于连接池中连接数的请求,排队等待。应用程序还可根据连接池中连接的使用率,动态增加或减少池中的连接数。
传统方式存在问题
Connection对象在每次执行DML和DQL的过程中都要创建一次,DML和DQL执行完毕后,connection对象都会被销毁. connection对象是可以反复使用的,没有必要每次都创建新的.该对象的创建和销毁都是比较消耗系统资源的,如何实现connection对象的反复使用呢?使用连接池技术实现.
连接池的优势
1、预先准备一些链接对象,放入连接池中,当多个线程并发执行时,可以避免短时间内一次性大量创建链接对象,减少计算机单位时间内的运算压力,提高程序的响应速度
2、实现链接对象的反复使用,可以大大减少链接对象的创建次数,减少资源的消耗
具体实现如下
1、定义连接池
public class MyConnectionPool {
private static String driver ="com.mysql.cj.jdbc.Driver";
private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
private static String user="root";
private static String password="root";
private static int initSize=1;
private static int maxSize=1;
private static LinkedList pool;
static{
// 加载驱动
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 初始化pool
pool=new LinkedList();
// 创建5个链接对象
for (int i = 0; i 0){
connection= pool.removeFirst();// 移除集合中的第一个元素
System.out.println("连接池中还有连接:"+connection.hashCode());
}else{
connection = initConnection();
System.out.println("连接池空,创建新连接:"+connection.hashCode());
}
return connection;
}
// 共有的向连接池归还连接对象的方法
public static void returnConnection(Connection connection){
if(null != connection){
try {
if(!connection.isClosed()){
if(pool.size()
2、修改BaseDao
public abstract class BaseDao {
public int baseUpdate(String sql,Object ... args){
// 向 Emp表中增加一条数据
Connection connection = null;
PreparedStatement preparedStatement=null;
int rows=0;
try{
connection = MyConnectionPool.getConnection();
preparedStatement = connection.prepareStatement(sql);
//设置参数
for (int i = 0; i
配置文件优化参数存储
准备jdbc.properties配置文件,放在src下
准备PropertiesUtil工具类
public class PropertiesUtil {
private Properties properties;
public PropertiesUtil(String path){
properties=new Properties();
InputStream inputStream = this.getClass().getResourceAsStream(path);
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public String getProperties(String key){
return properties.getProperty(key);
}
}
连接池中代码修改
public class MyConnectionPool {
private static String driver;
private static String url;
private static String user;
private static String password;
private static int initSize;
private static int maxSize;
private static LinkedList pool;
static{
// 初始化参数
PropertiesUtil propertiesUtil=new PropertiesUtil("/jdbc.properties");
driver=propertiesUtil.getProperties("driver");
url=propertiesUtil.getProperties("url");
user=propertiesUtil.getProperties("user");
password=propertiesUtil.getProperties("password");
initSize=Integer.parseInt(propertiesUtil.getProperties("initSize"));
maxSize=Integer.parseInt(propertiesUtil.getProperties("maxSize"));
// 加载驱动
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 初始化pool
pool=new LinkedList();
// 创建5个链接对象
for (int i = 0; i 0){
connection= pool.removeFirst();// 移除集合中的第一个元素
System.out.println("连接池中还有连接:"+connection.hashCode());
}else{
connection = initConnection();
System.out.println("连接池空,创建新连接:"+connection.hashCode());
}
return connection;
}
// 共有的向连接池归还连接对象的方法
public static void returnConnection(Connection connection){
if(null != connection){
try {
if(!connection.isClosed()){
if(pool.size()
1) 什么是日志log
异常信息 登录成功失败的信息 其他重要操作的信息
日志可以记录程序的运行状态,运行信息,用户的一些常用操作.日志可以帮助我们分析程序的运行状态,帮我们分析用户的操作习惯,进而对程序进行改进
2) 如何记录日志
方式1:System.out.println(.....) e.printStackTrace();
缺点:不是保存到文件,不能长久存储
方式2:IO流 将System.out.println(.....) e.printStackTrace();写入文件
缺点:操作繁琐,IO流操作容易阻塞线程,日志没有等级,日志的格式不能很好的定制,要想实行编程复杂
方式3:使用现成的日志框架,比如log4j
优点:1长久保存 2有等级3格式可以很好的定制 4代码编写简单
3) log4j日志的级别
FATAL: 指出现非常严重的错误事件,这些错误可能导致应用程序异常中止
ERROR: 指虽有错误,但仍允许应用程序继续运行
WARN: 指运行环境潜藏着危害
INFO: 指报告信息,这些信息在粗粒度级别上突出显示应用程序的进程
DEBUG: 指细粒度信息事件,对于应用程序的调试是最有用的
4) 使用log4j记录日志
1.加入jar包 log4j-1.2.8.jar
2.加入属性文件 src 下 log4j.properties
通过属性文件理解log4j的主要API
Appender 日志目的地 :ConsoleAppender FileAppender
Layout 日志格式化器 :SimpleLayout PatternLayout
3.代码中记录日志
//创建一个日志记录器
//在合适的地方添加日志
logger.info("正确的读取了属性文件:"+prop);
logger.debug("正确的关闭了结果集");
logger.error("DML操作错误:"+e);
|
5) 理解日志格式化字符的含义
%p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy/MM/dd HH:mm:ss,SSS}。
%r:输出自应用程序启动到输出该log信息耗费的毫秒数。
%t:输出产生该日志事件的线程名。
%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如
test.TestLog4j.main(TestLog4j.java:10)。
%c:输出日志信息所属的类目,通常就是所在类的全名。
%M:输出产生日志信息的方法名。
%F:输出日志消息产生时所在的文件名称。
%L::输出代码中的行号。
%m::输出代码中指定的具体日志信息。
%n:输出一个回车换行符,Windows平台为"rn",Unix平台为"n"。
%x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%:输出一个"%"字符。
6) 使用log4j记录日志 连接池中通过log4j记录日志
public class MyConnectionPool {
private static String driver;
private static String url;
private static String user;
private static String password;
private static int initSize;
private static int maxSize;
private static Logger logger;
private static LinkedList pool;
static{
logger=Logger.getLogger(MyConnectionPool.class);
// 初始化参数
PropertiesUtil propertiesUtil=new PropertiesUtil("/jdbc.properties");
driver=propertiesUtil.getProperties("driver");
url=propertiesUtil.getProperties("url");
user=propertiesUtil.getProperties("user");
password=propertiesUtil.getProperties("password");
initSize=Integer.parseInt(propertiesUtil.getProperties("initSize"));
maxSize=Integer.parseInt(propertiesUtil.getProperties("maxSize"));
// 加载驱动
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
logger.fatal("找不到数据库驱动类"+driver,e);
}
// 初始化pool
pool=new LinkedList();
// 创建5个链接对象
for (int i = 0; i 0){
connection= pool.removeFirst();// 移除集合中的第一个元素
logger.info("连接池中还有连接:"+connection.hashCode());
}else{
connection = initConnection();
logger.info("连接池空,创建新连接:"+connection.hashCode());
}
return connection;
}
// 共有的向连接池归还连接对象的方法
public static void returnConnection(Connection connection){
if(null != connection){
try {
if(!connection.isClosed()){
if(pool.size()