Java jdbc数据库连接池总结

DB连接池满排查 简介:最近遇到线上机器连接池满的情况,排查发现tddl里面在连接池获取和释放流程中有些问题 问题现象: 线上报HSF线程池满,CPU100%。 排查过程: 线程日志dump下来进行分析 Hsf等待线程1:大约400个线程等待获取连接池 at sun.misc.Unsafe.park(Native Method) - waiting on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject. 阅读详情
1. 引言

  近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机

  应用程序已从传统的桌面应用转到Web应用。基于B/S(Browser/Server)架构的3层开发模式逐渐取代C/S(Client/Server)架构的开发模式,成为开发企业级应用和电子商务普遍采用的技术。在Web应用开发的早期,主要使用的技术是CGI﹑ASP﹑PHP等。之后,Sun公司推出了基于Java语言的Servlet+Jsp+JavaBean技术。相比传统的开发技术,它具有跨平台﹑安全﹑有效﹑可移植等特性,这使其更便于使用和开发。

  Java应用程序访问数据库的基本原理

  在Java语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁,

  即Java语言通过JDBC技术访问数据库。JDBC是一种“开放”的方案,它为数据库应用开发人员﹑数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯Java语言编写完整的数据库应用程序。JDBC提供两种API,分别是面向开发人员的API和面向底层的JDBC驱动程序API,底层主要通过直接的JDBC驱动和JDBC-ODBC桥驱动实现与数据库的连接。

  一般来说,Java应用程序访问数据库的过程(如图1所示)是:

  ①装载数据库驱动程序;

  ②通过JDBC建立数据库连接;

  ③访问数据库,执行SQL语句;

  ④断开数据库连接。

图1 Java数据库访问机制

  JDBC作为一种数据库访问技术,具有简单易用的优点。但使用这种模式进行Web应用

  程序开发,存在很多问题:首先,每一次Web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s~1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。可是对于现在的Web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃。不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题。其次,对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将不得不重启数据库。还有,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

 

  数据库连接池(connection pool)的工作原理

  1、基本概念及原理

由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理。我们知道,

  对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。连接池的基本工作原理见下图2。

图2 连接池的基本工作原理

  2、服务器自带的连接池

  JDBC的API中没有提供连接池的方法。一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。

  连接池关键问题分析

  1、并发问题

  为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为Java语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字,如:

public synchronized Connection getConnection()

  2、多数据库服务器和多用户

  对于大型的企业级应用,常常需要同时连接不同的数据库(如连接Oracle和Sybase)。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址(<poolName.url>)﹑用户名(<poolName.user>)﹑密码(<poolName.password>)等信息。如tx.url=192.168.1.123:5000/tx_it,tx.user=cyl,tx.password=123456。根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。

  对于同一个数据库有多个用户使用不同的名称和密码访问的情况,也可以通过资源文件处理,即在资源文件中设置多个具有相同url地址,但具有不同用户名和密码的数据库连接信息。

  3、事务处理

  我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。

在Java语言中,Connection类本身提供了对事务的支持,可以通过设置Connection的AutoCommit属性为false,然后显式的调用commit或rollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。

  4、连接池的分配与释放

  连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。

  对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxConn),如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法。

  5、连接池的配置与维护

  连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。

  如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。

连接池的实现

  1、连接池模型

  本文讨论的连接池包括一个连接池类(DBConnectionPool)和一个连接池管理类(DBConnetionPoolManager)和一个配置文件操作类(ParseDSConfig)。连接池类是对某一数据库所有连接的“缓冲池”,主要实现以下功能:①从连接池获取或创建可用连接;②使用完毕之后,把连接返还给连接池;③在系统关闭前,断开所有连接并释放连接占用的系统资源;④还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。(5)当多数据库时,且数据库是动态增加的话,将会加到配置文件中。

  连接池管理类是连接池类的外覆类(wrapper),符合单例模式,即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理,具有以下功能:①装载并注册特定数据库的JDBC驱动程序;②根据属性文件给定的信息,创建连接池对象;③为方便管理多个连接池对象,为每一个连接池对象取一个名字,实现连接池名字与其实例之间的映射;④跟踪客户使用连接情况,以便需要是关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理,如系统需要连接不同的数据库,或连接相同的数据库但由于安全性问题,需要不同的用户使用不同的名称和密码。

         2、连接池实现(经过本人改版,可以适用多数据库类型的应用以及一种数据库类型多个数据库且数据  库的数量可以动态增加的应用程序)

         1),DBConnectionPool.java   数据库连接池类

         2),DBConnectionManager .java   数据库管理类

         3),DSConfigBean .java                单个数据库连接信息Bean

         4),ParseDSConfig.java                操作多(这个'多'包括不同的数据库和同一种数据库有多个数据库)

                                                            数据 配置文件xml

         5),ds.config.xml                           数据库配置文件xml

         原代码如下: 

        DBConnectionPool.java  

        ----------------------------------------------------------

      /**

 * 数据库连接池类

 */

package com.chunkyo.db;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.Timer;

/**

 * @author chenyanlin

 *

 */

public class DBConnectionPool implements TimerListener {

 private Connection con=null;

 private int inUsed=0;    //使用的连接数

 private ArrayList freeConnections = new ArrayList();//容器,空闲连接

 private int minConn;     //最小连接数

 private int maxConn;     //最大连接

 private String name;     //连接池名字

 private String password; //密码

 private String url;      //数据库连接地址

 private String driver;   //驱动

 private String user;     //用户名

 public Timer timer;      //定时

 /**

  *

  */

 public DBConnectionPool() {

  // TODO Auto-generated constructor stub

 }

 /**

  * 创建连接池

  * @param driver

  * @param name

  * @param URL

  * @param user

  * @param password

  * @param maxConn

  */

 public DBConnectionPool(String name, String driver,String URL, String user, String password, int maxConn)

 {

  this.name=name;

  this.driver=driver;

  this.url=URL;

  this.user=user;

  this.password=password;

  this.maxConn=maxConn;

 }

 /**

  * 用完,释放连接

  * @param con

  */

 public synchronized void freeConnection(Connection con)

 {

  this.freeConnections.add(con);//添加到空闲连接的末尾

  this.inUsed--;

 }

 /**

  * timeout  根据timeout得到连接

  * @param timeout

  * @return

  */

 public synchronized Connection getConnection(long timeout)

 {

  Connection con=null;

  if(this.freeConnections.size()>0)

  {

   con=(Connection)this.freeConnections.get(0);

   if(con==null)con=getConnection(timeout); //继续获得连接

  }

  else

  {

   con=newConnection(); //新建连接

  }

  if(this.maxConn==0||this.maxConn<this.inUsed)

  {

   con=null;//达到最大连接数,暂时不能获得连接了。

  }

  if(con!=null)

  {

   this.inUsed++;

  }

  return con;

 }

 /**

  *

  * 从连接池里得到连接

  * @return

  */

 public synchronized Connection getConnection()

 {

  Connection con=null;

  if(this.freeConnections.size()>0)

  {

   con=(Connection)this.freeConnections.get(0);

   this.freeConnections.remove(0);//如果连接分配出去了,就从空闲连接里删除

   if(con==null)con=getConnection(); //继续获得连接

  }

  else

  {

   con=newConnection(); //新建连接

  }

  if(this.maxConn==0||this.maxConn<this.inUsed)

  {

   con=null;//等待 超过最大连接时

  }

  if(con!=null)

  {

   this.inUsed++;

   System.out.println("得到 "+this.name+" 的连接,现有"+inUsed+"个连接在使用!");

  }

  return con;

 }

 /**

  *释放全部连接

  *

  */

 public synchronized void release()

 {

  Iterator allConns=this.freeConnections.iterator();

  while(allConns.hasNext())

  {

   Connection con=(Connection)allConns.next();

   try

   {

    con.close();

   }

   catch(SQLException e)

   {

    e.printStackTrace();

   }

   

  }

  this.freeConnections.clear();

   

 }

 /**

  * 创建新连接

  * @return

  */

 private Connection newConnection()

 {

  try {

   Class.forName(driver);

   con=DriverManager.getConnection(url, user, password);

  } catch (ClassNotFoundException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

   System.out.println("sorry can't find db driver!");

  } catch (SQLException e1) {

   // TODO Auto-generated catch block

   e1.printStackTrace();

   System.out.println("sorry can't create Connection!");

  }

  return con;

  

 }

 /**

  * 定时处理函数

  */

 public synchronized void TimerEvent()

 {

     //暂时还没有实现以后会加上的

 }

 /**

  * @param args

  */

 public static void main(String[] args) {

  // TODO Auto-generated method stub

 }

 /**

  * @return the driver

  */

 public String getDriver() {

  return driver;

 }

 /**

  * @param driver the driver to set

  */

 public void setDriver(String driver) {

  this.driver = driver;

 }

 /**

  * @return the maxConn

  */

 public int getMaxConn() {

  return maxConn;

 }

 /**

  * @param maxConn the maxConn to set

  */

 public void setMaxConn(int maxConn) {

  this.maxConn = maxConn;

 }

 /**

  * @return the minConn

  */

 public int getMinConn() {

  return minConn;

 }

 /**

  * @param minConn the minConn to set

  */

 public void setMinConn(int minConn) {

  this.minConn = minConn;

 }

 /**

  * @return the name

  */

 public String getName() {

  return name;

 }

 /**

  * @param name the name to set

  */

 public void setName(String name) {

  this.name = name;

 }

 /**

  * @return the password

  */

 public String getPassword() {

  return password;

 }

 /**

  * @param password the password to set

  */

 public void setPassword(String password) {

  this.password = password;

 }

 /**

  * @return the url

  */

 public String getUrl() {

  return url;

 }

 /**

  * @param url the url to set

  */

 public void setUrl(String url) {

  this.url = url;

 }

 /**

  * @return the user

  */

 public String getUser() {

  return user;

 }

 /**

  * @param user the user to set

  */

 public void setUser(String user) {

  this.user = user;

 }

}

 

-------------------------------------------

 DBConnectionManager .java

------------------------------------------

/**

 * 数据库连接池管理类

 */

package com.chunkyo.db;

import java.sql.Connection;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.HashMap;

import java.util.Hashtable;

import java.util.Iterator;

import java.util.Properties;

import java.util.Vector;

import com.chunkyo.db.ParseDSConfig;

import com.chunkyo.db.DSConfigBean;

import com.chunkyo.db.DBConnectionPool;

/**

 * @author chenyanlin

 *

 */

public class DBConnectionManager {

 static private DBConnectionManager instance;//唯一数据库连接池管理实例类

 static private int clients;                 //客户连接数

 private Vector drivers  = new Vector();//驱动信息

 private Hashtable pools=new Hashtable();//连接池

 

 /**

  * 实例化管理类

  */

 public DBConnectionManager() {

  // TODO Auto-generated constructor stub

  this.init();

 }

 /**

  * 得到唯一实例管理类

  * @return

  */

 static synchronized public DBConnectionManager getInstance()

 {

  if(instance==null)

  {

   instance=new DBConnectionManager();

  }

  return instance;

  

 }

 /**

  * 释放连接

  * @param name

  * @param con

  */

 public void freeConnection(String name, Connection con)

 {

  DBConnectionPool pool=(DBConnectionPool)pools.get(name);//根据关键名字得到连接池

  if(pool!=null)

  pool.freeConnection(con);//释放连接

 }

 /**

  * 得到一个连接根据连接池的名字name

  * @param name

  * @return

  */

 public Connection getConnection(String name)

 {

  DBConnectionPool pool=null;

  Connection con=null;

  pool=(DBConnectionPool)pools.get(name);//从名字中获取连接池

  con=pool.getConnection();//从选定的连接池中获得连接

  if(con!=null)

  System.out.println("得到连接。。。");

  return con;

 }

 /**

  * 得到一个连接,根据连接池的名字和等待时间

  * @param name

  * @param time

  * @return

  */

 public Connection getConnection(String name, long timeout)

 {

  DBConnectionPool pool=null;

  Connection con=null;

  pool=(DBConnectionPool)pools.get(name);//从名字中获取连接池

  con=pool.getConnection(timeout);//从选定的连接池中获得连接

  System.out.println("得到连接。。。");

  return con;

 }

 /**

  * 释放所有连接

  */

 public synchronized void release()

 {

  Enumeration allpools=pools.elements();

  while(allpools.hasMoreElements())

  {

   DBConnectionPool pool=(DBConnectionPool)allpools.nextElement();

   if(pool!=null)pool.release();

  }

  pools.clear();

 }

 /**

  * 创建连接池

  * @param props

  */

 private void createPools(DSConfigBean dsb)

 {

  DBConnectionPool dbpool=new DBConnectionPool();

  dbpool.setName(dsb.getName());

  dbpool.setDriver(dsb.getDriver());

  dbpool.setUrl(dsb.getUrl());

  dbpool.setUser(dsb.getUsername());

  dbpool.setPassword(dsb.getPassword());

  dbpool.setMaxConn(dsb.getMaxconn());

  System.out.println("ioio:"+dsb.getMaxconn());

  pools.put(dsb.getName(), dbpool);

 }

 /**

  * 初始化连接池的参数

  */

 private void init()

 {

  //加载驱动程序

  this.loadDrivers();

  //创建连接池

  Iterator alldriver=drivers.iterator();

  while(alldriver.hasNext())

  {

   this.createPools((DSConfigBean)alldriver.next());

   System.out.println("创建连接池。。。");

   

  }

  System.out.println("创建连接池完毕。。。");

 }

 /**

  * 加载驱动程序

  * @param props

  */

 private void loadDrivers()

 {

  ParseDSConfig pd=new ParseDSConfig();

 //读取数据库配置文件

  drivers=pd.readConfigInfo("ds.config.xml");

  System.out.println("加载驱动程序。。。");

 }

 /**

  * @param args

  */

 public static void main(String[] args) {

  // TODO Auto-generated method stub

 }

}

----------------------------------------

DSConfigBean.java

----------------------------------------

/**

 * 配置文件Bean类

 */

package com.chunkyo.db;

/**

 * @author chenyanlin

 *

 */

public class DSConfigBean {

 private String type     =""; //数据库类型

 private String name     =""; //连接池名字

 private String driver   =""; //数据库驱动

 private String url      =""; //数据库url

 private String username =""; //用户名

 private String password =""; //密码

 private int maxconn  =0; //最大连接数

 /**

  *

  */

 public DSConfigBean() {

  // TODO Auto-generated constructor stub

 }

 /**

  * @param args

  */

 public static void main(String[] args) {

  // TODO Auto-generated method stub

 }

 /**

  * @return the driver

  */

 public String getDriver() {

  return driver;

 }

 /**

  * @param driver the driver to set

  */

 public void setDriver(String driver) {

  this.driver = driver;

 }

 /**

  * @return the maxconn

  */

 public int getMaxconn() {

  return maxconn;

 }

 /**

  * @param maxconn the maxconn to set

  */

 public void setMaxconn(int maxconn) {

  this.maxconn = maxconn;

 }

 /**

  * @return the name

  */

 public String getName() {

  return name;

 }

 /**

  * @param name the name to set

  */

 public void setName(String name) {

  this.name = name;

 }

 /**

  * @return the password

  */

 public String getPassword() {

  return password;

 }

 /**

  * @param password the password to set

  */

 public void setPassword(String password) {

  this.password = password;

 }

 /**

  * @return the type

  */

 public String getType() {

  return type;

 }

 /**

  * @param type the type to set

  */

 public void setType(String type) {

  this.type = type;

 }

 /**

  * @return the url

  */

 public String getUrl() {

  return url;

 }

 /**

  * @param url the url to set

  */

 public void setUrl(String url) {

  this.url = url;

 }

 /**

  * @return the username

  */

 public String getUsername() {

  return username;

 }

 /**

  * @param username the username to set

  */

 public void setUsername(String username) {

  this.username = username;

 }

}

-----------------------------------------------------

ParseDSConfig.java

-----------------------------------------------------

/**

 * 操作配置文件类 读  写 修改 删除等操作

 */

package com.chunkyo.db;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.List;

import java.util.Vector;

import java.util.Iterator;

import org.jdom.Document;

import org.jdom.Element;

import org.jdom.JDOMException;

import org.jdom.input.SAXBuilder;

import org.jdom.output.Format;

import org.jdom.output.XMLOutputter;

/**

 * @author chenyanlin

 *

 */

public class ParseDSConfig {

 /**

  * 构造函数

  */

 public ParseDSConfig() {

  // TODO Auto-generated constructor stub

 }

 /**

  * 读取xml配置文件

  * @param path

  * @return

  */

 public Vector readConfigInfo(String path)

 {

  String rpath=this.getClass().getResource("").getPath().substring(1)+path;

  Vector dsConfig=null;

  FileInputStream fi = null;

  try

  {

   fi=new FileInputStream(rpath);//读取路径文件

   dsConfig=new Vector();

   SAXBuilder sb=new SAXBuilder();

   Document doc=sb.build(fi);

   Element root=doc.getRootElement();

   List pools=root.getChildren();

   Element pool=null;

   Iterator allPool=pools.iterator();

   while(allPool.hasNext())

   {

    pool=(Element)allPool.next();

    DSConfigBean dscBean=new DSConfigBean();

    dscBean.setType(pool.getChild("type").getText());

    dscBean.setName(pool.getChild("name").getText());

    System.out.println(dscBean.getName());

    dscBean.setDriver(pool.getChild("driver").getText());

    dscBean.setUrl(pool.getChild("url").getText());

    dscBean.setUsername(pool.getChild("username").getText());

    dscBean.setPassword(pool.getChild("password").getText());

    dscBean.setMaxconn(Integer.parseInt(pool.getChild("maxconn").getText()));

    dsConfig.add(dscBean);

   }

   

  } catch (FileNotFoundException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  } catch (JDOMException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  } catch (IOException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  }

  

  finally

  {

   try {

    fi.close();

   } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

   }

  }

  

  return dsConfig;

 }

/**

 *修改配置文件 没时间写 过段时间再贴上去 其实一样的

 */

 public void modifyConfigInfo(String path,DSConfigBean dsb) throws Exception

 {

  String rpath=this.getClass().getResource("").getPath().substring(1)+path;

  FileInputStream fi=null; //读出

  FileOutputStream fo=null; //写入

  

 }

/**

 *增加配置文件

 *

 */

 public void addConfigInfo(String path,DSConfigBean dsb)

 {

  String rpath=this.getClass().getResource("").getPath().substring(1)+path;

  FileInputStream fi=null;

  FileOutputStream fo=null;

  try

  {

   fi=new FileInputStream(rpath);//读取xml流

   

   SAXBuilder sb=new SAXBuilder();

   

   Document doc=sb.build(fi); //得到xml

   Element root=doc.getRootElement();

   List pools=root.getChildren();//得到xml子树

   

   Element newpool=new Element("pool"); //创建新连接池

   

   Element pooltype=new Element("type"); //设置连接池类型

   pooltype.setText(dsb.getType());

   newpool.addContent(pooltype);

   

   Element poolname=new Element("name");//设置连接池名字

   poolname.setText(dsb.getName());

   newpool.addContent(poolname);

   

   Element pooldriver=new Element("driver"); //设置连接池驱动

   pooldriver.addContent(dsb.getDriver());

   newpool.addContent(pooldriver);

   

   Element poolurl=new Element("url");//设置连接池url

   poolurl.setText(dsb.getUrl());

   newpool.addContent(poolurl);

   

   Element poolusername=new Element("username");//设置连接池用户名

   poolusername.setText(dsb.getUsername());

   newpool.addContent(poolusername);

   

   Element poolpassword=new Element("password");//设置连接池密码

   poolpassword.setText(dsb.getPassword());

   newpool.addContent(poolpassword);

   

   Element poolmaxconn=new Element("maxconn");//设置连接池最大连接

   poolmaxconn.setText(String.valueOf(dsb.getMaxconn()));

   newpool.addContent(poolmaxconn);

   pools.add(newpool);//将child添加到root

   Format format = Format.getPrettyFormat();

      format.setIndent("");

      format.setEncoding("utf-8");

      XMLOutputter outp = new XMLOutputter(format);

      fo = new FileOutputStream(rpath);

      outp.output(doc, fo);

  } catch (FileNotFoundException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  } catch (JDOMException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  } catch (IOException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  }

  finally

  {

   

  }

 }

 /**

  *删除配置文件

  */

 public void delConfigInfo(String path,String name)

 {

  String rpath=this.getClass().getResource("").getPath().substring(1)+path;

  FileInputStream fi = null;

  FileOutputStream fo=null;

  try

  {

   fi=new FileInputStream(rpath);//读取路径文件

   SAXBuilder sb=new SAXBuilder();

   Document doc=sb.build(fi);

   Element root=doc.getRootElement();

   List pools=root.getChildren();

   Element pool=null;

   Iterator allPool=pools.iterator();

   while(allPool.hasNext())

   {

    pool=(Element)allPool.next();

    if(pool.getChild("name").getText().equals(name))

    {

     pools.remove(pool);

     break;

    }

   }

   Format format = Format.getPrettyFormat();

      format.setIndent("");

      format.setEncoding("utf-8");

      XMLOutputter outp = new XMLOutputter(format);

      fo = new FileOutputStream(rpath);

      outp.output(doc, fo);

   

  } catch (FileNotFoundException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  } catch (JDOMException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  } catch (IOException e) {

   // TODO Auto-generated catch block

   e.printStackTrace();

  }

  

  finally

  {

   try {

    fi.close();

   } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

   }

  }

 }

 /**

  * @param args

  * @throws Exception

  */

 public static void main(String[] args) throws Exception {

  // TODO Auto-generated method stub

  ParseDSConfig pd=new ParseDSConfig();

  String path="ds.config.xml";

  pd.readConfigInfo(path);

  //pd.delConfigInfo(path, "tj012006");

  DSConfigBean dsb=new DSConfigBean();

  dsb.setType("oracle");

  dsb.setName("yyy004");

  dsb.setDriver("org.oracle.jdbc");

  dsb.setUrl("jdbc:oracle://localhost");

  dsb.setUsername("sa");

  dsb.setPassword("");

  dsb.setMaxconn(1000);

  pd.addConfigInfo(path, dsb);

  pd.delConfigInfo(path, "yyy001");

 }

}

--------------------------------------

ds.config.xml   配置文件

--------------------------------------

<ds-config>

<pool>

<type>mysql</type>

<name>user</name>

<driver>com.mysql.jdbc.driver</driver>

<url>jdbc:mysql://localhost:3306/user</url>

<username>sa</username>

<password>123456</password>

<maxconn>100</maxconn>

</pool>

<pool>

<type>mysql</type>

<name>user2</name>

<driver>com.mysql.jdbc.driver</driver>

<url>jdbc:mysql://localhost:3306/user2</url>

<username>sa</username>

<password>1234</password>

<maxconn>10</maxconn>

</pool>

<pool>

<type>sql2000</type>

<name>books</name>

<driver>com.microsoft.sqlserver.driver</driver>

<url>jdbc:sqlserver://localhost:1433/books:databasename=books</url>

<username>sa</username>

<password></password>

<maxconn>100</maxconn>

</pool>

</ds-config>

3. 连接池的使用

  1。Connection的获得和释放

  DBConnectionManager   connectionMan=DBConnectionManager .getInstance();//得到唯一实例

   //得到连接

   String name="mysql";//从上下文得到你要访问的数据库的名字

   Connection  con=connectionMan.getConnection(name);

  //使用

  。。。。。。。

  // 使用完毕

 connectionMan.freeConnection(name,con);//释放,但并未断开连接

 2。数据库连接的动态增加和连接池的动态增加

      1。调用xml操作增加类

      2。重新实例华连接池管理池类

Java数据库连接池原理及spring boot使用数据库连接池(HikariCP、Druid) - druid连接池核心包,不是spring boot官方提供的组件一般没有定义默认版本,所以需要指定版本 --> < dependency > < groupId > com.alibaba < artifactId > druid < version > 1.2.8 阅读详情

相关推荐

java通过jdbc连接Oracle通过数据库连接池实现增删改查

java通过jdbc连接Oracle通过数据库连接池实现增删改查

sunsiyuan521的博客 7670

Java-数据库连接池

1)预先在缓冲池中放入一定数量的链接,当需要建立数据库连接时,只需要从“缓冲池”中取出,使用完毕后再“放回”;2)数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立;3)当应用程序向连接池请求的连接数量超过最大连接数量时,这些请求将被加入到等待队列中。

Ego_Ekko的博客 6295

重温JDBC(Java Database Connectivity) Java数据库连接 : JDBC快速入门、核心API讲解、Druid连接池、JDBC工具类封装

准备数据库。官网下载数据库连接驱动jar包。创建Java项目,在项目下创建lib文件夹,将下载的驱动jar包复制到文件夹里。选中lib文件夹右键->Add as Library,与项目集成。编写代码贾琏欲执事 (加载驱动-建立连接-编写SQL语句-执行SQL-释放连接资源)注册驱动【依赖的驱动类,进行安装】获取连接【Connection建立连接】创建发送SQL语句对象【Connection创建发送SQL语句的Statement】

Guizy 593

详解数据库连接池概念、原理、运行机制等

概述   数据库连接池是负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。那么其中的运行机制又是怎样的呢?今天主要介绍一下数据库连接池原理和常用的连接池。 01 为什么要使用连接池   数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。 一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,...

weixin_30485379的博客 803

JAVA——> 数据库连接池(c3p0和druid)以及Spring JDBC : JDBC Template

今日内容 1. 数据库连接池 2. Spring JDBC : JDBC Template Ps:本节内容需要导入jar包 数据库连接池 1. 概念:其实就是一个容器(集合),存放数据库连接的容器。 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。 2. 好处: 1. 节约资源 2. 用...

JAVA求生之路——博主406766467 297

双通道中频信号数字下变频及相位差估计(FPGA)

双通道中频信号数字下变频及相位差估计实验 一、上框图(通俗易懂) 二、实验要求 1、 用点频信号模拟中频信号:中频信号由DDS1和DDS2产生。具体产生方法见第2点。 2、 DDS1和 DDS2:调用IPcore里的数字信号处理中的NCO模块,工作时钟为100MHz,数据率即为100MHz,DDS1和DDS2的频率为:(学号后三位+500)Khz+f0(可设为20MHz);输出为16位;DDS1...

qq_39809425的博客 6948

什么是 Java 中的数据库连接池?为什么使用连接池来管理数据库连接?

数据库连接池(database connection pool)是在 Java 中用于管理数据库连接的一种技术。它的主要目的是提高数据库连接的重用性和性能。在传统的数据库连接方式中,每次与数据库建立连接时都需要进行一系列的网络通信和身份验证操作,这样的开销较大并且会影响应用程序的性能。而连接池则通过预先创建一定数量的数据库连接,并将这些连接保存在一个池中,供应用程序随时使用和归还。

Java智慧阁 2407

携程旅行网景区,评论数据爬虫项目数据库保存附源码

这是一个专门用于爬取某旅行网景区评论数据的Python爬虫项目。项目采用模块化设计,支持MySQL数据库存储,具备完整的异常处理机制和反爬虫策略。

ymqzhy的博客 2572

Java 的JDBC 数据库连接池实现方法

Java 的JDBC 数据库连接池实现方法 关键字: Java, JDBC, Connection Pool, Database, 数据库连接池, sourcecode  虽然 J2EE 程序员一般都有现成的应用服务器所带的JDBC 数据库连接池,不过对于开发一般的 Java Application 、 Applet 或者 JSP、velocity 时,我们可用的JDBC 数据库连接池并不

jacklondon的专栏 1967

WinForm实战:如何用C#和PdfiumViewer打造一个功能齐全的PDF阅读器(含源码)

本文详细介绍了如何使用C#和PdfiumViewer库从零开始构建一个功能齐全的WinForm PDF阅读器。内容涵盖项目环境搭建、核心组件解析、基于命令模式的工具栏与UI架构设计,并深入讲解了智能缩放、页面导航、打印功能等核心交互的实现,以及内存管理和性能优化等高级话题,为开发者提供了一套完整的实战解决方案。

docker8compose的博客 505

电源完整性之Cadence Sigrity Power DC_IR_Drop仿真

之前和大家分享过电源完整性之仿真设计原理链接: link.今天接着上一篇文章总结一下电源直流压降的的仿真操作流程及一些simulation中的设置参数,用到的时候Cadence Sigrity 中的Power DC组件,下面开始享受仿真的快乐吧: 1.仿真模式选择与文件导入 选择Cadence Sigrity下的Power DC组件,然后先择licence,最后就可以打开我们之前转化好的.SPD文件。操作如下图: 2.设置层叠信息和过孔焊盘参数 层叠信息:每层的介质厚度、材料、介电常数、介质损耗角等,如

刘小同学的博客 1万+

Java—JDBC 和数据库连接池

介绍了JDBC的基本原理、模拟实现及其优势,展示了Java通过JDBC API连接数据库、执行增删改查操作的具体步骤

2401_88623584的博客 1180

QGis 相关技术、疑难杂症文章合集(掌握后可自封大侠 ⓿_⓿)(记得收藏,持续更新中...)

QGis 相关技术、疑难杂症文章合集(掌握后可自封大侠 ⓿_⓿)(记得收藏,持续更新中...)

280

java 读取db3 数据库_JDBC java数据连接 读取properties 数据库连接池 预编译

1.创建连接,下载MySQL驱动(JDBC接口的实现类,就是一个jar包)public classDemo01 {public static voidmain(String[] args)throwsClassNotFoundException, SQLException {//1. 注册驱动 告诉虚拟机使用的是哪个数据库软件Class.forName("com.mysql.jdbc.Drive...

weixin_42518709的博客 683

UNet改进(24):注意力机制-从基础原理到高级融合策略

本文系统探讨了如何通过引入各类注意力机制增强UNet在医学图像分割中的性能。文章分为基础篇、进阶篇和高级篇三个层级:基础篇介绍了时序注意力、可变形注意力、分层注意力等8种基础机制;进阶篇提出了5种混合注意力设计;高级篇则探讨了全局+局部+多尺度等复杂组合机制。实验表明,这些注意力模块在心脏MRI、肺部感染等任务中能提升2-15%的分割精度。文章还提供了硬件适配建议和完整实现代码,为研究者提供了全面的技术参考。未来方向包括NAS优化、量子注意力等前沿探索,为UNet在医疗影像等领域的应用革新提供了理论指导。

2501_91516851的博客 765

基于MATLAB的数字滤波器之低通滤波器

本文首先介绍了数字低通滤波器的概念和原理,其次论述了低通滤波器的技术指标和设计步骤,最后给出了数字低通滤波器应用于信号去噪的MATLAB代码。

总结论文中的算法并给出论文的复现代码 3万+

【JAVA】Java高级:数据库监控与调优:如何监控JDBC连接池性能与数据库负载

通过上述示例,我们了解了如何使用Apache DBCP连接池来监控JDBC连接池的性能以及数据库的负载。监控连接池和数据库的性能对于确保应用程序的稳定性和高效性至关重要。通过合理配置连接池参数、定期监控连接池状态和数据库负载,可以有效提升系统的性能,避免潜在的性能瓶颈。在实际应用中,监控工具(如Prometheus、Grafana等)可以与JMX结合使用,提供更直观的监控界面和报警机制,帮助开发人员及时发现并解决性能问题。

thinking_chou的专栏 1762

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java数据库连接—JDBC(JDBC详解、JDBC控制事务、C3P0连接池、Druid连接池、Spring JDBC-JDBC Template)

reparedStatement可以在传入sql后,执行语句前,给参数赋值,避免了因普通的拼接sql字符串语句所带来的安全问题,而且准备sql和执行sql是在两个语句里面完成的,也提高了语句执行的效率 比如单引号会给你加一个转义,加个斜杠。为 false 表示禁用自动提交模式(在执行SQL语句之前开始事务)2、提交事务 void commit() 使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 对象当前持有的所有数据库锁 (当所有事务中的SQL执行完就提交事务)

2401_84098033的博客 1025

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java--JDBC数据库连接池

Java--JDBC数据库连接池 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 概念 其实就是一个容器(集合),存放数据库连接的容器。 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。 好处 节约资源 用户访问高效 实现 标准接口:DataSource javax.sql包下的 获取连接:getConnection() 归还连接:Co

归子莫的博客 828

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

IPTVnator Stalker Portal 开发指南:门户模式、会话认证、系列契约与代码归属

IPTVnator 的 Stalker Portal 支持覆盖 Live TV(`itv`)、Radio(`radio`)、VOD、Series 以及收藏/最近观看等完整流程。本文以 `.codex/skills/stalker-portal/SKILL.md` 为骨架,结合 [Stalker Portal 架构文档](https://link.gitcode.com/i/80d3246a162d

gitblog_00034的博客 615

Java的JDBC数据库连接池实现方法

虽然J2EE程序员一般都有现成的应用服务器所带的JDBC数据库连接池,不过对于开发一般的Java Application、 Applet或者JSP、velocity时,我们可用的JDBC数据库连接池并不多,并且一般性能都不好。 AD: 51CTO云计算架构师峰会 抢票进行中! ...

chunhuanlong7105的博客 136

java jdbc 连接池_用java实现JDBC数据库连接池

1 packagecn.com.css.cas.jdbc;23 importjava.sql.Connection;4 importjava.sql.Driver;5 importjava.sql.DriverManager;6 importjava.sql.SQLException;7 importjava.util.HashSet;8 importjava.util.Iterator;9 im...

weixin_39616339的博客 118

Java jdbc数据库连接池总结!

Java jdbc数据库连接池总结! 1. 引言   近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机   应用程序已从传统的桌面应用转到Web应用。基于B/S(Browser/Server)架构的3层开发模式逐渐取代C/S(Client/Server)架构的开发模式,成为开发企业级应用和电子商务普遍采用的技术。在Web应用开发的早期,

shangsd的专栏 684
上一篇: MyEclipse 6.5 GA 下载 + 汉化方法 + 序列号
下一篇: 数据库连接池详细说明
JavaAlpha
博客等级 码龄18年 910粉丝 511原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值