用连接池提高Servlet访问数据库的效率(zt)

从CTF到HVV实战:Web安全进阶与红蓝对抗核心技术解析 Web安全是网络安全领域的基石,其核心在于理解应用层漏洞的原理与利用。从SQL注入、XSS、文件上传等常见漏洞的利用,到权限维持、内网横向移动等高级攻击链的构建,技术原理的深入掌握是实战能力提升的关键。这些技术不仅具有极高的攻防研究价值,更是企业构建纵深防御体系、应对高级持续性威胁(APT)必须防范的核心风险。在HVV(网络安全实战演习)等真实攻防场景中,攻击方(红队)需要将孤立的漏洞利用转化为隐蔽、持续的渗透路径,而防守方(蓝队)则需建立从资产梳理、实时监测到应急响应的完整闭环。本文聚焦于如何将基础的We 阅读详情

用连接池提高Servlet访问数据库的效率
好 兵

  Java Servlet作为首选的服务器端数据处理技术,正在迅速取代CGI脚本。Servlet超越CGI的优势之一在于,不仅多个请求可以共享公用资源,而且还可以在不同用户请求之间保留持续数据。本文介绍一种充分发挥该特色的实用技术,即数据库连接池。


  一、实现连接池的意义


  动态Web站点往往用数据库存储的信息生成Web页面,每一个页面请求导致一次数据库访问。连接数据库不仅要开销一定的通讯和内存资源,还必须完成用户验证、安全上下文配置这类任务,因而往往成为最为耗时的操作。当然,实际的连接时间开销千变万化,但1到2秒延迟并非不常见。如果某个基于数据库的Web应用只需建立一次初始连接,不同页面请求能够共享同一连接,就能获得显著的性能改善。

  Servlet是一个Java类。Servlet引擎(它可能是Web服务软件的一部分,也可能是一个独立的附加模块)在系统启动或Servlet第一次被请求时将该类装入Java虚拟机并创建它的一个实例。不同用户请求由同一Servlet实例的多个独立线程处理。那些要求在不同请求之间持续有效的数据既可以用Servlet的实例变量来保存,也可以保存在独立的辅助对象中。

  用JDBC访问数据库首先要创建与数据库之间的连接,获得一个连接对象(Connection),由连接对象提供执行SQL语句的方法。本文介绍的数据库连接池包括一个管理类DBConnectionManager,负责提供与多个连接池对象(DBConnectionPool类)之间的接口。每一个连接池对象管理一组JDBC连接对象,每一个连接对象可以被任意数量的Servlet共享。

  类DBConnectionPool提供以下功能:

   1) 从连接池获取(或创建)可用连接。

   2) 把连接返回给连接池。

   3) 在系统关闭时释放所有资源,关闭所有连接。

  此外, DBConnectionPool类还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不超过某个预定值。

  管理类DBConnectionManager用于管理多个连接池对象,它提供以下功能:

   1) 装载和注册JDBC驱动程序。

   2) 根据在属性文件中定义的属性创建连接池对象。

   3) 实现连接池名字与其实例之间的映射。

   4) 跟踪客户程序对连接池的引用,保证在最后一个客户程序结束时安全地关闭所有连接池。

  本文余下部分将详细说明这两个类,最后给出一个示例演示Servlet使用连接池的一般过程。


  二、具体实现


  DBConnectionManager.java程序清单如下:


  001    import java.io.*;


  002    import java.sql.*;


  003    import java.util.*;


  004    import java.util.Date;


  005


  006    /**


  007     * 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接


  008     * 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例.


  009     */


  010    public class DBConnectionManager {


  011       static private DBConnectionManager instance; // 唯一实例


  012       static private int clients;


  013


  014       private Vector drivers = new Vector();


  015       private PrintWriter log;


  016       private Hashtable pools = new Hashtable();


  017


  018       /**


  019        * 返回唯一实例.如果是第一次调用此方法,则创建实例


  020        *


  021        * @return DBConnectionManager 唯一实例


  022        */


  023       static synchronized public DBConnectionManager getInstance() {


  024          if (instance == null) {


  025             instance = new DBConnectionManager();


  026          }


  027          clients++;


  028          return instance;


  029       }


  030


  031       /**


  032        * 建构函数私有以防止其它对象创建本类实例


  033        */


  034       private DBConnectionManager() {


  035          init();


  036       }


  037


  038       /**


  039        * 将连接对象返回给由名字指定的连接池


  040        *


  041        * @param name 在属性文件中定义的连接池名字


  042        * @param con  连接对象


  043        */


  044       public void freeConnection(String name, Connection con) {


  045          DBConnectionPool pool = (DBConnectionPool) pools.get(name);


  046          if (pool != null) {


  047             pool.freeConnection(con);


  048          }


  049       }


  050


  051       /**


  052        * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数


  053        * 限制,则创建并返回新连接


  054        *


  055        * @param name  在属性文件中定义的连接池名字


  056        * @return Connection 可用连接或null


  057        */


  058       public Connection getConnection(String name) {


  059          DBConnectionPool pool = (DBConnectionPool) pools.get(name);


  060          if (pool != null) {


  061             return pool.getConnection();


  062          }


  063          return null;


  064       }


  065


  066       /**


  067        * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,


  068        * 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.


  069        *


  070        * @param name 连接池名字


  071        * @param time 以毫秒计的等待时间


  072        * @return Connection 可用连接或null


  073        */


  074       public Connection getConnection(String name, long time) {


  075          DBConnectionPool pool = (DBConnectionPool) pools.get(name);


  076          if (pool != null) {


  077             return pool.getConnection(time);


  078          }


  079          return null;


  080       }


  081


  082       /**


  083        * 关闭所有连接,撤销驱动程序的注册


  084        */


  085       public synchronized void release() {


  086          // 等待直到最后一个客户程序调用


  087          if (--clients != 0) {


  088             return;


  089          }


  090


  091          Enumeration allPools = pools.elements();


  092          while (allPools.hasMoreElements()) {


  093             DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();


  094             pool.release();


  095          }


  096          Enumeration allDrivers = drivers.elements();


  097          while (allDrivers.hasMoreElements()) {


  098             Driver driver = (Driver) allDrivers.nextElement();


  099             try {


  100                DriverManager.deregisterDriver(driver);


  101                log("撤销JDBC驱动程序 " + driver.getClass().getName()+"的注册");


  102             }


  103             catch (SQLException e) {


  104                log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());


  105             }


  106          }


  107       }


  108


  109       /**


  110        * 根据指定属性创建连接池实例.


  111        *


  112        * @param props 连接池属性


  113        */


  114       private void createPools(Properties props) {


  115          Enumeration propNames = props.propertyNames();


  116          while (propNames.hasMoreElements()) {


  117             String name = (String) propNames.nextElement();


  118             if (name.endsWith(".url")) {


  119                String poolName = name.substring(0, name.lastIndexOf("."));


  120                String url = props.getProperty(poolName + ".url");


  121                if (url == null) {


  122                   log("没有为连接池" + poolName + "指定URL");


  123                   continue;


  124                }


  125                String user = props.getProperty(poolName + ".user");


  126                String password = props.getProperty(poolName + ".password");


  127                String maxconn = props.getProperty(poolName + ".maxconn", "0");


  128                int max;


  129                try {


  130                   max = Integer.valueOf(maxconn).intValue();


  131                }


  132                catch (NumberFormatException e) {


  133                   log("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);


  134                   max = 0;


  135                }


  136                DBConnectionPool pool =


  137                                       new DBConnectionPool(poolName, url, user, password, max);


  138                pools.put(poolName, pool);


  139                log("成功创建连接池" + poolName);


  140             }


  141          }


  142       }


  143


  144       /**


  145        * 读取属性完成初始化


  146        */


  147       private void init() {


  148          InputStream is = getClass().getResourceAsStream("/db.properties");


  149          Properties dbProps = new Properties();


  150          try {


  151             dbProps.load(is);


  152          }


  153          catch (Exception e) {


  154             System.err.println("不能读取属性文件. " +


  155                                "请确保db.properties在CLASSPATH指定的路径中");


  156             return;


  157          }


  158          String logFile = dbProps.getProperty("logfile", "DBConnectionManager.log");


  159          try {


  160             log = new PrintWriter(new FileWriter(logFile, true), true);


  161          }


  162          catch (IOException e) {


  163             System.err.println("无法打开日志文件: " + logFile);


  164             log = new PrintWriter(System.err);


  165          }


  166          loadDrivers(dbProps);


  167          createPools(dbProps);


  168       }


  169


  170       /**


  171        * 装载和注册所有JDBC驱动程序


  172        *


  173        * @param props 属性


  174        */


  175       private void loadDrivers(Properties props) {


  176          String driverClasses = props.getProperty("drivers");


  177          StringTokenizer st = new StringTokenizer(driverClasses);


  178          while (st.hasMoreElements()) {


  179             String driverClassName = st.nextToken().trim();


  180             try {


  181                Driver driver = (Driver)


  182                                 Class.forName(driverClassName).newInstance();


  183                DriverManager.registerDriver(driver);


  184                drivers.addElement(driver);


  185                log("成功注册JDBC驱动程序" + driverClassName);


  186             }


  187             catch (Exception e) {


  188                log("无法注册JDBC驱动程序: " +


  189                    driverClassName + ", 错误: " + e);


  190             }


  191          }


  192       }


  193


  194       /**


  195        * 将文本信息写入日志文件


  196        */


  197       private void log(String msg) {


  198          log.println(new Date() + ": " + msg);


  199       }


  200


  201       /**


  202        * 将文本信息与异常写入日志文件


  203        */


  204       private void log(Throwable e, String msg) {


  205          log.println(new Date() + ": " + msg);


  206          e.printStackTrace(log);


  207       }


  208


  209        /**


  210         * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最


  211         * 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.


  212         */


  213       class DBConnectionPool {


  214          private int checkedOut;


  215          private Vector freeConnections = new Vector();


  216          private int maxConn;


  217          private String name;


  218          private String password;


  219          private String URL;


  220          private String user;


  221


  222          /**


  223           * 创建新的连接池


  224           *


  225           * @param name 连接池名字


  226           * @param URL  数据库的JDBC URL


  227           * @param user 数据库帐号,或 null


  228           * @param password 密码,或 null


  229           * @param maxConn 此连接池允许建立的最大连接数


  230           */


  231          public DBConnectionPool(String name, String URL, String user, String password,


  232                                  int maxConn) {


  233             this.name = name;


  234             this.URL = URL;


  235             this.user = user;


  236             this.password = password;


  237             this.maxConn = maxConn;


  238          }


  239


  240          /**


  241           * 将不再使用的连接返回给连接池


  242           *


  243           * @param con 客户程序释放的连接


  244           */


  245          public synchronized void freeConnection(Connection con) {


  246             // 将指定连接加入到向量末尾


  247             freeConnections.addElement(con);


  248             checkedOut--;


  249             notifyAll();


  250          }


  251


  252          /**


  253           * 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接


  254           * 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,


  255           * 然后递归调用自己以尝试新的可用连接.


  256           */


  257          public synchronized Connection getConnection() {


  258             Connection con = null;


  259             if (freeConnections.size() 〉 0) {


  260                // 获取向量中第一个可用连接


  261                con = (Connection) freeConnections.firstElement();


  262                freeConnections.removeElementAt(0);


  263                try {


  264                   if (con.isClosed()) {


  265                      log("从连接池" + name+"删除一个无效连接");


  266                      // 递归调用自己,尝试再次获取可用连接


  267                      con = getConnection();


  268                   }


  269                }


  270                catch (SQLException e) {


  271                   log("从连接池" + name+"删除一个无效连接");


  272                   // 递归调用自己,尝试再次获取可用连接


  273                   con = getConnection();


  274                }


  275             }


  276             else if (maxConn == 0 || checkedOut 〈 maxConn) {


  277                con = newConnection();


  278             }


  279             if (con != null) {


  280                checkedOut++;


  281             }


  282             return con;


  283          }


  284


  285          /**


  286           * 从连接池获取可用连接.可以指定客户程序能够等待的最长时间


  287           * 参见前一个getConnection()方法.


  288           *


  289           * @param timeout 以毫秒计的等待时间限制


  290           */


  291          public synchronized Connection getConnection(long timeout) {


  292             long startTime = new Date().getTime();


  293             Connection con;


  294             while ((con = getConnection()) == null) {


  295                try {


  296                   wait(timeout);


  297                }


  298                catch (InterruptedException e) {}


  299                if ((new Date().getTime() - startTime) 〉= timeout) {


  300                   // wait()返回的原因是超时


  301                   return null;


  302                }


  303             }


  304             return con;


  305          }


  306


  307          /**


  308           * 关闭所有连接


  309           */


  310          public synchronized void release() {


  311             Enumeration allConnections = freeConnections.elements();


  312             while (allConnections.hasMoreElements()) {


  313                Connection con = (Connection) allConnections.nextElement();


  314                try {


  315                   con.close();


  316                   log("关闭连接池" + name+"中的一个连接");


  317                }


  318                catch (SQLException e) {


  319                   log(e, "无法关闭连接池" + name+"中的连接");


  320                }


  321             }


  322             freeConnections.removeAllElements();


  323          }


  324


  325          /**


  326           * 创建新的连接


  327           */


  328          private Connection newConnection() {


  329             Connection con = null;


  330             try {


  331                if (user == null) {


  332                   con = DriverManager.getConnection(URL);


  333                }


  334                else {


  335                   con = DriverManager.getConnection(URL, user, password);


  336                }


  337                log("连接池" + name+"创建一个新的连接");


  338             }


  339             catch (SQLException e) {


  340                log(e, "无法创建下列URL的连接: " + URL);


  341                return null;


  342             }


  343             return con;


  344          }


  345       }


  346    }


  三、类DBConnectionPool说明


  该类在209至345行实现,它表示指向某个数据库的连接池。数据库由JDBC URL标识。一个JDBC URL由三部分组成:协议标识(总是jdbc),驱动程序标识(如 odbc、idb、oracle等),数据库标识(其格式依赖于驱动程序)。例如,jdbc:odbc:demo,即是一个指向demo数据库的JDBC URL,而且访问该数据库要使用JDBC-ODBC驱动程序。每个连接池都有一个供客户程序使用的名字以及可选的用户帐号、密码、最大连接数限制。如果Web应用程序所支持的某些数据库操作可以被所有用户执行,而其它一些操作应由特别许可的用户执行,则可以为两类操作分别定义连接池,两个连接池使用相同的JDBC URL,但使用不同的帐号和密码。

  类DBConnectionPool的建构函数需要上述所有数据作为其参数。如222至238行所示,这些数据被保存为它的实例变量:

  如252至283行、285至305行所示, 客户程序可以使用DBConnectionPool类提供的两个方法获取可用连接。两者的共同之处在于:如连接池中存在可用连接,则直接返回,否则创建新的连接并返回。如果没有可用连接且已有连接总数等于最大限制数,第一个方法将直接返回null,而第二个方法将等待直到有可用连接为止。

  所有的可用连接对象均登记在名为freeConnections的向量(Vector)中。如果向量中有多于一个的连接,getConnection()总是选取第一个。同时,由于新的可用连接总是从尾部加入向量,从而使得数据库连接由于长时间闲置而被关闭的风险减低到最小程度。

  第一个getConnection()在返回可用连接给客户程序之前,调用了isClosed()方法验证连接仍旧有效。如果该连接被关闭或触发异常,getConnection()递归地调用自己以尝试获取另外的可用连接。如果在向量freeConnections中不存在任何可用连接,getConnection()方法检查是否已经指定最大连接数限制。如已经指定,则检查当前连接数是否已经到达极限。此处maxConn为0表示没有限制。如果没有指定最大连接数限制或当前连接数小于该值,该方法尝试创建新的连接。如创建成功,则增加已使用连接的计数并返回,否则返回空值。

  如325至345行所示,创建新连接由newConnection()方法实现。创建过程与是否已经指定数据库帐号、密码有关。

  JDBC的DriverManager类提供多个getConnection()方法,这些方法要用到JDBC URL与其它一些参数,如用户帐号和密码等。DriverManager将使用指定的JDBC URL确定适合于目标数据库的驱动程序及建立连接。

  在285至305行实现的第二个getConnection()方法需要一个以毫秒为单位的时间参数,该参数表示客户程序能够等待的最长时间。建立连接的具体操作仍旧由第一个getConnection()方法实现。

  该方法执行时先将startTime初始化为当前时间。在while循环中尝试获得一个连接。如果失败,则以给定的时间值为参数调用wait()。wait()的返回可能是由于其它线程调用notify()或notifyAll(),也可能是由于预定时间已到。为找出wait()返回的真正原因,程序用当前时间减开始时间(startTime),如差值大于预定时间则返回空值,否则再次调用getConnection()。

  把空闲的连接登记到连接池由240至250行的freeConnection()方法实现,它的参数为返回给连接池的连接对象。该对象被加入到freeConnections向量的末尾,然后减少已使用连接计数。调用notifyAll()是为了通知其它正在等待可用连接的线程。

  许多Servlet引擎为实现安全关闭提供多种方法。数据库连接池需要知道该事件以保证所有连接能够正常关闭。DBConnectionManager类负协调整个关闭过程,但关闭连接池中所有连接的任务则由DBConnectionPool类负责。在307至323行实现的release()方法供DBConnectionManager调用。该方法遍历freeConnections向量并关闭所有连接,然后从向量中删除这些连接。


  四、类DBConnectionManager 说明


  该类只能创建一个实例,其它对象能够调用其静态方法(也称为类方法)获得该唯一实例的引用。如031至036行所示,DBConnectionManager类的建构函数是私有的,这是为了避免其它对象创建该类的实例。

  DBConnectionManager类的客户程序可以调用getInstance()方法获得对该类唯一实例的引用。如018至029行所示,类的唯一实例在getInstance()方法第一次被调用期间创建,此后其引用就一直保存在静态变量instance中。每次调用getInstance()都增加一个DBConnectionManager的客户程序计数。即,该计数代表引用DBConnectionManager唯一实例的客户程序总数,它将被用于控制连接池的关闭操作。

  该类实例的初始化工作由146至168行之间的私有方法init()完成。其中 getResourceAsStream()方法用于定位并打开外部文件。外部文件的定位方法依赖于类装载器的实现。标准的本地类装载器查找操作总是开始于类文件所在路径,也能够搜索CLASSPATH中声明的路径。db.properties是一个属性文件,它包含定义连接池的键-值对。可供定义的公用属性如下:

  drivers 以空格分隔的JDBC驱动程序类列表

  logfile 日志文件的绝对路径

  其它的属性和特定连接池相关,其属性名字前应加上连接池名字:

  〈poolname〉.url 数据库的 JDBC URL

  〈poolname〉.maxconn 允许建立的最大连接数,0表示没有限制

  〈poolname〉.user 用于该连接池的数据库帐号

  〈poolname〉.password 相应的密码

  其中url属性是必需的,而其它属性则是可选的。数据库帐号和密码必须合法。用于Windows平台的db.properties文件示例如下:

  drivers=sun.jdbc.odbc.JdbcOdbcDriver jdbc.idbDriver

  logfile=D://user//src//java//DBConnectionManager//log.txt

  idb.url=jdbc:idb:c://local//javawebserver1.1//db//db.prp

  idb.maxconn=2

  access.url=jdbc:odbc:demo

  access.user=demo

  access.password=demopw

  注意在Windows路径中的反斜杠必须输入2个,这是由于属性文件中的反斜杠同时也是一个转义字符。

  init()方法在创建属性对象并读取db.properties文件之后,就开始检查logfile属性。如果属性文件中没有指定日志文件,则默认为当前目录下的DBConnectionManager.log文件。如日志文件无法使用,则向System.err输出日志记录。

  装载和注册所有在drivers属性中指定的JDBC驱动程序由170至192行之间的loadDrivers()方法实现。该方法先用StringTokenizer将drivers属性值分割为对应于驱动程序名称的字符串,然后依次装载这些类并创建其实例,最后在 DriverManager中注册该实例并把它加入到一个私有的向量drivers。向量drivers将用于关闭服务时从DriverManager取消所有JDBC 驱动程序的注册。

  init()方法的最后一个任务是调用私有方法createPools()创建连接池对象。如109至142行所示,createPools()方法先创建所有属性名字的枚举对象(即Enumeration对象,该对象可以想象为一个元素系列,逐次调用其nextElement()方法将顺序返回各元素),然后在其中搜索名字以“.url”结尾的属性。对于每一个符合条件的属性,先提取其连接池名字部分,进而读取所有属于该连接池的属性,最后创建连接池对象并把它保存在实例变量pools中。散列表(Hashtable类 )pools实现连接池名字到连接池对象之间的映射,此处以连接池名字为键,连接池对象为值。

  为便于客户程序从指定连接池获得可用连接或将连接返回给连接池,类DBConnectionManager提供了方法getConnection()和freeConnection()。所有这些方法都要求在参数中指定连接池名字,具体的连接获取或返回操作则调用对应的连接池对象完成。它们的实现分别在051至064行、066至080行、038至049行。

  如082至107行所示,为实现连接池的安全关闭,DBConnectionManager提供了方法release()。在上面我们已经提到,所有DBConnectionManager的客户程序都应该调用静态方法getInstance()以获得该管理器的引用,此调用将增加客户程序计数。客户程序在关闭时调用release()可以递减该计数。当最后一个客户程序调用release(),递减后的引用计数为0,就可以调用各个连接池的release()方法关闭所有连接了。管理类release()方法最后的任务是撤销所有JDBC驱动程序的注册。


  五、Servlet使用连接池示例


  Servlet API所定义的Servlet生命周期类如:

   1) 创建并初始化Servlet(init()方法)。

   2) 响应客户程序的服务请求(service()方法)。

   3) Servlet终止运行,释放所有资源(destroy()方法)。

  本例演示连接池应用,上述关键步骤中的相关操作为:

   1) 在init(),用实例变量connMgr 保存调用DBConnectionManager.getInstance()所返回的引用。

   2) 在service(),调用getConnection(),执行数据库操作,用freeConnection()将连接返回给连接池。

   3) 在destroy(),调用release()关闭所有连接,释放所有资源。

  示例程序清单如下:

  import java.io.*;

  import java.sql.*;

  import javax.servlet.*;

  import javax.servlet.http.*;

  public class TestServlet extends HttpServlet {

   private DBConnectionManager connMgr;

   public void init(ServletConfig conf) throws ServletException {

   super.init(conf);

   connMgr = DBConnectionManager.getInstance();

  }

  public void service(HttpServletRequest req, HttpServletResponse res)

   throws IOException {

   res.setContentType("text/html");

   PrintWriter out = res.getWriter();

   Connection con = connMgr.getConnection("idb");

   if (con == null) {

   out.println("不能获取数据库连接.");

   return;

   }

   ResultSet rs = null;

   ResultSetMetaData md = null;

   Statement stmt = null;

   try {

   stmt = con.createStatement();

   rs = stmt.executeQuery("SELECT * FROM EMPLOYEE");

   md = rs.getMetaData();

   out.println("〈H1〉职工数据〈/H1〉");

   while (rs.next()) {

   out.println("〈BR〉");

   for (int i = 1; i 〈 md.getColumnCount(); i++) {

   out.print(rs.getString(i) + ", ");

   }

   }

   stmt.close();

   rs.close();

   }

   catch (SQLException e) {

   e.printStackTrace(out);

   }

   connMgr.freeConnection("idb", con);

  }

  public void destroy() {

   connMgr.release();

   super.destroy();

  }

  }

dbconnection-pool:数据库连接池简略版 1、首先数据库连接池(简略版本) #####未完待续######### 立即下载

相关推荐

Windows Server 2012评估版过期自动关机问题:两种高效解决方案详解

本文针对Windows Server 2012评估版过期导致的自动关机问题,提供了两种高效解决方案。一是通过slmgr.vbs命令重置授权,临时延长评估期;二是使用DISM工具将评估版转换为正式版,一劳永逸。文章详细解析了两种方法的操作步骤、注意事项及适用场景,帮助用户快速恢复服务器稳定运行。

pytorchlight8的博客 1196

基于JDBC的数据库连接池技术研究与应用

   摘 要 本文介绍了Java访问数据库的原理及其存在的问题,提出了解决办法-数据库连接池,并对其关键问题进行了分析,构建了一个简便易用的连接池并结合当前热门技术Servlet说明了其如何在开发时使用。  关键词 JDBC,Jsp/Servlet,数据库连接池,多数据库服务器和多用户,多线程  引言  近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算

csdn 数据库频道技术资料 1813

[仿真实战]FDTD Solutions 8.0:从零搭建薄膜光谱分析模型

本文提供了一份基于FDTD Solutions 8.0的薄膜光谱分析模型从零搭建实战指南。通过详细步骤,手把手教你创建玻璃基底与硅薄膜的几何结构、设置仿真区域与边界条件、配置光源与监视器,并最终计算反射率与透射率光谱。内容涵盖参数扫描与优化,旨在帮助用户快速掌握FDTD仿真在纳米光子学与薄膜光学设计中的核心应用。

defi6farmer的博客 500

DB连接池

DB连接池备忘 网络编程中提出了将Socket放入池中,让多个线程共享这些插座(Socket)对应的线缆(Conenction) DB连接池就是基于连接池的一个实现。连接池是客户端使用的技术。比如C3P0,DBCP都是应用程序做为客户端通过连接池访问DB       1.连接池的前世:通过JDBC访问DB: 一般来说,Java应用程序访问数据库的过程(如图1所示)

B_H_L的专栏 3095

新手必看:如何用T265和ROS实现无人机室内精准定位(附PX4参数配置)

本文详细介绍了如何使用Intel Realsense T265和ROS实现无人机室内精准定位,包括硬件准备、ROS数据流架构设计、PX4参数配置及系统验证。特别针对视觉SLAM技术在室内环境中的应用,提供了从零搭建到进阶优化的全流程解析,适合无人机开发新手快速上手。

weixin_30642561的博客 404

【随机过程】Markov Chain的定义及发展历程与实际应用

本模块书写的初衷:由于在学习张波张景肖等学者所著的《应用随机过程》存在着不甚了解的知识点,经过个人查找资料并整理、分享,希望能够为有同样疑惑的读者贡献绵薄之力,同时如果个人编写内容有错误,恳请读者指正。本文为对《应用随机过程》第42页中Markov Chain基本概念的补充。1.Markov Chain的定义俄国数学家 Andrey Andreyevich Markov 研究并提出一个用数学方法就能解释自然变化的一般规律模型,被命名为马尔科夫链(Markov Chain)。

qq_49657150的博客 3747

用连接池提高Servlet访问数据库的效率

作者:好兵Java Servlet作为首选的服务器端数据处理技术,正在迅速取代CGI脚本。Servlet超越CGI的优势之一在于,不仅多个请求可以共享公用资源,而且还可以在不同用户请求之间保留持续数据。本文介绍一种充分发挥该特色的实用技术,即数据库连接池。一、实现连接池的意义动态Web站点往往用数据库存储的信息生成Web页面,每一个页面请求导致一次数据库访问。连接数据库不仅要开销一定的通讯和内

2386

通达信浮筹多空波段抓牛擒龙指标公式源码

VAR33:=VA3>=REF(VA4,1) AND C<REF(C,1) AND VAR19=60 AND VAR18=0 AND 活跃线>=REF(活跃线,1) AND VA12<REF(VA13,1);DRAWTEXT(VAR28 AND COUNT(VAR28,30)=1,65,' ★超涨注意风险'),COLOR0000FF;DRAWTEXT(VAR26 AND COUNT(VAR26,30)=1,90,' ←继续等'),COLOR00FFFF;浮筹线:VA3,COLORFF00FF;

2401_86043146的博客 5267

java sql server 连接池_Java jdbc数据库连接池总结

如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。连接池的实现1、连接池模型本文讨论的连接池包括一个连接池类(DBConnectionPool)和一个连接池管理类(DBConnetionPoolManager)和一个配置文件操作类(ParseD...

weixin_31580797的博客 815

西门子RS485自由口通信Modbus RTU 通信协议

部分西门子的RS485模块不能使用西门子自带的Modbus RTU通信指令,需要通过自己拼接、发送、接收和解析报文完成Modbus RTU通信。通过多次尝试完成该功能: #R_TRIG_Instance(CLK := #触发, Q => #触发上升沿); IF #触发上升沿 THEN // 触发后先将读取完成复位 #读写完成 := 0; END_IF; CASE #功能码 OF 1: // 线圈状态读取 ; 2:

qq_20792765的博客 1万+

MIKE21 教程 3.2 随空间变化的网格文件制作(.dfsu文件制作) 曼宁值网格文件制作

上一节讲解了如何制作时间序列文件。本节讲解如何制作仅随空间变化的文件。 目录 1 数据准备 1.1 基于地形设置 1.2 基于地形水深设置: 2 数据导入 3 数据导出

Hello Word 3941

用连接池提高Servlet访问数据库的效率 ZT

Java Servlet作为首选的服务器端数据处理技术,正在迅速取代CGI脚本。Servlet超越CGI的优势之一在于,不仅多个请求可以共享公用资源,而且还可以在不同用户请求之间保留持续数据。本文介绍一种充分发挥该特色的实用技术,即数据库连接池。 一、实现连接池的意义 动态Web站点往往用数据库存储的信息生成Web页面,每一个页面请求导致一次数据库访问。连接数据库不仅要开销一定的通讯和

wish_silence的专栏 664

航天设备研制中的形态分类:电性件、正样件及其他关键形态详解

航天设备的研制是一个高度复杂且严谨的工程过程,涉及多个阶段的不同产品形态。这些形态各具特点,在研制流程中承担着不同的验证任务和工程目标。本文将系统介绍航天设备研制中的主要形态,包括**电性件(EM)**、**正样件(FM)**以及**结构热控件(STM)**、**鉴定件(QM)**和**初样件(PFM)**等,详细解析它们的定义、用途和工程意义,帮助读者全面理解航天产品从设计到飞行的全生命周期管理。

ScilogyHunter的博客 1661

[导入]用连接池提高Servlet访问数据库的效率(zt)

用连接池提高Servlet访问数据库的效率 好 兵 文章来源:http://blog.youkuaiyun.com/jaopen/archive/2005/05/26/381539.aspx

weixin_34293911的博客 90

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

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

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Web开发技术史话 ZT

Web开发技术史话 1.     荒芜年代 1990-19921990年,HTML标记的出现。这标志着Web开发时代的到来,B/S模型开始在之后的岁月中,不断的发展壮大,攻城略地蚕食着传统C/S的领域。如同所有的新生事物一样,在web的史前岁月,web的开发技术在html标记诞生后,无论是在服务端还是客户端都缓慢的发展着。在相当长的一个时间内,它并未象今天这样辉煌。甚至于只是静

JESoft -- Garden 1268

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Eclipse最新插件的下载地址大全[收集整理] zt

http://hi.baidu.com/damofeisha/blog/item/425b114f7bd6f53cafc3ab14.htmlEMF,GEF - Graphical Editor Framework,UML2,VE - Visual Editor都在这里下载http://www.eclipse.org/downloads/index.php2 lomboz J2EE插件,开发JSP...

weixin_30709635的博客 94

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Java学习从入门到精通[ZT]

作者:robbin 网址:http://hibernate.fankai.com/ Java Learning Path (一)、工具篇 一、 JDK (Java Development Kit) JDK是整个Java的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具和Java基础的类库(rt.jar)。不论什么Java应用服务器实质都是内置...

cpsing 172

安装ArcIMS (ZT)

这几天奋力地搞WebGIS,光安装就折腾了我好长时间。 我是从为了学WebGIS而构建网站,而不是在网站构成之后再学WebGIS。 由于没有人的指导,完全依靠网络与本人不懈的努力。起初不知道在装ArcIMS之前还要装一系列的与GIS无关的东西,没有任何的资料。ArcIMS资料匮乏,很难学习成功。 ArcIMS安装需要: 1. Java 2 SDK, Standard Editio...

weixin_30300523的博客 111

有感:应聘Java笔试时可能出现问题及其答案(第二版part two) ZT

 线程编程方面60、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?答:有两种实现方法,分别是继承Thread类与实现Runnable接口用synchronized关键字修饰同步方法反对使用

coolcat9527的专栏 519

数据库连接池

1、连接池简介 通常情况下,在每次访问数据库之前都要先建立与数据库的连接,这将消耗一定的资源,并延长了访问数据库的时间,如果是访问量相对较低的系统还可以,如果访问量较高,将严重影响系统的性能。为了解决这一问题,引入了连接池的概念。所谓连接池,就是预先建立好一定数量的数据库连接,模拟存放在一个连接池中,由连接池负责对这些数据库连接进行管理。这样,当需要访问数据库时,就可以通过已经建立好的连接访问数

NSDaBen的专栏 990

用apache的dbcp来建立独立的数据库连接池(db connection pool)

数据库连接池的好处是不言而喻的,现在大部分的application server都提供自己的数据库连接池方案,此时,只要按照application server的文档说明,正确配置,即可在应用中享受到数据库连接池的好处。但是,有些时候,我们的应用是个独立的java application,并不是普通的WEB/J2EE应用,而且是单独运行的,不要什么application server的配合,这种情

yoyo_yaya的专栏 2223

如何设计并实现一个db连接池?

连接池的使命! 无论是线程池还是db连接池,他们都有一个共同的特性:资源复用,在普通的场景中,我们使用一个连接,它的生命周期可能是这样的: 一个连接,从创建完毕到销毁,期间只被使用了一次(这里的一次是指在单个作用域内的使用),当周期结束,另外一个调用者仍然需要这个连接去做事,就要重复去经历这种生命周期。因为创建和销毁都是需要对应的服务消耗时间以及系统资源去处理的,这样不仅浪费了大量的系统资源,而...

weixin_34109408的博客 521
上一篇: 一个离线ADO数据管理模块的实现
下一篇: Tomcat5.5.9 DBCP配置错误解决
jaopen
博客等级 码龄24年 12粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值