﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-天道酬勤 tiān dào chóu qín-文章分类-java</title><link>http://www.blogjava.net/abram/category/40689.html</link><description>天将降大任于斯人也，必将苦其心志，劳其筋骨          
宠辱不惊，看庭上花开花落；去留无意，望天上云卷云舒</description><language>zh-cn</language><lastBuildDate>Sat, 11 Jul 2009 22:09:15 GMT</lastBuildDate><pubDate>Sat, 11 Jul 2009 22:09:15 GMT</pubDate><ttl>60</ttl><item><title>通过JDBC连接oracle数据库的十大技巧</title><link>http://www.blogjava.net/abram/articles/286132.html</link><dc:creator>chong</dc:creator><author>chong</author><pubDate>Thu, 09 Jul 2009 10:26:00 GMT</pubDate><guid>http://www.blogjava.net/abram/articles/286132.html</guid><wfw:comment>http://www.blogjava.net/abram/comments/286132.html</wfw:comment><comments>http://www.blogjava.net/abram/articles/286132.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/abram/comments/commentRss/286132.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/abram/services/trackbacks/286132.html</trackback:ping><description><![CDATA[<span  style="font-family: Arial; font-size: 12px; line-height: 18px; ">　Java数据库连接（JDBC）API是一系列能够让Java编程人员访问数据库的接口，各个开发商的接口并不完全相同。在使用多年的Oracle公司的JDBC后，我积累了许多技巧，这些技巧能够使我们更好地发挥系统的性能和实现更多的功能。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">1、在客户端软件开发中使用Thin驱动程序&nbsp;</strong><br />
在开发Java软件方面，Oracle的数据库提供了四种类型的驱动程序，二种用于应用软件、applets、servlets等客户端软件，另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中，我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口（JNI），通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序，它直接与数据库进行通讯。为了获得最高的性能，Oracle建议在客户端软件的开发中使用OCI驱动程序，这似乎是正确的。但我建议使用Thin驱动程序，因为通过多次测试发现，在通常情况下，Thin驱动程序的性能都超过了OCI驱动程序。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">2、关闭自动提交功能，提高系统性能&nbsp;</strong><br />
在第一次建立与数据库的连接时，在缺省情况下，连接是在自动提交模式下的。为了获得更好的性能，可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能，如下所示：&nbsp;<br />
<br />
<br />
conn.setAutoCommit(false);&nbsp;<br />
<br />
值得注意的是，一旦关闭了自动提交功能，我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">3、在动态SQL或有时间限制的命令中使用Statement对象&nbsp;</strong><br />
在执行SQL命令时，我们有二种选择：可以使用PreparedStatement对象，也可以使用Statement对象。无论多少次地使用同一个SQL命令，PreparedStatement都只对它解析和编译一次。当使用Statement对象时，每次执行一个SQL命令时，都会对它进行解析和编译。这可能会使你认为，使用PreparedStatement对象比使用Statement对象的速度更快。然而，我进行的测试表明，在客户端软件中，情况并非如此。因此，在有时间限制的SQL操作中，除非成批地处理SQL命令，我们应当考虑使用Statement对象。&nbsp;<br />
<br />
此外，使用Statement对象也使得编写动态SQL命令更加简单，因为我们可以将字符串连接在一起，建立一个有效的SQL命令。因此，我认为，Statement对象可以使动态SQL命令的创建和执行变得更加简单。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">4、利用helper函数对动态SQL命令进行格式化&nbsp;</strong><br />
在创建使用Statement对象执行的动态SQL命令时，我们需要处理一些格式化方面的问题。例如，如果我们想创建一个将名字O'Reilly插入表中的SQL命令，则必须使用二个相连的&#8220;''&#8221;号替换O'Reilly中的&#8220;'&#8221;号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法，然后在连接字符串心服用公式表达一个SQL命令时，使用创建的helper方法。与此类似的是，我们可以让helper方法接受一个Date型的值，然后让它输出基于Oracle的to_date()函数的字符串表达式。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">5、利用PreparedStatement对象提高数据库的总体效率&nbsp;</strong><br />
在使用PreparedStatement对象执行SQL命令时，命令被数据库进行解析和编译，然后被放到命令缓冲区。然后，每当执行同一个PreparedStatement对象时，它就会被再解析一次，但不会被再次编译。在缓冲区中可以发现预编译的命令，并且可以重新使用。在有大量用户的企业级应用软件中，经常会重复执行相同的SQL命令，使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务，我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">6、在成批处理重复的插入或更新操作中使用PreparedStatement对象&nbsp;</strong><br />
<br />
<br />
如果成批地处理插入和更新操作，就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理，只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理，或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制，可以以如下所示的方式调用setExecuteBatch()：&nbsp;<br />
<br />
PreparedStatement pstmt3D null;&nbsp;<br />
try {&nbsp;<br />
((OraclePreparedStatement)&nbsp;<br />
pstmt).setExecuteBatch(30);&nbsp;<br />
...&nbsp;<br />
pstmt.executeUpdate();&nbsp;<br />
}&nbsp;<br />
<br />
调用setExecuteBatch()时指定的值是一个上限，当达到该值时，就会自动地引发SQL命令执行，标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">7、使用Oracle locator方法插入、更新大对象（LOB）&nbsp;</strong><br />
Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理，尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值，也不支持利用setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用PreparedStatement对象插入或更新LOB，但需要使用locator才能获取LOB的值。由于存在这二个问题，因此，我建议使用locator的方法来插入、更新或获取LOB的值。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">8、使用SQL92语法调用存储过程&nbsp;</strong><br />
在调用存储过程时，我们可以使用SQL92或Oracle PL/SQL，由于使用Oracle PL/SQL并没有什么实际的好处，而且会给以后维护你的应用程序的开发人员带来麻烦，因此，我建议在调用存储过程时使用SQL92。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">9、使用Object SQL将对象模式转移到数据库中&nbsp;</strong><br />
既然可以将Oracle的数据库作为一种面向对象的数据库来使用，就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象，将它们的属性映射到关系表中，然后在这些bean中添加方法。尽管这样作在Java中没有什么问题，但由于操作都是在数据库之外进行的，因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术，可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作，然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式，不但Java应用程序可以使用应用软件的对象模式，其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。&nbsp;<br />
<br />
<strong style="font-weight: bold; ">10、利用SQL完成数据库内的操作&nbsp;</strong><br />
我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求，而不是使用Java等过程化的编程语言。&nbsp;<br />
<br />
如果编程人员要在一个表中查找许多行，结果中的每个行都会查找其他表中的数据，最后，编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据。与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成。当能够在单一的SQL命令中完成任务，何必要让数据在网上流来流去的？我建议用户认真学习如何最大限度地发挥SQL的功能。&nbsp;</span>
<img src ="http://www.blogjava.net/abram/aggbug/286132.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/abram/" target="_blank">chong</a> 2009-07-09 18:26 <a href="http://www.blogjava.net/abram/articles/286132.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA 性能优化 “通用篇”</title><link>http://www.blogjava.net/abram/articles/286130.html</link><dc:creator>chong</dc:creator><author>chong</author><pubDate>Thu, 09 Jul 2009 10:24:00 GMT</pubDate><guid>http://www.blogjava.net/abram/articles/286130.html</guid><wfw:comment>http://www.blogjava.net/abram/comments/286130.html</wfw:comment><comments>http://www.blogjava.net/abram/articles/286130.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/abram/comments/commentRss/286130.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/abram/services/trackbacks/286130.html</trackback:ping><description><![CDATA[<span  style="font-family: Arial; font-size: 12px; line-height: 18px; ">&#8220;通用篇&#8221;讨论的问题适合于大多数Java应用。&nbsp;<br />
<br />
1.1 不用new关键词创建类的实例&nbsp;<br />
<br />
用new关键词创建类的实例时，构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口，我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。&nbsp;<br />
<br />
在使用设计模式（Design Pattern）的场合，如果用Factory模式创建对象，则改用clone()方法创建新的对象实例非常简单。例如，下面是Factory模式的一个典型实现：&nbsp;<br />
<br />
<div class="dp-highlighter" style="font-family: Consolas, 'Courier New', Courier, mono; font-size: 12px; background-color: transparent; width: 694px; overflow-x: auto; overflow-y: auto; margin-left: 9px; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word; ">
<div class="bar">
<div class="tools" style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; text-align: left; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: black; font-weight: bold; ">Java代码&nbsp;<embed src="http://guoli83945.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" width="14" height="15" flashvars="clipboard=public%20static%20Credit%20getNewCredit()%20%0A%7B%0A%E3%80%80return%20new%20Credit()%3B%0A%7D%20" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></div>
</div>
<ol start="1" class="dp-j" style="font-size: 1em; line-height: 1.4em; margin-top: 0px; margin-right: 0px; margin-bottom: 1px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #d1d7dc; border-right-color: #d1d7dc; border-bottom-color: #d1d7dc; border-left-color: #d1d7dc; list-style-type: decimal; list-style-position: initial; list-style-image: initial; background-color: #ffffff; color: #2b91af; ">
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; "><span class="keyword" style="color: #7f0055; font-weight: bold; ">public</span><span style="color: black; ">&nbsp;</span><span class="keyword" style="color: #7f0055; font-weight: bold; ">static</span><span style="color: black; ">&nbsp;Credit&nbsp;getNewCredit()&nbsp;&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">{&nbsp;&nbsp;</span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">　<span class="keyword" style="color: #7f0055; font-weight: bold; ">return</span><span style="color: black; ">&nbsp;</span><span class="keyword" style="color: #7f0055; font-weight: bold; ">new</span><span style="color: black; ">&nbsp;Credit();&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">}&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
改进后的代码使用clone()方法，如下所示：&nbsp;<br />
<br />
<div class="dp-highlighter" style="font-family: Consolas, 'Courier New', Courier, mono; font-size: 12px; background-color: transparent; width: 694px; overflow-x: auto; overflow-y: auto; margin-left: 9px; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word; ">
<div class="bar">
<div class="tools" style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; text-align: left; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: black; font-weight: bold; ">Java代码&nbsp;<embed src="http://guoli83945.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" width="14" height="15" flashvars="clipboard=private%20static%20Credit%20BaseCredit%20%3D%20new%20Credit()%3B%0Apublic%20static%20Credit%20getNewCredit()%20%0A%7B%0A%E3%80%80return%20(Credit)%20BaseCredit.clone()%3B%0A%7D%20" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></div>
</div>
<ol start="1" class="dp-j" style="font-size: 1em; line-height: 1.4em; margin-top: 0px; margin-right: 0px; margin-bottom: 1px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #d1d7dc; border-right-color: #d1d7dc; border-bottom-color: #d1d7dc; border-left-color: #d1d7dc; list-style-type: decimal; list-style-position: initial; list-style-image: initial; background-color: #ffffff; color: #2b91af; ">
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; "><span class="keyword" style="color: #7f0055; font-weight: bold; ">private</span><span style="color: black; ">&nbsp;</span><span class="keyword" style="color: #7f0055; font-weight: bold; ">static</span><span style="color: black; ">&nbsp;Credit&nbsp;BaseCredit&nbsp;=&nbsp;</span><span class="keyword" style="color: #7f0055; font-weight: bold; ">new</span><span style="color: black; ">&nbsp;Credit();&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; "><span class="keyword" style="color: #7f0055; font-weight: bold; ">public</span><span style="color: black; ">&nbsp;</span><span class="keyword" style="color: #7f0055; font-weight: bold; ">static</span><span style="color: black; ">&nbsp;Credit&nbsp;getNewCredit()&nbsp;&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">{&nbsp;&nbsp;</span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">　<span class="keyword" style="color: #7f0055; font-weight: bold; ">return</span><span style="color: black; ">&nbsp;(Credit)&nbsp;BaseCredit.clone();&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">}&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
上面的思路对于数组处理同样很有用。&nbsp;<br />
<br />
1.2 使用非阻塞I/O&nbsp;<br />
<br />
版本较低的JDK不支持非阻塞I/O API。为避免I/O阻塞，一些应用采用了创建大量线程的办法（在较好的情况下，会使用一个缓冲池）。这种技术可以在许多必须支持并发I/O流的应用中见到，如Web服务器、报价和拍卖应用等。然而，创建Java线程需要相当可观的开销。&nbsp;<br />
<br />
JDK 1.4引入了非阻塞的I/O库（java.nio）。如果应用要求使用版本较早的JDK，在这里有一个支持非阻塞I/O的软件包。&nbsp;<br />
<br />
1.3 慎用异常&nbsp;<br />
<br />
异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地（Native）方法，fillInStackTrace()方法检查堆栈，收集调用跟踪信息。只要有异常被抛出，VM就必须调整调用堆栈，因为在处理过程中创建了一个新的对象。&nbsp;<br />
<br />
异常只能用于错误处理，不应该用来控制程序流程。&nbsp;<br />
<br />
1.4 不要重复初始化变量&nbsp;<br />
<br />
默认情况下，调用类的构造函数时，Java会把变量初始化成确定的值：所有的对象被设置成null，整数变量（byte、short、int、long）设置成0，float和double变量设置成0.0，逻辑值设置成false。当一个类从另一个类派生时，这一点尤其应该注意，因为用new关键词创建一个对象时，构造函数链中的所有构造函数都会被自动调用。&nbsp;<br />
<br />
1.5 尽量指定类的final修饰符&nbsp;<br />
<br />
带有final修饰符的类是不可派生的。在Java核心API中，有许多应用final的例子，例如java.lang.String。为String类指定final防止了人们覆盖length()方法。&nbsp;<br />
<br />
另外，如果指定一个类为final，则该类所有的方法都是final。Java编译器会寻找机会内联（inline）所有的final方法（这和具体的编译器实现有关）。此举能够使性能平均提高50%。&nbsp;<br />
<br />
1.6 尽量使用局部变量&nbsp;<br />
<br />
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈（Stack）中，速度较快。其他变量，如静态变量、实例变量等，都在堆（Heap）中创建，速度较慢。另外，依赖于具体的编译器/JVM，局部变量还可能得到进一步优化。请参见《尽可能使用堆栈变量》。&nbsp;<br />
<br />
1.7 乘法和除法&nbsp;<br />
<br />
考虑下面的代码：&nbsp;<br />
<br />
<div class="dp-highlighter" style="font-family: Consolas, 'Courier New', Courier, mono; font-size: 12px; background-color: transparent; width: 694px; overflow-x: auto; overflow-y: auto; margin-left: 9px; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word; ">
<div class="bar">
<div class="tools" style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; text-align: left; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: black; font-weight: bold; ">Java代码&nbsp;<embed src="http://guoli83945.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" width="14" height="15" flashvars="clipboard=for%20(val%20%3D%200%3B%20val%20%3C%20100000%3B%20val%20%2B%3D5)%20%0A%7B%0A%E3%80%80alterX%20%3D%20val%20*%208%3B%20%0A%E3%80%80myResult%20%3D%20val%20*%202%3B%20%0A%7D%20" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></div>
</div>
<ol start="1" class="dp-j" style="font-size: 1em; line-height: 1.4em; margin-top: 0px; margin-right: 0px; margin-bottom: 1px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #d1d7dc; border-right-color: #d1d7dc; border-bottom-color: #d1d7dc; border-left-color: #d1d7dc; list-style-type: decimal; list-style-position: initial; list-style-image: initial; background-color: #ffffff; color: #2b91af; ">
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; "><span class="keyword" style="color: #7f0055; font-weight: bold; ">for</span><span style="color: black; ">&nbsp;(val&nbsp;=&nbsp;</span><span class="number" style="color: #c00000; ">0</span><span style="color: black; ">;&nbsp;val&nbsp;&lt;&nbsp;</span><span class="number" style="color: #c00000; ">100000</span><span style="color: black; ">;&nbsp;val&nbsp;+=</span><span class="number" style="color: #c00000; ">5</span><span style="color: black; ">)&nbsp;&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">{&nbsp;&nbsp;</span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">　alterX&nbsp;=&nbsp;val&nbsp;*&nbsp;<span class="number" style="color: #c00000; ">8</span><span style="color: black; ">;&nbsp;&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">　myResult&nbsp;=&nbsp;val&nbsp;*&nbsp;<span class="number" style="color: #c00000; ">2</span><span style="color: black; ">;&nbsp;&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">}&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
用移位操作替代乘法操作可以极大地提高性能。下面是修改后的代码：&nbsp;<br />
<br />
<div class="dp-highlighter" style="font-family: Consolas, 'Courier New', Courier, mono; font-size: 12px; background-color: transparent; width: 694px; overflow-x: auto; overflow-y: auto; margin-left: 9px; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word; ">
<div class="bar">
<div class="tools" style="padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; text-align: left; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: black; font-weight: bold; ">Java代码&nbsp;<embed src="http://guoli83945.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" width="14" height="15" flashvars="clipboard=for%20(val%20%3D%200%3B%20val%20%3C%20100000%3B%20val%20%2B%3D%205)%20%0A%7B%0A%E3%80%80alterX%20%3D%20val%20%3C%3C%203%3B%0A%E3%80%80myResult%20%3D%20val%20%3C%3C%201%3B%0A%7D%20" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></div>
</div>
<ol start="1" class="dp-j" style="font-size: 1em; line-height: 1.4em; margin-top: 0px; margin-right: 0px; margin-bottom: 1px; margin-left: 0px; padding-top: 2px; padding-right: 0px; padding-bottom: 2px; padding-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #d1d7dc; border-right-color: #d1d7dc; border-bottom-color: #d1d7dc; border-left-color: #d1d7dc; list-style-type: decimal; list-style-position: initial; list-style-image: initial; background-color: #ffffff; color: #2b91af; ">
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; "><span class="keyword" style="color: #7f0055; font-weight: bold; ">for</span><span style="color: black; ">&nbsp;(val&nbsp;=&nbsp;</span><span class="number" style="color: #c00000; ">0</span><span style="color: black; ">;&nbsp;val&nbsp;&lt;&nbsp;</span><span class="number" style="color: #c00000; ">100000</span><span style="color: black; ">;&nbsp;val&nbsp;+=&nbsp;</span><span class="number" style="color: #c00000; ">5</span><span style="color: black; ">)&nbsp;&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">{&nbsp;&nbsp;</span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">　alterX&nbsp;=&nbsp;val&nbsp;&lt;&lt;&nbsp;<span class="number" style="color: #c00000; ">3</span><span style="color: black; ">;&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">　myResult&nbsp;=&nbsp;val&nbsp;&lt;&lt;&nbsp;<span class="number" style="color: #c00000; ">1</span><span style="color: black; ">;&nbsp;&nbsp;</span></span></li>
    <li style="font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; border-left-width: 1px; border-left-style: solid; border-left-color: #d1d7dc; background-color: #fafafa; line-height: 18px; "><span style="color: black; ">}&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
<br />
修改后的代码不再做乘以8的操作，而是改用等价的左移3位操作，每左移1位相当于乘以2。相应地，右移1位操作相当于除以2。值得一提的是，虽然移位操作速度快，但可能使代码比较难于理解，所以最好加上一些注释。&nbsp;<br />
<br />
本贴来自ZDNetChina中文社区 http://bbs.zdnet.com.cn ,本贴地址：http://bbs.zdnet.com.cn/viewthread.php?tid=222399&nbsp;</span>
<img src ="http://www.blogjava.net/abram/aggbug/286130.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/abram/" target="_blank">chong</a> 2009-07-09 18:24 <a href="http://www.blogjava.net/abram/articles/286130.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java相对路径/绝对路径总结 （转）</title><link>http://www.blogjava.net/abram/articles/285762.html</link><dc:creator>chong</dc:creator><author>chong</author><pubDate>Tue, 07 Jul 2009 02:58:00 GMT</pubDate><guid>http://www.blogjava.net/abram/articles/285762.html</guid><wfw:comment>http://www.blogjava.net/abram/comments/285762.html</wfw:comment><comments>http://www.blogjava.net/abram/articles/285762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/abram/comments/commentRss/285762.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/abram/services/trackbacks/285762.html</trackback:ping><description><![CDATA[<span  style="font-family: Verdana; font-size: 13px; line-height: 16px; "><font size="3"><strong>1.基本概念的理解</strong><br />
<br />
绝对路径：绝对路径就是你的主页上的文件或目录在硬盘上真正的路径，(URL和物理路径)例如：<br />
C:xyz est.txt 代表了test.txt文件的绝对路径。http://www.sun.com/index.htm也代表了一个URL绝对路径。<br />
<br />
相对路径：相对与某个基准目录的路径。包含Web的相对路径（HTML中的相对目录），例如：在<br />
Servlet中，"/"代表Web应用的跟目录。和物理路径的相对表示。例如："./" 代表当前目录,"../"代表上级目录。这种类似的表示，也是属于相对路径。<br />
另外关于URI，URL,URN等内容，请参考RFC相关文档标准。<br />
<br />
RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax,<br />
(http://www.ietf.org/rfc/rfc2396.txt)<br />
<br />
<br />
<strong>2.关于JSP/Servlet中的相对路径和绝对路径。</strong><br />
<br />
2.1服务器端的地址<br />
<br />
服务器端的相对地址指的是相对于你的web应用的地址，这个地址是在服务器端解析的（不同于html和javascript中的相对地址，他们是由客户端 浏览器解析的）也就是说这时候在jsp和servlet中的相对地址应该是相对于你的web应用，即相对于http: //192.168.0.1/webapp/的。<br />
<br />
其用到的地方有：<br />
forward：servlet中的request.getRequestDispatcher(address);这个address是在服务器端解析 的，所以，你要forward到a.jsp应该这么写：request.getRequestDispatcher(&#8220;/user/a.jsp&#8221;)这个/ 相对于当前的web应用webapp，其绝对地址就是：http://192.168.0.1/webapp/user/a.jsp。 sendRedirect：在jsp中&lt;%response.sendRedirect("/rtccp/user/a.jsp");%&gt;<br />
<br />
2.22、客户端的地址<br />
<br />
所有的html页面中的相对地址都是相对于服务器根目录(http://192.168.0.1/)的，而不是(跟目录下的该Web应用的目录) http://192.168.0.1/webapp/的。 Html中的form表单的action属性的地址应该是相对于服务器根目录(http://192.168.0.1/)的，所以，如果提交到a.jsp 为：action＝"/webapp/user/a.jsp"或action="&lt;%=request.getContextPath()% &gt;"/user/a.jsp；<br />
提交到servlet为actiom＝"/webapp/handleservlet" Javascript也是在客户端解析的，所以其相对路径和form表单一样。<br />
<br />
<br />
因此，一般情况下，在JSP/HTML页面等引用的CSS,Javascript.Action等属性前面最好都加上<br />
&lt;%=request.getContextPath()%&gt;,以确保所引用的文件都属于Web应用中的目录。另外，应该尽量避免使用类 似".","./","../../"等类似的相对该文件位置的相对路径，这样当文件移动时，很容易出问题。<br />
<br />
<br />
<strong>3. JSP/Servlet中获得当前应用的相对路径和绝对路径<br />
<br />
</strong>3.1 JSP中获得当前应用的相对路径和绝对路径<br />
根目录所对应的绝对路径:request.getRequestURI()<br />
文件的绝对路径 　:application.getRealPath(request.getRequestURI());<br />
当前web应用的绝对路径 :application.getRealPath("/");<br />
取得请求文件的上层目录:new File(application.getRealPath(request.getRequestURI())).getParent()<br />
<br />
3.2 Servlet中获得当前应用的相对路径和绝对路径<br />
根目录所对应的绝对路径:request.getServletPath();<br />
文件的绝对路径 :request.getSession().getServletContext().getRealPath<br />
(request.getRequestURI())<br />
当前web应用的绝对路径 :servletConfig.getServletContext().getRealPath("/");<br />
(ServletContext对象获得几种方式：<br />
javax.servlet.http.HttpSession.getServletContext()<br />
javax.servlet.jsp.PageContext.getServletContext()<br />
javax.servlet.ServletConfig.getServletContext()<br />
)<br />
<br />
<strong>4.java 的Class中获得相对路径，绝对路径的方法<br />
<br />
</strong>4.1单独的Java类中获得绝对路径<br />
根据java.io.File的Doc文挡，可知:<br />
默认情况下new File("/")代表的目录为：System.getProperty("user.dir")。<br />
一下程序获得执行类的当前路径<br />
</font>
<div>
<div><font size="3">&nbsp;</font></div>
<ol>
    <li><font size="3">package&nbsp;org.cheng.file;&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;</font></li>
    <li><font size="3">import&nbsp;java.io.File;&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;</font></li>
    <li><font size="3">public&nbsp;class&nbsp;FileTest&nbsp;{&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getContextClassLoader().getResource(""));&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(FileTest.class.getClassLoader().getResource(""));&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(ClassLoader.getSystemResource(""));&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(FileTest.class.getResource(""));&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(FileTest.class.getResource("/"));</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</font>Class<font size="3">文件所在路径</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(new&nbsp;File("/").getAbsolutePath());&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(System.getProperty("user.dir"));&nbsp;&nbsp;</font></li>
    <li><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</font></li>
    <li><font size="3"><span style="line-height: 15px; font-size: 13px; ">}&nbsp;&nbsp;<br />
    </span></font></li>
</ol>
</div>
<font size="3"><br />
4.2服务器中的Java类获得当前路径（来自网络）<strong><br />
<br />
</strong>(1).Weblogic<br />
<br />
WebApplication的系统文件根目录是你的weblogic安装所在根目录。<br />
例如：如果你的weblogic安装在c:eaweblogic700.....<br />
那么，你的文件根路径就是c:.<br />
所以，有两种方式能够让你访问你的服务器端的文件：<br />
a.使用绝对路径：<br />
比如将你的参数文件放在c:yourconfigyourconf.properties，<br />
直接使用 new FileInputStream("yourconfig/yourconf.properties");<br />
b.使用相对路径：<br />
相对路径的根目录就是你的webapplication的根路径，即WEB-INF的上一级目录，将你的参数文件放<br />
<br />
在yourwebappyourconfigyourconf.properties，<br />
这样使用：<br />
new FileInputStream("./yourconfig/yourconf.properties");<br />
这两种方式均可，自己选择。<br />
<br />
(2).Tomcat<br />
<br />
在类中输出System.getProperty("user.dir");显示的是%Tomcat_Home%/bin<br />
<br />
(3).Resin<br />
<br />
不是你的JSP放的相对路径,是JSP引擎执行这个JSP编译成SERVLET<br />
的路径为根.比如用新建文件法测试File f = new File("a.htm");<br />
这个a.htm在resin的安装目录下<br />
<br />
(4).如何读相对路径哪？<br />
<br />
在Java文件中getResource或getResourceAsStream均可<br />
<br />
例：getClass().getResourceAsStream(filePath);//filePath可以是"/filename",这里的/代表web<br />
<br />
发布根路径下WEB-INF/classes<br />
<br />
默认使用该方法的路径是：WEB-INF/classes。已经在Tomcat中测试。<br />
<br />
5.读取文件时的相对路径，避免硬编码和绝对路径的使用。（来自网络）<br />
5.1 采用Spring的DI机制获得文件，避免硬编码。<br />
参考下面的连接内容：<br />
http://www.javajia.net/viewtopic.php?p=90213&amp;<br />
5.2 配置文件的读取<br />
参考下面的连接内容：<br />
http://dev.csdn.net/develop/article/39/39681.shtm<br />
<br />
<strong>5.3 通过虚拟路径或相对路径读取一个xml文件，避免硬编码<br />
<br />
</strong>参考下面的连接内容：<br />
http://club.gamvan.com/club/clubPage.jsp?iPage=1&amp;tID=10708&amp;ccID=8<br />
<br />
6.Java中文件的常用操作（复制，移动，删除，创建等）（来自网络）<br />
常用 java File 操作类<br />
http://www.easydone.cn/014/200604022353065155.htm<br />
<br />
Java文件操作大全（JSP中）<br />
http://www.pconline.com.cn/pcedu/empolder/gj/java/0502/559401.html<br />
<br />
java文件操作详解（Java中文网）<br />
http://www.51cto.com/html/2005/1108/10947.htm<br />
<br />
JAVA 如何创建删除修改复制目录及文件<br />
http://www.gamvan.com/developer/java/2005/2/264.html<br />
<br />
总结：<br />
通过上面内容的使用，可以解决在Web应用服务器端，移动文件，查找文件，复制<br />
删除文件等操作，同时对服务器的相对地址，绝对地址概念更加清晰。<br />
建议参考URI,的RFC标准文挡。同时对Java.io.File. Java.net.URI.等内容了解透彻<br />
对其他方面的理解可以更加深入和透彻。</font></span>
<img src ="http://www.blogjava.net/abram/aggbug/285762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/abram/" target="_blank">chong</a> 2009-07-07 10:58 <a href="http://www.blogjava.net/abram/articles/285762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA连接池(转)</title><link>http://www.blogjava.net/abram/articles/285761.html</link><dc:creator>chong</dc:creator><author>chong</author><pubDate>Tue, 07 Jul 2009 02:57:00 GMT</pubDate><guid>http://www.blogjava.net/abram/articles/285761.html</guid><wfw:comment>http://www.blogjava.net/abram/comments/285761.html</wfw:comment><comments>http://www.blogjava.net/abram/articles/285761.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/abram/comments/commentRss/285761.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/abram/services/trackbacks/285761.html</trackback:ping><description><![CDATA[<span  style="font-family: Verdana; font-size: 13px; line-height: 16px; ">
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">package com.xinnuo.jdbc;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">import java.io.*;<br />
import java.sql.*;<br />
import java.util.*;<br />
import java.util.Date;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/*<br />
&nbsp; * 该类只能创建一个实例，其它对象能够调用其静态方法（也称为类方法）获得该唯一实例的引用。<br />
&nbsp; * DBConnectionManager类的建构函数是私有的，这是为了避免其它对象创建该类的实例.<br />
&nbsp; * DBConnectionManager类的客户程序可以调用getInstance()方法获得对该类唯一实例的引用。<br />
&nbsp; * 类的唯一实例在getInstance()方法第一次被调用期间创建，此后其引用就一直保存在静态变量<br />
&nbsp; * instance中。每次调用getInstance()都增加一个DBConnectionManager的客户程序计数。<br />
&nbsp; * 即，该计数代表引用DBConnectionManager唯一实例的客户程序总数，它将被用于控制连接池的<br />
&nbsp; * 关闭操作。 该类实例的初始化工作私有方法init()完成。其中 getResourceAsStream()方法<br />
&nbsp; * 用于定位并打开外部文件。外部文件的定位方法依赖于类装载器的实现。标准的本地类装载器查找操<br />
&nbsp; * 作总是开始于类文件所在路径，也能够搜索CLASSPATH中声明的路径。db.properties是一个属性<br />
&nbsp; * 文件，它包含定义连接池的键-值对。可供定义的公用属性如下：&nbsp;<br />
&nbsp; * &nbsp;&nbsp;drivers 以空格分隔的JDBC驱动程序类列表""&nbsp;<br />
&nbsp; * &nbsp;&nbsp;logfile 日志文件的绝对路径&nbsp;<br />
&nbsp; *&nbsp;&nbsp;其它的属性和特定连接池相关，其属性名字前应加上连接池名字：&nbsp;<br />
&nbsp; *&nbsp;&nbsp;&lt; poolname&gt;.url 数据库的 JDBC URL&nbsp;<br />
&nbsp; *&nbsp;&nbsp;&lt; poolname&gt;.maxconn 允许建立的最大连接数，0表示没有限制&nbsp;<br />
&nbsp; *&nbsp;&nbsp;&lt; poolname&gt;.user 用于该连接池的数据库帐号&nbsp;<br />
&nbsp; *&nbsp;&nbsp;&lt; poolname&gt;.password 相应的密码""<br />
&nbsp; *&nbsp;其中url属性是必需的，而其它属性则是可选的。数据库帐号和密码必须合法。用于Windows平台的<br />
&nbsp; *&nbsp;db.properties文件示例如下：<br />
&nbsp; *&nbsp;&nbsp;drivers=com.microsoft.jdbc.sqlserver.SQLServerDriver<br />
&nbsp; *&nbsp;&nbsp;logfile=D:""log.txt<br />
&nbsp; *&nbsp;&nbsp;access.maxconn=20<br />
&nbsp; *&nbsp;&nbsp;access.url=jdbc:microsoft:sqlserver://localhost:1433;databasename=web<br />
&nbsp; *&nbsp;&nbsp;access.user=sa<br />
&nbsp; *&nbsp;&nbsp;access.password=sa&nbsp;<br />
&nbsp; *&nbsp;注意在Windows路径中的反斜杠必须输入2个，这是由于属性文件中的反斜杠同时也是一个转义字符。<br />
&nbsp; *&nbsp;init()方法在创建属性对象并读取db.properties文件之后，就开始检查logfile属性。如果属<br />
&nbsp; *&nbsp;性文件中没有指定日志文件，则默认为当前目录下的DBConnectionManager.log文件。如日志文<br />
&nbsp; *&nbsp;件无法使用，则向System.err输出日志记录。装载和注册所有在drivers属性中指定的JDBC驱动<br />
&nbsp; *&nbsp;程序loadDrivers()方法实现。该方法先用StringTokenizer将drivers属性值分割为对应于驱<br />
&nbsp; *&nbsp;动程序名称的字符串，然后依次装载这些类并创建其实例，最后在DriverManager中注册该实例并把<br />
&nbsp; *&nbsp;它加入到一个私有的向量drivers。向量drivers将用于关闭服务时从DriverManager取消所有<br />
&nbsp; *&nbsp;JDBC 驱动程序的注册。init()方法的最后一个任务是调用私有方法createPools()创建连接池对<br />
&nbsp; *&nbsp;象。createPools()方法先创建所有属性名字的枚举对象（即Enumeration对象，该对象可以想象<br />
&nbsp; *&nbsp;为一个元素系列，逐次调用其nextElement()方法将顺序返回各元素），然后在其中搜索名字以&#8220;.url&#8221;<br />
&nbsp; *&nbsp;结尾的属性。对于每一个符合条件的属性，先提取其连接池名字部分，进而读取所有属于该连接池的属性，<br />
&nbsp; *&nbsp;最后创建连接池对象并把它保存在实例变量pools中。散列表（Hashtable类 ）pools实现连接池名字<br />
&nbsp; *&nbsp;到连接池对象之间的映射，此处以连接池名字为键，连接池对象为值。 为便于客户程序从指定连接池获<br />
&nbsp; *&nbsp;得可用连接或将连接返回给连接池，类DBConnectionManager提供了方法getConnection()和<br />
&nbsp; *&nbsp;freeConnection()。所有这些方法都要求在参数中指定连接池名字，具体的连接获取或返回操作则调<br />
&nbsp; *&nbsp;用对应的连接池对象完成。为实现连接池的安全关闭，DBConnectionManager提供了方法release()。<br />
&nbsp; *&nbsp;在上面我们已经提到，所有DBConnectionManager的客户程序都应该调用静态方法getInstance()<br />
&nbsp; *&nbsp;以获得该管理器的引用，此调用将增加客户程序计数。客户程序在关闭时调用release()可以递减该计数。<br />
&nbsp; *&nbsp;当最后一个客户程序调用release()，递减后的引用计数为0，就可以调用各个连接池的release()方法<br />
&nbsp; *&nbsp;关闭所有连接了。管理类release()方法最后的任务是撤销所有JDBC驱动程序的注册。<br />
&nbsp; */</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">/**<br />
&nbsp;* 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接<br />
&nbsp;* 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例.<br />
&nbsp;*/<br />
public class DBConnectionManager {<br />
&nbsp;static private DBConnectionManager instance; // 唯一实例</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;static private int clients;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;private Vector drivers = new Vector();</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;private PrintWriter log;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;private Hashtable pools = new Hashtable();</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 返回唯一实例.如果是第一次调用此方法,则创建实例<br />
&nbsp; * @return DBConnectionManager 唯一实例<br />
&nbsp; */<br />
&nbsp;static synchronized public DBConnectionManager getInstance() {<br />
&nbsp;&nbsp;if (instance == null) {<br />
&nbsp;&nbsp;&nbsp;instance = new DBConnectionManager();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;clients++;<br />
&nbsp;&nbsp;return instance;<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 建构函数私有以防止其它对象创建本类实例<br />
&nbsp; */<br />
&nbsp;private DBConnectionManager() {<br />
&nbsp;&nbsp;init();<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * * 将连接对象返回给由名字指定的连接池<br />
&nbsp; * @param name在属性文件中定义的连接池名字<br />
&nbsp; * @param con连接对象<a>""""r</a><br />
&nbsp; */<br />
&nbsp;public void freeConnection(String name, Connection con) {<br />
&nbsp;&nbsp;DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br />
&nbsp;&nbsp;if (pool != null) {<br />
&nbsp;&nbsp;&nbsp;pool.freeConnection(con);<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数 053 * 限制,则创建并返回新连<br />
&nbsp; * @param name在属性文件中定义的连接池名字 056 *<br />
&nbsp; * @return Connection 可用连接或null 057<br />
&nbsp; */<br />
&nbsp;public Connection getConnection(String name) {<br />
&nbsp;&nbsp;DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br />
&nbsp;&nbsp;if (pool != null) {<br />
&nbsp;&nbsp;&nbsp;return pool.getConnection();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return null;<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,&nbsp;<br />
&nbsp; * 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.<br />
&nbsp; * @param name 连接池名字 071 *<br />
&nbsp; * @param time以毫秒计的等待时间<a>""""r</a><br />
&nbsp; * @return Connection 可用连接或null<br />
&nbsp; */<br />
&nbsp;public Connection getConnection(String name, long time) {<br />
&nbsp;&nbsp;DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br />
&nbsp;&nbsp;if (pool != null) {<br />
&nbsp;&nbsp;&nbsp;return pool.getConnection(time);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return null;<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 关闭所有连接,撤销驱动程序的注册<a>""""r</a><br />
&nbsp; */<br />
&nbsp;public synchronized void release() {<br />
&nbsp;&nbsp;// 等待直到最后一个客户程序调用<br />
&nbsp;&nbsp;if (--clients != 0) {<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;Enumeration allPools = pools.elements();<br />
&nbsp;&nbsp;while (allPools.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();<br />
&nbsp;&nbsp;&nbsp;pool.release();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;Enumeration allDrivers = drivers.elements();<br />
&nbsp;&nbsp;while (allDrivers.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;Driver driver = (Driver) allDrivers.nextElement();<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;DriverManager.deregisterDriver(driver);<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("撤销JDBC驱动程序 " + driver.getClass().getName() + "的注册");<br />
&nbsp;&nbsp;&nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 根据指定属性创建连接池实例.<br />
&nbsp; * @param props 连接池属性 113<br />
&nbsp; */<br />
&nbsp;private void createPools(Properties props) {<br />
&nbsp;&nbsp;Enumeration propNames = props.propertyNames();<br />
&nbsp;&nbsp;while (propNames.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;String name = (String) propNames.nextElement();<br />
&nbsp;&nbsp;&nbsp;if (name.endsWith(".url")) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;String poolName = name.substring(0, name.lastIndexOf("."));<br />
&nbsp;&nbsp;&nbsp;&nbsp;String url = props.getProperty(poolName + ".url");<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (url == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("没有为连接池" + poolName + "指定URL");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;String user = props.getProperty(poolName + ".user");<br />
&nbsp;&nbsp;&nbsp;&nbsp;String password = props.getProperty(poolName + ".password");<br />
&nbsp;&nbsp;&nbsp;&nbsp;String maxconn = props.getProperty(poolName + ".maxconn", "0");<br />
&nbsp;&nbsp;&nbsp;&nbsp;int max;<br />
&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = Integer.valueOf(maxconn).intValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;} catch (NumberFormatException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;DBConnectionPool pool = new DBConnectionPool(poolName, url,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user, password, max);<br />
&nbsp;&nbsp;&nbsp;&nbsp;pools.put(poolName, pool);<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("成功创建连接池" + poolName);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 读取属性完成初始化<br />
&nbsp; */<br />
&nbsp;private void init() {<br />
&nbsp;&nbsp;InputStream is = getClass().getResourceAsStream("/db.properties");<br />
&nbsp;&nbsp;Properties dbProps = new Properties();<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;dbProps.load(is);<br />
&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;System.err.println("不能读取属性文件. "+"请确保db.properties在CLASSPATH指定的路径中");<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;String logFile = dbProps.getProperty("logfile","DBConnectionManager.log");<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;log = new PrintWriter(new FileWriter(logFile, true), true);<br />
&nbsp;&nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;System.err.println("无法打开日志文件: " + logFile);<br />
&nbsp;&nbsp;&nbsp;log = new PrintWriter(System.err);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;loadDrivers(dbProps);<br />
&nbsp;&nbsp;createPools(dbProps);<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 装载和注册所有JDBC驱动程序<br />
&nbsp; * @param props属性<br />
&nbsp; */<br />
&nbsp;private void loadDrivers(Properties props) {<br />
&nbsp;&nbsp;String driverClasses = props.getProperty("drivers");&nbsp;<br />
&nbsp;&nbsp;StringTokenizer st = new StringTokenizer(driverClasses);<br />
&nbsp;&nbsp;while (st.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;String driverClassName = st.nextToken().trim();&nbsp;<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Driver driver = (Driver) Class.forName(driverClassName).newInstance();<br />
&nbsp;&nbsp;&nbsp;&nbsp;DriverManager.registerDriver(driver);<br />
&nbsp;&nbsp;&nbsp;&nbsp;drivers.addElement(driver);<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("成功注册JDBC驱动程序" + driverClassName);<br />
&nbsp;&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("无法注册JDBC驱动程序: " + driverClassName + ", 错误: " + e);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 将文本信息写入日志文件<br />
&nbsp; */<br />
&nbsp;private void log(String msg) {<br />
&nbsp;&nbsp;log.println(new Date() + ": " + msg);<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 将文本信息与异常写入日志文件<br />
&nbsp; */<br />
&nbsp;private void log(Throwable e, String msg) {<br />
&nbsp;&nbsp;log.println(new Date() + ": " + msg);<br />
&nbsp;&nbsp;e.printStackTrace(log);<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;// ///////////////////////////////////////////////////////////////////////////////////////////////////////<br />
&nbsp;// ///////////////////////////////////////////////////////////////////////////////////////////////////////<br />
&nbsp;/*<br />
&nbsp; * DBConnectionPool实现，它表示指向某个数据库的连接池。数据库由JDBC URL标识。一个JDBCURL由三部分组成：协议标识（总是jdbc），<br />
&nbsp; * 驱动程序标识（如odbc、idb、oracle等），数据库标识（其格式依赖于驱动程序）。例如，jdbc:odbc:demo，即是一个指向demo数据&nbsp;<br />
&nbsp; * 库的JDBCURL，而且访问该数据库要使用JDBC-ODBC驱动程序。每个连接池都有一个供客户程序使用的名字以及可选的用户帐号、密码、最<br />
&nbsp; * 大连接数限制。如果Web应用程序所支持的某些数据库操作可以被所有用户执行，而其它一些操作应由特别许可的用户执行，则可以为两类操作<br />
&nbsp; * 分别定义连接池，两个连接池使用相同的JDBC URL，但使用不同的帐号和密码。类DBConnectionPool的建构函数需要上述所有数据作为其<br />
&nbsp; * 参数。客户程序可以使用DBConnectionPool<br />
&nbsp; * 类提供的两个方法获取可用连接。两者的共同之处在于：如连接池中存在可用连接，则直接返回，否则创建新的连接并返回。如果没有可用连接<br />
&nbsp; * 且已有连接总数等于最大限制数，第一个方法将直接返回null，而第二个方法将等待直到有可用连接为止。所有的可用连接对象均登记在名为<br />
&nbsp; * freeConnections的向量（Vector）中。如果向量中有多于一个的连接，getConnection()总是选取第一个。同时，由于新的可用连接总<br />
&nbsp; * 是从尾部加入向量，从而使得数据库连接由于长时间闲置而被关闭的风险减低到最小程度。 第一个getConnection()在返回可用连接给客户<br />
&nbsp; * 程序之前，调用了isClosed()方法验证连接仍旧有效。如果该连接被关闭或触发异常，getConnection()递归地调用自己以尝试获取另外的<br />
&nbsp; * 可用连接。如果在向量freeConnections中不存在任何可用连接，getConnection()方法检查是否已经指定最大连接数限制。如已经指定，<br />
&nbsp; * 则检查当前连接数是否已经到达极限。此处maxConn为0表示没有限制。如果没有指定最大连接数限制或当前连接数小于该值，该方法尝试创建<br />
&nbsp; * 新的连接。如创建成功，则增加已使用连接的计数并返回，否则返回空值。创建新连接由newConnection()方法实现。<br />
&nbsp; * 创建过程与是否已经指定数据库帐号、密码有关。JDBC的DriverManager类提供多个getConnection()方法，这些方法要用到JDBC URL<br />
&nbsp; * 与其它一些参数，如用户帐号和密码等。DriverManager将使用指定的JDBC URL确定适合于目标数据库的驱动程序及建立连接。<br />
&nbsp; * 第二个getConnection()方法需要一个以毫秒为单位的时间参数，该参数表示客户程序能够等待的最长时间。建立连接的具体操<br />
&nbsp; * 作仍旧由第一个getConnection()方法实现。该方法执行时先将startTime初始化为当前时间。在while循环中尝试获得一个连接。如果失<br />
&nbsp; * 败，则以给定的时间值为参数调用wait()。wait()的返回可能是由于其它线程调用notify()或notifyAll()，也可能是由于预定时间已到。<br />
&nbsp; * 为找出wait()返回的真正原因，程序用当前时间减开始时间（startTime），如差值大于预定时间则返回空值，否则再次调用getConnection()。<br />
&nbsp; * 把空闲的连接登记到连接池由freeConnection()方法实现，它的参数为返回给连接池的连接对象。该对象被加入到freeConnections<br />
&nbsp; * 向量的末尾，然后减少已使用连接计数。调用notifyAll()是为了通知其它正在等待可用连接的线程。 许多Servlet引擎为实现安全关闭提供<br />
&nbsp; * 多种方法。数据库连接池需要知道该事件以保证所有连接能够正常关闭。DBConnectionManager类负协调整个关闭过程，但关闭连接池中所有连<br />
&nbsp; * 接的任务则由DBConnectionPool类负责。release()方法供DBConnectionManager调用。该方法遍历freeConnections向量并关闭所有连接，<br />
&nbsp; * 然后从向量中删除这些连接。<br />
&nbsp; */</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/**<br />
&nbsp; * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最<a>""""r</a><br />
&nbsp; */<br />
&nbsp;class DBConnectionPool {<br />
&nbsp;&nbsp;private int checkedOut;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;private Vector freeConnections = new Vector();</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;private int maxConn;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;private String name;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;private String password;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;private String URL;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;private String user;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 创建新的连接池<br />
&nbsp;&nbsp; * @param name连接池名字<br />
&nbsp;&nbsp; * @param URL数据库的JDBC URL<br />
&nbsp;&nbsp; * @param user数据库帐号,或 null<br />
&nbsp;&nbsp; * @param password密码,或 null<br />
&nbsp;&nbsp; * @param maxConn此连接池允许建立的最大连接数<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public DBConnectionPool(String name, String URL, String user,<br />
&nbsp;&nbsp;&nbsp;&nbsp;String password, int maxConn) {<br />
&nbsp;&nbsp;&nbsp;this.name = name;<br />
&nbsp;&nbsp;&nbsp;this.URL = URL;<br />
&nbsp;&nbsp;&nbsp;this.user = user;<br />
&nbsp;&nbsp;&nbsp;this.password = password;<br />
&nbsp;&nbsp;&nbsp;this.maxConn = maxConn;<br />
&nbsp;&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 将不再使用的连接返回给连接池<br />
&nbsp;&nbsp; * @param con客户程序释放的连接<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public synchronized void freeConnection(Connection con) {<br />
&nbsp;&nbsp;&nbsp;// 将指定连接加入到向量末尾<br />
&nbsp;&nbsp;&nbsp;freeConnections.addElement(con);<br />
&nbsp;&nbsp;&nbsp;checkedOut--;<br />
&nbsp;&nbsp;&nbsp;notifyAll();<br />
&nbsp;&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接 数限制,则创建新连接.<br />
&nbsp;&nbsp; * 如原来登记为可用的连接不再有效,则从向量删除之,<br />
&nbsp;&nbsp; * 然后递归调用自己以尝试新的可用连接.<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public synchronized Connection getConnection() {<br />
&nbsp;&nbsp;&nbsp;Connection con = null;<br />
&nbsp;&nbsp;&nbsp;if (freeConnections.size() &gt; 0) {// 获取向量中第一个可用连接<br />
&nbsp;&nbsp;&nbsp;&nbsp;con = (Connection) freeConnections.firstElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;freeConnections.removeElementAt(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (con.isClosed()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("从连接池" + name + "删除一个无效连接");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 递归调用自己,尝试再次获取可用连接<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con = getConnection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("从连接池" + name + "删除一个无效连接");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 递归调用自己,尝试再次获取可用连接<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con = getConnection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;} else if (maxConn == 0 || checkedOut &lt; maxConn) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;con = newConnection();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;if (con != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;checkedOut++;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return con;<br />
&nbsp;&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 从连接池获取可用连接.可以指定客户程序能够等待的最长时间 参见前一个getConnection()方法.<br />
&nbsp;&nbsp; * @param timeout以毫秒计的等待时间限制<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public synchronized Connection getConnection(long timeout) {<br />
&nbsp;&nbsp;&nbsp;long startTime = new Date().getTime();<br />
&nbsp;&nbsp;&nbsp;Connection con;<br />
&nbsp;&nbsp;&nbsp;while ((con = getConnection()) == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait(timeout);<br />
&nbsp;&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;if ((new Date().getTime() - startTime) &gt;= timeout) {// wait()返回的原因是超时<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return con;<br />
&nbsp;&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 关闭所有连接<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public synchronized void release() {<br />
&nbsp;&nbsp;&nbsp;Enumeration allConnections = freeConnections.elements();<br />
&nbsp;&nbsp;&nbsp;while (allConnections.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Connection con = (Connection) allConnections.nextElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("关闭连接池" + name + "中的一个连接");<br />
&nbsp;&nbsp;&nbsp;&nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log(e, "无法关闭连接池" + name + "中的连接");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;freeConnections.removeAllElements();<br />
&nbsp;&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 创建新的连接<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;private Connection newConnection() {<br />
&nbsp;&nbsp;&nbsp;Connection con = null;<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (user==null||"".equals(user)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con = DriverManager.getConnection(URL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con = DriverManager.getConnection(URL, user, password);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("连接池" + name + "创建一个新的连接");<br />
&nbsp;&nbsp;&nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;log(e, "无法创建下列URL的连接: " + URL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;return null;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return con;<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">&nbsp;/////////////////////////////////////////////////////////////////////////////////////////////<br />
&nbsp;/////////////////////////////////////////////////////////////////////////////////////////////<br />
}<br />
<br />
在sqlserver2000，tomcat5.5验证通过</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">方法调用！</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">package com.xinnuo.jdbc;</p>
<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; ">import java.sql.Connection;<br />
import java.sql.ResultSet;<br />
import java.sql.SQLException;<br />
import java.sql.Statement;</p>
public class DBConn {<br />
&nbsp;private DBConnectionManager connMgr = null;<br />
&nbsp;private Connection conn = null;<br />
&nbsp;private Statement stat = null;<br />
&nbsp;private ResultSet rs = null;<br />
&nbsp;public DBConn() {<br />
&nbsp;&nbsp;connMgr = DBConnectionManager.getInstance();<br />
&nbsp;}<br />
&nbsp;public ResultSet executeQuery(String strSQL) throws SQLException {<br />
&nbsp;&nbsp;this.conn = connMgr.getConnection("access");<br />
&nbsp;&nbsp;this.stat = this.conn.createStatement();<br />
&nbsp;&nbsp;this.rs = this.stat.executeQuery(strSQL);<br />
&nbsp;&nbsp;return this.rs;<br />
&nbsp;}<br />
&nbsp;public void execute(String strSQL) throws SQLException {<br />
&nbsp;&nbsp;this.conn = connMgr.getConnection("access");<br />
&nbsp;&nbsp;this.stat = this.conn.createStatement();<br />
&nbsp;&nbsp;this.stat.execute(strSQL);<br />
&nbsp;}<br />
&nbsp;public void executeUpdate(String strSQL) throws SQLException {<br />
&nbsp;&nbsp;this.conn = connMgr.getConnection("access");<br />
&nbsp;&nbsp;this.stat = this.conn.createStatement();<br />
&nbsp;&nbsp;this.stat.executeUpdate(strSQL);<br />
&nbsp;}<br />
&nbsp;public Connection getConnection(){<br />
&nbsp;&nbsp;this.conn = connMgr.getConnection("access");<br />
&nbsp;&nbsp;return this.conn;<br />
&nbsp;}<br />
&nbsp;public void free(){<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;if (this.rs != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.rs.close();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;if (this.stat != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.stat.close();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;connMgr.freeConnection("access", this.conn);<br />
&nbsp;}<br />
}</span>
<img src ="http://www.blogjava.net/abram/aggbug/285761.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/abram/" target="_blank">chong</a> 2009-07-07 10:57 <a href="http://www.blogjava.net/abram/articles/285761.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>