﻿<?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-苦涩的JAVA淡淡的余香</title><link>http://www.blogjava.net/wangyong/</link><description /><language>zh-cn</language><lastBuildDate>Tue, 05 May 2026 21:58:27 GMT</lastBuildDate><pubDate>Tue, 05 May 2026 21:58:27 GMT</pubDate><ttl>60</ttl><item><title>持久层设计与资源管理模式一</title><link>http://www.blogjava.net/wangyong/archive/2007/08/02/133919.html</link><dc:creator>CoolYongZi</dc:creator><author>CoolYongZi</author><pubDate>Thu, 02 Aug 2007 01:49:00 GMT</pubDate><guid>http://www.blogjava.net/wangyong/archive/2007/08/02/133919.html</guid><wfw:comment>http://www.blogjava.net/wangyong/comments/133919.html</wfw:comment><comments>http://www.blogjava.net/wangyong/archive/2007/08/02/133919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangyong/comments/commentRss/133919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangyong/services/trackbacks/133919.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;无论是怎样的应用系统，都无法脱离对资源的管理和使用。而对于持久层而言，资源的合理管理和调度则显得尤为重要。在大多所应用系统中，80%以上的应用逻辑并不需要特别复杂的数据访问逻辑(可能只是几条简单的Select或者Insert/Update语句)。对于这些占大多数的简单逻辑而言，如果SQL语句和数据库本身的设计不是太糟糕(合理的关联，字段索引以及数据库分区策略)，在特定的硬件环境...&nbsp;&nbsp;<a href='http://www.blogjava.net/wangyong/archive/2007/08/02/133919.html'>阅读全文</a><img src ="http://www.blogjava.net/wangyong/aggbug/133919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangyong/" target="_blank">CoolYongZi</a> 2007-08-02 09:49 <a href="http://www.blogjava.net/wangyong/archive/2007/08/02/133919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于JDBC的数据库连接池高效管理策略</title><link>http://www.blogjava.net/wangyong/archive/2007/08/01/133822.html</link><dc:creator>CoolYongZi</dc:creator><author>CoolYongZi</author><pubDate>Wed, 01 Aug 2007 08:15:00 GMT</pubDate><guid>http://www.blogjava.net/wangyong/archive/2007/08/01/133822.html</guid><wfw:comment>http://www.blogjava.net/wangyong/comments/133822.html</wfw:comment><comments>http://www.blogjava.net/wangyong/archive/2007/08/01/133822.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangyong/comments/commentRss/133822.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangyong/services/trackbacks/133822.html</trackback:ping><description><![CDATA[<p>在基于JDBC的数据库应用开发中，数据库连接的管理是一个难点，因为它是决定该应用性能的一个重要因素。本文在对数据库连接进行透彻分析的基础上，提出并实现了一个高效的连接管理策略，使得开发高性能的数据库应用变得相对容易。特别是，对于连接管理中的两个难点：事务和多线程问题进行了深入的剖析，并给出了一个基于设计模式的解决方案。<br>介绍</p>
<p>在使用Java语言进行和数据库有关的的应用开发中，一般都使用JDBC来进行和数据库的交互，其中有一个关键的概念就是Connection（连接），它在Java中是一个类，代表了一个通道。通过它，使用数据的应用就可以从数据库访问数据了。</p>
<p>对于一个简单的数据库应用，由于对于数据库的访问不是很频繁。这时可以简单地在需要访问数据库时，就新创建一个连接，用完后就关闭它，这样做也不会带来什么明显的性能上的开销。但是对于一个复杂的数据库应用，情况就完全不同了。频繁的建立、关闭连接，会极大的减低系统的性能，因为对于连接的使用成了系统性能的瓶颈。</p>
<p>本文给出的方法可以有效的解决这个问题。在本方法中提出了一个合理、有效的连接管理策略，避免了对于连接的随意、无规则的使用。该策略的核心思想是：连接复用。通过建立一个数据库连接池以及一套连接使用管理策略，使得一个数据库连接可以得到高效、安全的复用，避免了数据库连接频繁建立、关闭的开销。另外，由于对JDBC中的原始连接进行了封装，从而方便了数据库应用对于连接的使用（特别是对于事务处理），提高了开发效率，也正是因为这个封装层的存在，隔离了应用的本身的处理逻辑和具体数据库访问逻辑，使应用本身的复用成为可能。</p>
<p>问题产生\r</p>
<p>我参与的项目是开发一个网管系统，不可避免的要和数据库打交道。刚开始时，由于对于数据库的访问不是很频繁，对于数据库连接的使用就是简单的需要时就建立，用完就关闭的策略，这很符合XP（eXtreme Programming）的口号："Do the Simplest Thing that Could Possibly Work"。确实，开始时工作的很好。随着项目的进展，对于数据库的访问开始变的频繁，问题就暴露出来了，原先的通过简单地获取和关闭数据库连接的方法将很大的影响系统的性能，这种影响是由于数据库资源管理器进程频繁的创建和摧毁那些连接对象而引起的。</p>
<p>此时，就有必要对数据库访问方法进行重构（refactoring），因为我们确实需要进行改进，来提高系统的性能。</p>
<p>解决方案</p>
<p>可以看出，问题的根源就是由于对于连接资源的低效管理造成的。对于共享资源，有一个很著名的设计模式：资源池。该模式正是为了解决资源频繁分配、释放所造成的问题的。把该模式应用到数据库连接管理领域，就是建立一个数据库连接池，提供一套高效的连接分配、使用策略，最终目标是实现连接的高效、安全的复用。</p>
<p>3.1、建立连接池</p>
<p>第一步，就是要建立一个静态的连接池，所谓静态是指，池中的连接是在系统初始化时就分配好的，并且不能够随意关闭的。Java中给我们提供很多容器类可以方便的用来构建连接池，如：Vector、Stack等。在系统初始化时，根据配置创建连接并放置在连接池中，以后所使用的连接都是从该连接池中获取的，这样就可以避免连接随意建立、关闭造成的开销（当然，我们没有办法避免Java的Garbage Collection带来的开销）。</p>
<p>3.2、分配、释放策略</p>
<p>有了这个连接池，下面我们就可以提供一套自定义的分配、释放策略。</p>
<p>当客户请求数据库连接时，首先看连接池中是否有空闲连接，这里的空闲是指，目前没有分配出去的连接。如果存在空闲连接则把连接分配给客户，并作相应处理，具体处理策略，在关键议题中会详述，主要的处理策略就是标记该连接为已分配。若连接池中没有空闲连接，就在已经分配出去的连接中，寻找一个合适的连接给客户（选择策略会在关键议题中详述），此时该连接在多个客户间复用。</p>
<p>当客户释放数据库连接时，可以根据该连接是否被复用，进行不同的处理。如果连接没有使用者，就放入到连接池中，而不是被关闭。</p>
<p>可以看出正是这套策略保证了数据库连接的有效复用。</p>
<p>3.3、配置策略</p>
<p>数据库连接池中到底要放置多少个连接，连接耗尽后该如何处理呢？这时一个配置策略。一般的配置策略是，开始时，根据具体的应用需求，给出一个初始的连接池中连接的数目以及一个连接池可以扩张到的最大连接数目。本方案就是按照这种策略实现的。</p>
<p>关键议题\r</p>
<p>本节将对上述解决方案中的关键细节进行详述，正是这些关键的策略保证了数据库连接复用的高效和安全。</p>
<p>4.1、引用记数</p>
<p>3.2节中的分配、释放策略对于有效复用连接非常重要，我们采用的方法也是采用了一个很有名的设计模式：Reference Counting（引用记数）。该模式在复用资源方面用的非常广泛，我们把该方法运用到对于连接的分配释放上。每一个数据库连接，保留一个引用记数，用来记录该连接的使用者的个数。具体的实现上，我们采用了两极连接池，空闲池和使用池。空闲池中存放目前还没有分配出去被使用的连接，一旦一个连接被分配出去，那么就会放入到使用池中，并且增加引用记数。</p>
<p>这样做有一个很大的好处，使得我们可以高效的使用连接，因为一旦空闲池中的连接被全部分配出去，我们就可以根据相应的策略从使用池中挑选出一个已经正在使用的连接用来复用，而不是随意拿出一个连接去复用。策略可以根据需要去选择，我们采用的策略比较简单：复用引用记数最小的连接。Java的面向对象特性，使得我们可以灵活的选择不同的策略（提供一个不同策略共用的抽象接口，各个具体的策略都实现这个接口，这样对于策略的处理逻辑就和策略的实现逻辑分离）。</p>
<p>4.2、事务处理\r</p>
<p>前面谈到的都是关于使用数据库连接进行普通的数据库访问。对于事务处理，情况就变得比较复杂。因为事务本身要求原子性的保证，此时就要求对于数据库的操作符合"All-All-Nothing"原则，即要么全部完成，要么什么都不做。如果简单的采用上述的连接复用的策略，就会发生问题，因为没有办法控制属于同一个事务的多个数据库操作方法的动作，可能这些数据库操作是在多个连接上进行的，并且这些连接可能被其他非事务方法复用。</p>
<p>Connection本身具有提供了对于事务的支持，可以通过设置Connection的AutoCommit属性为false，显式的调用commit或者rollback方法来实现。但是要安全、高效的进行Connection进行复用，就必须提供相应的事务支持机制。我们采用的方法是：采用显式的事务支撑方法，每一个事务独占一个连接。这种方法可以大大降低对于事务处理的复杂性（如果事务不独占一条连接，那么要保证事务的原子性并且又不妨碍复用该连接的其他和该事务无关的操作，基本上不可能，除非Connection类是你开发的），并且又不会妨碍连接的复用，因为隶属于该事务的所有数据库操作都是通过这一个连接完成的，并且事务方法又复用了其他一些数据库方法。</p>
<p>在我们的连接管理服务提供了显式的事务开始、结束（commit或者rollback）声明，以及一个事务注册表，用于登记事务发起者和事务使用的连接的对应关系，通过该表，使用事务的部分和我们的连接管理部分就隔离开，因为该表是在运行时根据实际的调用情况，动态生成的。事务使用的连接在该事务运行中不能被复用。</p>
<p>当使用者需要使用事务方法时，首先调用连接管理服务提供的beginTrans方法，该方法主要处理流程如下(伪码描述)：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void beginTrans( ) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn = getIdleConnectionFromPoll( );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; userId = getUserId( );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; registerTrans(userId, conn);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;<br>} </p>
<p><br>&nbsp;</p>
<p>&nbsp;</p>
<p>在我们的实现中，用户标识是通过使用者所在的线程来标识的。后面的所有对于数据库的访问都是通过查找该注册表，使用已经分配的连接来完成的。当事务结束时，从注册表中删除相应表项。</p>
<p>对于嵌套的事务如何处理呢？我们采用的方法仍为引用记数，不过这里的引用记数是指的"嵌套层次"，具体的细节，不再赘述。</p>
<p>4.3、封装</p>
<p>从上面的论述可以看出，普通的数据库方法和事务方法对于连接的使用（分配、释放）是不同的，为了便于使用，对外提供一致的操作接口，我们对连接进行了封装：即普通连接和事务连接。在此，我们利用了Java中的强大的面向对象特性：多态。普通连接和事务连接均实现了一个DbConnection接口，对于接口中定义的方法，分别根据自己的特点作了不同的实现，这样在对于连接的处理上就非常的一致了。</p>
<p>4.4、并发问题\r</p>
<p>为了是我们的连接管理服务有更大的通用性，就必须要考虑到多线程环境，即并发问题。在一个多线程的环境下，我们必须要保证连接管理自身数据的一致性和连接内部数据是一致性，还好Java提供对这方面的很好的支持（synchronized关键字），这样我们就很容易使连接管理成为线程安全的。</p>
<p>5、结论</p>
<p>本文给出了一个基本的连接管理框架，在其中使用了一些广泛使用的设计模式（资源池，引用记数等），使得高效、安全的复用数据库连接成为可能。当然，还有一些问题没有考虑到，比如：没有实现对不同种类的数据库的联合管理；没有提供定时检测机制，查询连接的状态等。另外在连接管理的使用包装上比起一些商用的系统还显粗糙，但是底层的基理是一致的，所以通过本文相信对于这些商用的产品中的相关功能会有更好的理解。</p>
<p>参考文献<br>《Thinking in Java》Bruce Eckel</p>
<p>《Real-Time Design Patterns》 Bruce Powel Dougladd<br></p>
<img src ="http://www.blogjava.net/wangyong/aggbug/133822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangyong/" target="_blank">CoolYongZi</a> 2007-08-01 16:15 <a href="http://www.blogjava.net/wangyong/archive/2007/08/01/133822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts分页</title><link>http://www.blogjava.net/wangyong/archive/2007/08/01/133821.html</link><dc:creator>CoolYongZi</dc:creator><author>CoolYongZi</author><pubDate>Wed, 01 Aug 2007 08:11:00 GMT</pubDate><guid>http://www.blogjava.net/wangyong/archive/2007/08/01/133821.html</guid><wfw:comment>http://www.blogjava.net/wangyong/comments/133821.html</wfw:comment><comments>http://www.blogjava.net/wangyong/archive/2007/08/01/133821.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangyong/comments/commentRss/133821.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangyong/services/trackbacks/133821.html</trackback:ping><description><![CDATA[<p>拜读了bibiye的《一个高效简洁的Struts分页方法(原创)》后，根据bibiye的方法，自己修改了一下，也弄了一个struts下的分页，大家见笑了！</p>
<p>我的方法是，根据用户点击导航条上的页号(offset)，到DB中读取该页的数据(不是一次全部读出)，点到哪页读哪页的数据，JBX + tomcat + oracle下测试通过，数据库用的表是oracle的emp表。</p>
<p>********分页类Pager.java，负责生成分页导航条********</p>
<p>package page;</p>
<p>/**<br>&nbsp;* 分页代码<br>&nbsp;* &lt;p&gt;Title: 分页&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Description: &lt;/p&gt;<br>&nbsp;* &lt;p&gt;Copyright: Copyright (c) 2005&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Company: BCS&lt;/p&gt;<br>&nbsp;* @author Alex<br>&nbsp;* @version 1.0<br>&nbsp;*/<br>public class Pager {<br>&nbsp; private int offset;<br>&nbsp; private int size;<br>&nbsp; private int length;<br>&nbsp; private String url;<br>&nbsp; private String pageHeader;<br>&nbsp; public Pager(int offset, int size, int length, String url, String pageHeader) {<br>&nbsp;&nbsp;&nbsp; this.offset = offset;<br>&nbsp;&nbsp;&nbsp; this.size = size;<br>&nbsp;&nbsp;&nbsp; this.length = length;<br>&nbsp;&nbsp;&nbsp; this.url = url;<br>&nbsp;&nbsp;&nbsp; this.pageHeader = pageHeader;<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 返回分页导航条<br>&nbsp;&nbsp; * @param offset int 起始记录的位置<br>&nbsp;&nbsp; * @param size int 总记录数<br>&nbsp;&nbsp; * @param length int 步长<br>&nbsp;&nbsp; * @param url String .do的url<br>&nbsp;&nbsp; * @param pageHeader String 导航条的前缀文字提示<br>&nbsp;&nbsp; * @return String<br>&nbsp;&nbsp; */<br>&nbsp; public String getPageNavigation() {<br>&nbsp;&nbsp;&nbsp; String pageNavigation = ""; //最终返回的分页导航条<br>&nbsp;&nbsp;&nbsp; //记录数超过一页,需要分页<br>&nbsp;&nbsp;&nbsp; if (size &gt; length) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String pref; //前缀<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (url.indexOf("?") &gt; -1) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果url中已经包含了其他的参数,就把offset参数接在后面<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pref = "&amp;";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果url中没有别的参数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pref = "?";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果导航条包含header<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pageHeader != null &amp;&amp; pageHeader.length() &gt; 0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pageNavigation = pageHeader + " : ";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果不是第一页,导航条将包含&#8220;&lt;&lt;&#8221;(第一页)和&#8220;&lt;&#8221;(前一页)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (offset &gt; 0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pageNavigation += "&lt;a href='" + url + pref + "offset=0'&gt;[&lt;&lt;]&lt;/a&gt;\n" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;a href='" + url + pref + "offset=" + (offset - length) +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "'&gt;[&lt;]&lt;/a&gt;\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //导航条中,排头的那一页的offset值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int startOffset;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //位于导航条中间的那一页的offset值(半径)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int radius = constants.MAX_PAGE_INDEX / 2 * length;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果当前的offset值小于半径<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (offset &lt; radius || this.pageCount() &lt;= constants.MAX_PAGE_INDEX) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //那么第一页排头<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startOffset = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (offset &lt; size - radius) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startOffset = offset - radius;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startOffset = (size / length - constants.MAX_PAGE_INDEX) * length;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = startOffset;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i &lt; size &amp;&amp; i &lt; startOffset + constants.MAX_PAGE_INDEX * length;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i += length) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (i == offset) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //当前页号,加粗显示<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pageNavigation += "&lt;b&gt;" + (i / length + 1) + "&lt;/b&gt;\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //其他页号,包含超链接<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pageNavigation += "&lt;a href='" + url + pref + "offset=" + i + "'&gt;" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (i / length + 1) + "&lt;/a&gt;\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果不是最后一页,导航条将包含&#8220;&gt;&#8221;(下一页)和&#8220;&gt;&gt;&#8221;(最后一页)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (offset &lt; size - length) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pageNavigation += "&lt;a href='" + url + pref + "offset=" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (offset + length) + "'&gt;[&gt;]&lt;/a&gt;\n" +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;a href='" + url + pref + "offset=" + lastPageOffset() +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "'&gt;[&gt;&gt;]&lt;/a&gt;\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("radius : " + radius);<br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("start offset : " + startOffset);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return pageNavigation;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; //记录不超过一页,不需要分页<br>&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "";<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 返回分页后的总页数<br>&nbsp;&nbsp; * @param size int 总记录数<br>&nbsp;&nbsp; * @param length int 每页的记录数<br>&nbsp;&nbsp; * @return int<br>&nbsp;&nbsp; */<br>&nbsp; public int pageCount() {<br>&nbsp;&nbsp;&nbsp; int pagecount = 0;<br>&nbsp;&nbsp;&nbsp; if (size % length == 0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pagecount = size / length;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pagecount = size / length + 1;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return pagecount;<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 返回最后一页的记录数<br>&nbsp;&nbsp; * @param size int 总记录数<br>&nbsp;&nbsp; * @param length int 每页的记录数<br>&nbsp;&nbsp; * @return int<br>&nbsp;&nbsp; */<br>&nbsp; public int lastPageSize() {<br>&nbsp;&nbsp;&nbsp; int lastpagesize = 0;<br>&nbsp;&nbsp;&nbsp; if (size % length == 0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastpagesize = length;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastpagesize = size % length;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return lastpagesize;<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 返回最后一页的起始记录位置<br>&nbsp;&nbsp; * @param size int 总记录数<br>&nbsp;&nbsp; * @param length int 每页的记录数<br>&nbsp;&nbsp; * @return int<br>&nbsp;&nbsp; */<br>&nbsp; public int lastPageOffset() {<br>&nbsp;&nbsp;&nbsp; return size - lastPageSize();<br>&nbsp; }</p>
<p>&nbsp; public int getOffset() {<br>&nbsp;&nbsp;&nbsp; return offset;<br>&nbsp; }</p>
<p>&nbsp; public void setOffset(int offset) {<br>&nbsp;&nbsp;&nbsp; this.offset = offset;<br>&nbsp; }</p>
<p>&nbsp; public int getSize() {<br>&nbsp;&nbsp;&nbsp; return size;<br>&nbsp; }</p>
<p>&nbsp; public void setSize(int size) {<br>&nbsp;&nbsp;&nbsp; this.size = size;<br>&nbsp; }</p>
<p>&nbsp; public int getLength() {<br>&nbsp;&nbsp;&nbsp; return length;<br>&nbsp; }</p>
<p>&nbsp; public void setLength(int length) {<br>&nbsp;&nbsp;&nbsp; this.length = length;<br>&nbsp; }</p>
<p>&nbsp; public String getUrl() {<br>&nbsp;&nbsp;&nbsp; return url;<br>&nbsp; }</p>
<p>&nbsp; public void setUrl(String url) {<br>&nbsp;&nbsp;&nbsp; this.url = url;<br>&nbsp; }</p>
<p>&nbsp; public String getPageHeader() {<br>&nbsp;&nbsp;&nbsp; return pageHeader;<br>&nbsp; }</p>
<p>&nbsp; public void setPageHeader(String pageHeader) {<br>&nbsp;&nbsp;&nbsp; this.pageHeader = pageHeader;<br>&nbsp; }<br>}</p>
<p>********数据处理类empDAO.java，负责访问DB，获取当前页面需要显示的记录********</p>
<p>package page;</p>
<p>import java.sql.*;<br>import java.util.*;</p>
<p>public class empDAO {<br>&nbsp; public empDAO() {<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 从offset位置起始,返回length条记录<br>&nbsp;&nbsp; * @param offset int 起始的记录位置<br>&nbsp;&nbsp; * @param length int 步长<br>&nbsp;&nbsp; * @param conn Connection 数据库连接<br>&nbsp;&nbsp; * @return ArrayList<br>&nbsp;&nbsp; */<br>&nbsp; public ArrayList findAllEmp(int offset, int length, Connection conn) throws<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SQLException {<br>&nbsp;&nbsp;&nbsp; PreparedStatement ps = null;<br>&nbsp;&nbsp;&nbsp; ResultSet rs = null;<br>&nbsp;&nbsp;&nbsp; ArrayList emps = new ArrayList();<br>&nbsp;&nbsp;&nbsp; empVO empvo = null;<br>&nbsp;&nbsp;&nbsp; String strSql = "select empno, ename from emp where rowid not in (select rowid from emp where rownum &lt;= ?) and rownum &lt;= ?";<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ps = conn.prepareStatement(strSql);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ps.setInt(1, offset); //起始记录的位置<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ps.setInt(2, length); //步长<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rs = ps.executeQuery();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (rs != null &amp;&amp; rs.next()) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; empvo = new empVO();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; empvo.setEmpno(rs.getInt("empno"));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; empvo.setEname(rs.getString("ename"));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; emps.add(empvo);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (SQLException ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ex.printStackTrace();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw ex;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return emps;<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 返回总的记录数<br>&nbsp;&nbsp; * @param conn Connection<br>&nbsp;&nbsp; * @throws SQLException<br>&nbsp;&nbsp; * @return int<br>&nbsp;&nbsp; */<br>&nbsp; public int getRsTotalCount(Connection conn) throws SQLException {<br>&nbsp;&nbsp;&nbsp; PreparedStatement ps = null;<br>&nbsp;&nbsp;&nbsp; ResultSet rs = null;<br>&nbsp;&nbsp;&nbsp; int rsCount = 0;<br>&nbsp;&nbsp;&nbsp; String strSql = "select count(empno) as empCount from emp";<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ps = conn.prepareStatement(strSql);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rs = ps.executeQuery();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (rs != null &amp;&amp; rs.next()) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rsCount = rs.getInt("empCount");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (SQLException ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ex.printStackTrace();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw ex;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return rsCount;<br>&nbsp; }<br>}</p>
<p>********业务类empBO.java，调用empDAO类********</p>
<p>package page;</p>
<p>import java.util.*;</p>
<p>/**<br>&nbsp;* BO类<br>&nbsp;* &lt;p&gt;Title: 分页&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Description: &lt;/p&gt;<br>&nbsp;* &lt;p&gt;Copyright: Copyright (c) 2005&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Company: BCS&lt;/p&gt;<br>&nbsp;* @author Alex<br>&nbsp;* @version 1.0<br>&nbsp;*/<br>public class empBO {<br>&nbsp; private DBPool db = DBPool.newInstance();<br>&nbsp; private empDAO empdao = new empDAO();</p>
<p>&nbsp; public empBO() {<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 从offset位置起始,返回length条记录<br>&nbsp;&nbsp; * @param offset int 起始<br>&nbsp;&nbsp; * @param length int 步长<br>&nbsp;&nbsp; * @throws Exception<br>&nbsp;&nbsp; * @return ArrayList<br>&nbsp;&nbsp; */<br>&nbsp; public ArrayList findAllEmp(int offset, int length) throws Exception {<br>&nbsp;&nbsp;&nbsp; ArrayList emps = new ArrayList();<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; emps = empdao.findAllEmp(offset, length, db.getConnection());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (Exception ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw ex;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; finally {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db.release();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return emps;<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 返回总的记录数<br>&nbsp;&nbsp; * @throws Exception<br>&nbsp;&nbsp; * @return int<br>&nbsp;&nbsp; */<br>&nbsp; public int getRsTotalCount() throws Exception {<br>&nbsp;&nbsp;&nbsp; int rsCount = 0;<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rsCount = empdao.getRsTotalCount(db.getConnection());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (Exception ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw ex;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; finally {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db.release();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return rsCount;<br>&nbsp; }<br>}</p>
<p><br>********ActionForm类empForm.java********</p>
<p>package page;</p>
<p>import javax.servlet.http.*;</p>
<p>import org.apache.struts.action.*;</p>
<p>public class empForm<br>&nbsp;&nbsp;&nbsp; extends ActionForm {<br>&nbsp; private int offset; //起始记录的位置//每页显示的记录数<br>&nbsp; public ActionErrors validate(ActionMapping actionMapping,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest httpServletRequest) {<br>&nbsp;&nbsp;&nbsp; <a>/**@todo</a>: finish this method, this is just the skeleton.*/<br>&nbsp;&nbsp;&nbsp; return null;<br>&nbsp; }</p>
<p>&nbsp; public void reset(ActionMapping actionMapping,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest httpServletRequest) {<br>&nbsp;&nbsp;&nbsp; this.offset = 0; //记录默认从第一条开始显示<br>&nbsp; }</p>
<p>&nbsp; public int getOffset() {<br>&nbsp;&nbsp;&nbsp; return offset;<br>&nbsp; }</p>
<p>&nbsp; public void setOffset(int offset) {<br>&nbsp;&nbsp;&nbsp; this.offset = offset;<br>&nbsp; }</p>
<p>}</p>
<p><br>********Action类empAction.java，控制器，调用BO类，Pager类********</p>
<p>package page;</p>
<p>import java.util.*;<br>import javax.servlet.http.*;</p>
<p>import org.apache.struts.action.*;</p>
<p>/**<br>&nbsp;* 分页测试的Action<br>&nbsp;* &lt;p&gt;Title: 分页&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Description: &lt;/p&gt;<br>&nbsp;* &lt;p&gt;Copyright: Copyright (c) 2005&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Company: BCS&lt;/p&gt;<br>&nbsp;* @author Alex<br>&nbsp;* @version 1.0<br>&nbsp;*/<br>public class empAction<br>&nbsp;&nbsp;&nbsp; extends Action {</p>
<p>&nbsp; public ActionForward execute(ActionMapping actionMapping,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ActionForm actionForm,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest httpServletRequest,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse httpServletResponse) {<br>&nbsp;&nbsp;&nbsp; empForm empform = (empForm) actionForm;<br>&nbsp;&nbsp;&nbsp; return performList(actionMapping, actionForm, httpServletRequest,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpServletResponse);<br>&nbsp; }</p>
<p>&nbsp; private ActionForward performList(ActionMapping actionMapping,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ActionForm actionForm,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest request,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse response) {<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; empBO empbo = new empBO();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //获取外部传进来的起始记录号<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int offset = ( (empForm) actionForm).getOffset();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //获取每页的记录数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int pagesize = constants.PAGE_SIZE;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //获取记录集合,从offset开始,取length条记录<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ArrayList emps = empbo.findAllEmp(offset, pagesize);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //计算所有记录的条数(总记录数)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int size = empbo.getRsTotalCount();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //外部url地址,得到形如: <a href="http://localhost:8088/bugMIS/showlist.do">http://localhost:8088/bugMIS/showlist.do</a> 的String<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String url = request.getContextPath() + actionMapping.getPath() + ".do";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实例化分页类<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pager p = new Pager(offset, size, pagesize, url, "Page Navigation");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //获取分页导航条<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //String pageNavigation = p.getPageNavigation();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //将url字符串和记录集合,存入request中<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.setAttribute("pager", p);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.setAttribute("emps", emps);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return actionMapping.findForward("failure");<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return actionMapping.findForward("success");<br>&nbsp; }<br>}</p>
<p><br>********数据库连接池类DBPool.java，可以使用tomcat的连接池，也可以不用，这里关闭了********</p>
<p>package page;</p>
<p>import java.sql.*;<br>import javax.naming.*;<br>import javax.sql.*;</p>
<p>import org.apache.commons.logging.*;</p>
<p>/**<br>&nbsp;* 系统连接池类<br>&nbsp;* &lt;p&gt;Title: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#71;&#97;&#110;&#116;&#111;&#111;&#64;&#57;&#49;&#46;&#99;&#111;&#109;&#60;&#47;&#112;">
Gantoo@91.com&lt;/p</a>&gt;<br>&nbsp;* &lt;p&gt;Description: &lt;/p&gt;<br>&nbsp;* &lt;p&gt;Copyright: Copyright (c) 2005&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Company: BCS&lt;/p&gt;<br>&nbsp;* @author Alex<br>&nbsp;* @version 1.0<br>&nbsp;*/<br>public class DBPool {<br>&nbsp; Log log = LogFactory.getLog("DBPool"); //日志机<br>&nbsp; private DBPool() {<br>&nbsp; }</p>
<p>&nbsp; private Connection conn = null;</p>
<p>&nbsp; /* true:使用连接池<br>&nbsp;&nbsp;&nbsp;&nbsp; false:不使用连接池,采用JDBC直接连接 */<br>&nbsp; private final static boolean USE_DB_POOL = false;<br>&nbsp; private final static String jndi_DataSource = "jdbc/BugMIS_ora";<br>&nbsp; private final static String jdbcdriver =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "oracle.jdbc.driver.OracleDriver";<br>&nbsp; private final static String url =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "jdbc:oracle:thin:@localhost:1521:myo9";<br>&nbsp; private final static String user = "scott";<br>&nbsp; private final static String pass = "tiger";</p>
<p>&nbsp; public static DBPool newInstance() {<br>&nbsp;&nbsp;&nbsp; return new DBPool();<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 切换是否使用连接池<br>&nbsp;&nbsp; * */<br>&nbsp; public Connection getConnection() {<br>&nbsp;&nbsp;&nbsp; if (USE_DB_POOL) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn = getConnectionByDBPool();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn = getConnectionDirect();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return conn;<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 直接采用JDBC连接数据库<br>&nbsp;&nbsp; * */<br>&nbsp; private Connection getConnectionDirect() {<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class.forName(jdbcdriver).newInstance();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn = DriverManager.getConnection(url, user, pass);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (SQLException ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("Error Connection! " + ex.getMessage());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (ClassNotFoundException ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("Driver Not Found! " + ex.getMessage());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (IllegalAccessException ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error(ex.getMessage());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (InstantiationException ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error(ex.getMessage());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return conn;<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 采用连接池<br>&nbsp;&nbsp; * */<br>&nbsp; private Connection getConnectionByDBPool() {<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Context initCtx = new InitialContext();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Context ctx = (Context) initCtx.lookup("java:/comp/env");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataSource ds = (DataSource) ctx.lookup(jndi_DataSource);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn = ds.getConnection();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (NamingException ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("Data Source Not Found! " + ex.getMessage());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //System.out.println("未找到数据源" + ex.getMessage());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (SQLException ex1) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("Error Connection! " + ex1.getMessage());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //System.out.println("错误的数据连接" + ex1.getMessage());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return conn;<br>&nbsp; }</p>
<p>&nbsp; /**<br>&nbsp;&nbsp; * 释放连接<br>&nbsp;&nbsp; * */<br>&nbsp; public void release() {<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!conn.isClosed()) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (SQLException ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("Connection Closing Error! " + ex.getMessage());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //System.out.println("连接关闭失败" + ex.getMessage());<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>}</p>
<p><br>********包含常量的类constants.java，常量********</p>
<p>package page;</p>
<p>/**<br>&nbsp;* 定义工程中公用的常量<br>&nbsp;* &lt;p&gt;Title: 分页&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Description: &lt;/p&gt;<br>&nbsp;* &lt;p&gt;Copyright: Copyright (c) 2005&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Company: BCS&lt;/p&gt;<br>&nbsp;* @author Alex<br>&nbsp;* @version 1.0<br>&nbsp;*/<br>public final class constants {<br>&nbsp; public static final int MAX_PAGE_INDEX = 5; //页脚显示多少页<br>&nbsp; public static final int PAGE_SIZE = 2; //每页的记录数<br>}</p>
<p><br>********测试jsp页面index.jsp，为了方便测试，嵌入了java代码，能显示就行********</p>
<p>&lt;%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %&gt;<br>&lt;%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %&gt;<br>&lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&gt;<br>&lt;%@ page contentType="text/html; charset=GBK" import="java.util.*,page.*"%&gt;<br>&lt;html:html&gt;<br>&lt;head&gt;<br>&lt;title&gt;&lt;/title&gt;<br>&lt;style type="text/css"&gt;<br>.pt9 {&nbsp; font: 10pt "宋体"}<br>body { font: 10pt "宋体" ; margin: 15px}<br>td {&nbsp; font-size: 10pt}<br>a:hover {&nbsp; font-size: 10pt; color: red; text-decoration: underline}<br>a:link {&nbsp; font-size: 10pt; color: blue; text-decoration: underline}<br>a:active {&nbsp; font-size: 10pt; color: blue; text-decoration: underline}<br>a:visited { font-size: 10pt; color: blue; text-decoration: underline }<br>&lt;/style&gt;<br>&lt;/head&gt;<br>&lt;body bgcolor="#ffffff"&gt;</p>
<p>&lt;p&gt;&lt;a href="<a href='http://localhost:8088/page/showEmp.do?offset=0">Show'>http://localhost:8088/page/showEmp.do?offset=0"&gt;Show</a> Me All Of The Emps&lt;/a&gt;&lt;/p&gt;</p>
<p>&lt;logic:present name="emps"&gt;<br>&nbsp; &lt;%<br>&nbsp; ArrayList emps = (ArrayList)request.getAttribute("emps");<br>&nbsp; Iterator it = emps.iterator();<br>&nbsp; empVO empvo;<br>&nbsp; while(it!=null &amp;&amp; it.hasNext()){<br>&nbsp;&nbsp;&nbsp; empvo = (empVO)it.next();<br>&nbsp;&nbsp;&nbsp; out.print(empvo.getEmpno() + "&nbsp; ");<br>&nbsp;&nbsp;&nbsp; out.print(empvo.getEname() + "&lt;br&gt;");<br>&nbsp; }<br>&nbsp;&nbsp;&nbsp; out.print("当前页有 " + emps.size() + " 条记录&lt;br&gt;");<br>&nbsp;&nbsp;&nbsp; out.print("&lt;p&gt;");<br>&nbsp; %&gt;<br>&lt;/logic:present&gt;</p>
<p>&lt;logic:present name="pager"&gt;<br>&nbsp; &lt;%<br>&nbsp; Pager pager = (Pager)request.getAttribute("pager");<br>&nbsp; out.print(pager.getPageNavigation() + "&lt;p&gt;");<br>&nbsp; out.print("共有记录 " + pager.getSize() + " 条&lt;br&gt;");<br>&nbsp; out.print("每页有 " + pager.getLength() + " 条记录&lt;br&gt;");<br>&nbsp; out.print("共分 " + pager.pageCount() + " 页&lt;br&gt;");<br>&nbsp; %&gt;<br>&lt;/logic:present&gt;<br>&lt;/body&gt;<br>&lt;/html:html&gt;</p>
<p>********配置文件struts-config.xml********</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>&lt;!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "<a href="http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd</a>"&gt;<br>&lt;struts-config&gt;<br>&nbsp; &lt;form-beans&gt;<br>&nbsp;&nbsp;&nbsp; &lt;form-bean name="empForm" type="page.empForm" /&gt;<br>&nbsp; &lt;/form-beans&gt;<br>&nbsp; &lt;action-mappings&gt;<br>&nbsp;&nbsp;&nbsp; &lt;action input="/index.jsp" name="empForm" path="/showEmp" scope="request" type="page.empAction" validate="false"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;forward name="faiure" path="/index.jsp" /&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;forward name="success" path="/index.jsp" /&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/action&gt;<br>&nbsp; &lt;/action-mappings&gt;<br>&lt;/struts-config&gt;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br>在网上看了几个Structs分页，感觉不是很完善，于是根据自己的经验，写了一个相对高效简洁的分页方法。由于本人水平有限，如果大家有什么更好的想法，欢迎不吝赐教。<br>　　<br>　　一、 开发环境<br>　　<br>　　我的开发环境是：JBuilder x + Weblogic 8.1 + Oracle 9i + Windows 2003 ，如果朋友们的开发环境不一样亦无妨。<br>　　<br>　　二、开发思路<br>　　<br>　　既然讲的是Struts，那自然离不了MVC，分页显示也是如此。<br>　　<br>　　1、 建立数据库和对应的表，本例的表是TCertificate。<br>　　<br>　　2、 建立适当的模型组件，对应你要查询数据库中的表。这部分由DAO数据访问层来实现，如果有的朋友对DAO不熟悉可以查询一下相关资料。本例由CertificateDAO.java来实现。<br>　　<br>　　3 、建立分页所需要的模型组件，由javaBean来充当，并与CertificateDAO实现分离。网上介绍的很多方法，都存在着数据与分页组件藕合的现象，这也是本方法与其它分页方法的主要不同之处。<br>　　<br>　　4、建立控制器组件，这部分由Struts 中的Action来实现。主要负责将实例化CertificateDAO，只取要显示的数据记录，存入ArrayList对象然后返回，并放到request中。而分页部分则根据分页条件，单独进行构造，避免了与DAO混在一起的情况发生。网上其它介绍的一些分页方法中，基本上都是一次性读出所有查询的数据，然后再由分页相关组件进行构造。这样，如果数据量大的话，很容易形成瓶颈。在本例中由于不是一次性地读出查询的所有数据，而只是读出一个页面要显示的数据记录，这就节省了很多不必要的数据传输，提高了效率。本例中为CertificateAction.java。<br>　　<br>　　5、建立视图组件，这部分由jsp来充当，为了不出现java 代码，我们使用Struts提供的标签库，主要负责从request中取出刚刚放入的对象，通过反复调用CertificateAction以及action参数，而实现分页显示。本例中为listcertificate.jsp。<br>　　<br>　　6、 建立并配置struts-config.xml。<br>　　<br>　　三、实例代码<br>　　<br>　　确定好上面的开发思路后，代码的实现就有单可循了。<br>　　<br>　　1、建数据库和相应的表。<br>　　<br>　　2、数据逻辑层的相关代码。<br>　　<br>　　1）、通用的DAO类：CommonDAO.java<br>　　<br>　　这是一个很多DAO都要继承到的通用DAO类，是我根据实践总结出来的，为了减少篇幅，这里只显示和本例相关的代码。<br>　　<br>　　java代码:<br>　　<br>　　代码：<br>　　--------------------------------------------------------------------------------<br>　　package com.xindeco.business ;<br>　　import java.io.*;<br>　　import java.sql.*;<br>　　import java.util.*;<br>　　import javax.sql.*;<br>　　import java.lang.IllegalAccessException;<br>　　import java.lang.reflect.InvocationTargetException;<br>　　import org.apache.commons.beanutils.BeanUtils;<br>　　public class DAO<br>　　{<br>　　protected DataSource ds;<br>　　/**<br>　　* 说明:取得当前查询的总记录数<br>　　*/<br>　　public int getRows ()<br>　　{<br>　　return this.count;<br>　　}<br>　　public void rsHandler (ResultSet rs, int offset, int limit)<br>　　{<br>　　try<br>　　{<br>　　count = 0;<br>　　rs.absolute ( -1) ;<br>　　count = rs.getRow () ;<br>　　if (offset &lt;= 0)<br>　　{<br>　　rs.beforeFirst () ;<br>　　}<br>　　else<br>　　{<br>　　rs.absolute (offset) ;<br>　　}<br>　　}<br>　　catch (Exception e)<br>　　{<br>　　e.printStackTrace () ;<br>　　}<br>　　}<br>　　public DAO(DataSource ds) {<br>　　this.ds = ds;<br>　　}<br>　　<br>　　public void setDataSource(DataSource ds) {<br>　　this.ds = ds;<br>　　}<br>　　<br>　　protected void close(ResultSet rs) {<br>　　if (rs != null) {<br>　　try {<br>　　rs.close();<br>　　} catch (SQLException e) {<br>　　}<br>　　rs = null;<br>　　}<br>　　}<br>　　<br>　　protected void close(PreparedStatement pstmt) {<br>　　if (pstmt != null) {<br>　　try {<br>　　pstmt.close();<br>　　} catch (SQLException e) {<br>　　}<br>　　pstmt = null;<br>　　}<br>　　}<br>　　protected void close(Connection conn) {<br>　　if (conn != null) {<br>　　try {<br>　　conn.close();<br>　　} catch (SQLException e) {<br>　　e.printStackTrace();<br>　　}<br>　　conn = null;<br>　　}<br>　　}<br>　　<br>　　protected void rollback(Connection conn) {<br>　　if (conn != null) {<br>　　try {<br>　　conn.rollback();<br>　　} catch (SQLException e) {<br>　　e.printStackTrace();<br>　　}<br>　　conn = null;<br>　　}<br>　　}<br>　　}<br>　　<br>　　这个类主要是通过子类传进来的先进结果集，取得查询的记录总数，并对数据库连接进行简单的管理。<br>　　<br>　　2）、对数据库进行访问：CertificateDAO.java<br>　　<br>　　java代码:<br>　　<br>　　代码：<br>　　--------------------------------------------------------------------------------<br>　　package com.xindeco.business;<br>　　<br>　　import java.io.*;<br>　　import java.sql.*;<br>　　import java.util.*;<br>　　import javax.sql.*;<br>　　<br>　　import com.xindeco.common.dbconn.DbConn;<br>　　<br>　　public class CertificateDAO extends DAO<br>　　{<br>　　<br>　　public NationDAO(DataSource ds) {<br>　　super(ds);<br>　　}<br>　　<br>　　public List findCertificateList(int offset,int limit) throws SQLException<br>　　{<br>　　int countRows = 0 ;<br>　　ArrayList list = null ;<br>　　Connection conn = null;<br>　　PreparedStatement pstmt = null;<br>　　ResultSet rs = null;<br>　　try<br>　　{<br>　　conn = ds.getConnection();<br>　　String sql =<br>　　"SELECT certificateID, certificateCode,certificateName,photoURL,"<br>　　+ "description,graduateID FROM TCertificate " ;<br>　　pstmt = conn.prepareStatement(sql);<br>　　rs = pstmt.executeQuery();<br>　　/*对游标进行处理，rsHandler 方法在父类DAO中*/<br>　　this.rsHandler(rs,offset,limit);<br>　　if (rs != null &amp;&amp; rs.next ())<br>　　{<br>　　list = new ArrayList () ;<br>　　do<br>　　{<br>　　countRows++ ;<br>　　list.add (rs2VO (rs)) ;<br>　　}<br>　　while ( (countRows++ &lt; limit) &amp;&amp; rs.next ()) ;<br>　　}<br>　　close(rs);<br>　　close(pstmt);<br>　　} catch (SQLException e) {<br>　　close(rs);<br>　　close(pstmt);<br>　　rollback(conn);<br>　　e.printStackTrace();<br>　　}<br>　　finally {<br>　　close(conn);<br>　　}<br>　　return list ;<br>　　}<br>　　<br>　　private CertificateVO rs2VO (ResultSet rs)<br>　　{<br>　　try<br>　　{<br>　　CertificateVO certificateVO = new CertificateVO () ;<br>　　certificateVO.setCertificateID (rs.getInt ("certificateID")) ;<br>　　certificateVO.setCertificateCode (rs.getString ("certificateCode")) ;<br>　　certificateVO.setCertificateName (rs.getString ("certificateName")) ;<br>　　certificateVO.setPhotoURL (rs.getString ("photoURL")) ;<br>　　certificateVO.setDescription (rs.getString ("description")) ;<br>　　certificateVO.setGraduateID (rs.getInt ("graduateID")) ;<br>　　return certificateVO ;<br>　　}<br>　　catch (Exception ex)<br>　　{<br>　　ex.printStackTrace () ;<br>　　return null ;<br>　　}<br>　　}<br>　　}<br>　　<br>　　findCertificateList(int offset,int limit)是查得所有要显示的数据，并放入ArrayList中。看过网上有些例子，把数据记录放入ArrayList的动作过程直接在while循环体里完成，如果字段多的话，会造成方法过于宠大，又不美观。 这里，数据记录放入ArrayList的动作过程由rs2VO方法完成，就比较整洁了。另外，if (rs != null &amp;&amp; rs.next ()) 配合while ( (countRows++ &lt; limit) &amp;&amp; rs.next ()) 是为了程序的健壮性考虑的，稍分析一下不难得出结论。<br>　　<br>　　3、建立控制器组件：CertificateAction.java<br>　　<br>　　java代码:<br>　　<br>　　代码：<br>　　--------------------------------------------------------------------------------<br>　　package com.xindeco.presentation;<br>　　<br>　　import javax.sql.* ;<br>　　import java.util.* ;<br>　　<br>　　import javax.servlet.http.* ;<br>　　import javax.servlet.* ;<br>　　<br>　　import org.apache.struts.action.* ;<br>　　import org.apache.struts.util.* ;<br>　　<br>　　import com.xindeco.common.Pager;<br>　　import com.xindeco.business.graduatedata.CertificateDAO ;<br>　　<br>　　public class CertificateAction<br>　　extends Action<br>　　{<br>　　private static final int PAGE_LENGTH = 5 ; //每页显示5条记录<br>　　public ActionForward execute (ActionMapping mapping, Actionform form,<br>　　HttpServletRequest request,<br>　　HttpServletResponse response)<br>　　{<br>　　ActionForward myforward = null ;<br>　　String myaction = mapping.getParameter () ;<br>　　<br>　　if (isCancelled (request))<br>　　{<br>　　return mapping.findForward ("failure") ;<br>　　}<br>　　if ("".equalsIgnoreCase (myaction))<br>　　{<br>　　myforward = mapping.findForward ("failure") ;<br>　　}<br>　　else if　　　　("LIST".equalsIgnoreCase (myaction))<br>　　{<br>　　myforward = performList (mapping, form, request, response) ;<br>　　}<br>　　else<br>　　{<br>　　myforward = mapping.findForward ("failure") ;<br>　　}<br>　　return myforward ;<br>　　}<br>　　<br>　　private ActionForward performList (ActionMapping mapping,<br>　　Actionform actionform,<br>　　HttpServletRequest request,<br>　　HttpServletResponse response)<br>　　{<br>　　try<br>　　{<br>　　DataSource ds = (DataSource) servlet.getServletContext().getAttribute(Action.DATA_SOURCE_KEY);<br>　　<br>　　CertificateDAO　 certificateDAO　= new CertificateDAO　(ds) ;<br>　　<br>　　int offset = 0;　 //翻页时的起始记录所在游标<br>　　int length = PAGE_LENGTH;<br>　　String pageOffset = request.getParameter("pager.offset");<br>　　if (pageOffset == null || pageOffset.equals("")) {<br>　　offset = 0;<br>　　} else {<br>　　offset = Integer.parseInt(pageOffset);<br>　　}<br>　　List certificateList = certificateDAO .findCertificateList (offset,length) ;<br>　　int size = certificateDAO.getRows(); //　取得总记录数<br>　　String url = request.getContextPath()+"/"+mapping.getPath()+".do";<br>　　String pagerHeader = Pager.generate(offset, size, length, url); //分页处理<br>　　<br>　　request.setAttribute ("pager", pagerHeader) ;<br>　　request.setAttribute ("list", certificateList) ;<br>　　}<br>　　catch (Exception e)<br>　　{<br>　　e.printStackTrace();<br>　　return mapping.findForward ("error") ;<br>　　}<br>　　return mapping.findForward ("success") ;<br>　　}<br>　　}<br>　　<br>　　CertificateAction.java主要是把数据从DAO中取出，并放入一个ArrayList 中，然后通过配置文件再软件View的JSP页。<br>　　<br>　　5、建立视图listcertificate.jsp文件。<br>　　<br>　　jsp代码:<br>　　<br>　　代码：<br>　　--------------------------------------------------------------------------------<br>　　<br>　　&lt;%@ page contentType="text/html; charset=GBK" %&gt;<br>　　&lt;%@ taglib uri="/WEB-INF/struts-template.tld" prefix="template" %&gt;<br>　　&lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&gt;<br>　　&lt;%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %&gt;<br>　　&lt;%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %&gt;<br>　　<br>　　&lt;table bgcolor="#666666" cellpadding="1" cellspacing="0" border="0" width="500"&gt;<br>　　&lt;tr&gt;<br>　　&lt;td&gt;<br>　　&lt;table cellpadding="0" cellspacing="0" border="0" width="500"&gt;<br>　　&lt;tr&gt;<br>　　&lt;td bgcolor="#fecc51"&gt;&amp;&lt;/td&gt;<br>　　&lt;/tr&gt;<br>　　&lt;/table&gt;<br>　　&lt;/td&gt;<br>　　&lt;/tr&gt;<br>　　&lt;tr&gt;<br>　　&lt;td&gt;<br>　　&lt;table cellpadding="0" cellspacing="0" border="0" width="500"&gt;<br>　　&lt;tr&gt;<br>　　&lt;td bgcolor="#d6e0ed"&gt;<br>　　&amp;&amp;&lt;bean:message key="label.list4certificate"/&gt;<br>　　&lt;/td&gt;<br>　　&lt;/tr&gt;<br>　　&lt;tr bgcolor="#FFFFFF"&gt;<br>　　&lt;td width="5%"&gt;&lt;/td&gt;&lt;td width="19%"&gt;&lt;/td&gt;&lt;td width="76%"&gt;&lt;/td&gt;<br>　　&lt;/tr&gt;<br>　　&lt;tr&gt;<br>　　&lt;td&gt;<br>　　&lt;table bgcolor="#f2f2f2" width="500" cellspacing="0" border="0"&gt;<br>　　&lt;tr bgcolor="#bacce1"&gt;<br>　　&lt;td&gt;&lt;b&gt;&lt;bean:message key="Certificate.select"/&gt; &lt;/b&gt;&lt;/td&gt;<br>　　&lt;td&gt;&lt;b&gt;&lt;bean:message key="Certificate.certificateID"/&gt; &lt;/b&gt;&lt;/td&gt;<br>　　&lt;td&gt;&lt;b&gt;&lt;bean:message key="Certificate.certificateCode"/&gt;&lt;/b&gt;&lt;/td&gt;<br>　　&lt;td&gt;&lt;b&gt;&lt;bean:message key="Certificate.certificateName"/&gt;&lt;/b&gt;&lt;/td&gt;<br>　　&lt;td&gt;&lt;b&gt;&lt;bean:message key="Certificate.view"/&gt;&lt;/b&gt;&lt;/td&gt;<br>　　&lt;/tr&gt;<br>　　<br>　　&lt;bean:write name="pager" property="description"/&gt;<br>　　&lt;logic:equal name="pager" property="hasPrevious" value="true"&gt;<br>　　&lt;a href="/graduatedata/list.do?viewPage=&lt;bean:write name="pager" property="previousPage"/&gt;" class="a02"&gt;<br>　　Previous<br>　　&lt;/a&gt;<br>　　&lt;/logic:equal&gt;<br>　　&lt;logic:equal name="pager" property="hasNext" value="true"&gt;<br>　　&lt;a href="/graduatedata/list.do?viewPage=&lt;bean:write name="pager" property="nextPage"/&gt;" class="a02"&gt;<br>　　Next<br>　　&lt;/a&gt;<br>　　&lt;/logic:equal&gt;<br>　　<br>　　&lt;logic:notEmpty name="list" scope="request"&gt;<br>　　&lt;logic:iterate id="certificate" name="list" type="com.xindeco.business.graduatedata.CertificateVO"scope="request"&gt;<br>　　&lt;tr bgcolor="#FFFFFF"&gt;<br>　　&lt;td&gt;&lt;html:text property="name" value="&lt;bean:write name="certificate" property="certificateID" scope="page"/&gt;"/&gt;<br>　　&lt;/td&gt;<br>　　&lt;td&gt; &lt;bean:write name="certificate" property="certificateID" scope="page"/&gt;&lt;/td&gt;<br>　　&lt;td&gt; &lt;bean:write name="certificate" property="certificateCode" scope="page"/&gt;&lt;/td&gt;<br>　　&lt;td&gt; &lt;bean:write name="certificate" property="certificateName" scope="page"/&gt;&lt;/td&gt;<br>　　&lt;td&gt; &lt;bean:write name="certificate" property="photoURL" scope="page"/&gt;&lt;/td&gt;<br>　　&lt;/tr&gt;<br>　　&lt;/logic:iterate&gt;<br>　　&lt;/logic:notEmpty&gt;<br>　　&lt;/table&gt;<br>　　&lt;/td&gt;<br>　　&lt;/tr&gt;<br>　　&lt;/table&gt;<br>　　&lt;/td&gt;<br>　　&lt;/tr&gt;<br>　　&lt;/table&gt;<br>　　<br>　　6、对应的配置文件struts-config.xml。<br>　　<br>　　java代码:<br>　　<br>　　代码：<br>　　--------------------------------------------------------------------------------<br>　　&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>　　&lt;!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "<a href="http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd</a>"&gt;<br>　　&lt;struts-config&gt;<br>　　&lt;form-beans&gt;<br>　　&lt;form-bean name="certificateform" type="com.xindeco.presentation.graduatedata.Certificateform" /&gt;<br>　　&lt;/form-beans&gt;<br>　　&lt;global-forwards&gt;<br>　　&lt;forward name="error" path="/error/error.jsp" /&gt;<br>　　&lt;/global-forwards&gt;<br>　　&lt;action-mappings&gt;<br>　　&lt;action name="certificateform" parameter="LIST" path="/graduatedata/list" scope="request" type="com.xindeco.presentation.graduatedata.CertificateAction" validate="true"&gt;<br>　　&lt;forward name="success" path="/graduatedata/listcertificate.jsp" /&gt;<br>　　&lt;/action&gt;<br>　　&lt;/action-mappings&gt;<br>　　&#8230;&#8230;<br>　　&lt;/struts-config&gt;<br>　　<br>　　7、最后当然是最重要的分页代码了：Pager.java<br>　　<br>　　java代码:<br>　　<br>　　代码：<br>　　--------------------------------------------------------------------------------<br>　　package com.xindeco.common;<br>　　<br>　　import java.util.* ;<br>　　public class Pager {<br>　　private static int MAX_PAGE_INDEX = 10; //页脚显示多少页<br>　　private static String HEADER = "Result page";<br>　　<br>　　public static String generate(int offset, int length, int size, String url) {<br>　　if (length &gt; size) {<br>　　String pref;<br>　　if (url.indexOf("?") &gt; -1) {<br>　　pref = "&amp;";<br>　　} else {<br>　　pref = "?";<br>　　}<br>　　String header = "&lt;font face='Helvetica' size='-1'&gt;"+HEADER+": ";<br>　　if (offset &gt; 0) {<br>　　header += "&amp;&lt;a href=\""+url+pref+"pager.offset="+(offset-size)+"\"&gt;[&lt;&lt; Prev]&lt;/a&gt;\n";<br>　　}<br>　　int start;<br>　　int radius = MAX_PAGE_INDEX/2*size;<br>　　if (offset &lt; radius) {<br>　　start = 0;<br>　　} else if(offset &lt; length-radius) {<br>　　start = offset - radius;<br>　　} else {<br>　　start = (length/size-MAX_PAGE_INDEX)*size;<br>　　}<br>　　for(int i=start;i&lt;length &amp;&amp; i &lt; start + MAX_PAGE_INDEX*size;i+=size) {<br>　　if (i == offset) {<br>　　header += "&lt;b&gt;"+(i/size+1)+"&lt;/b&gt;\n";<br>　　} else {<br>　　header += "&amp;&lt;a href=\""+url+pref+"pager.offset="+i+"\"&gt;"+(i/size+1)+"&lt;/a&gt;\n";<br>　　}<br>　　}<br>　　if(offset &lt; length - size) {<br>　　header += "&amp;&lt;a href=\""+url+pref+"pager.offset="+((int)offset+(int)size)+"\"&gt;[Next &gt;&gt;]&lt;/a&gt;\n";<br>　　}<br>　　header += "&lt;/font&gt;";<br>　　return header;<br>　　} else {<br>　　return "";<br>　　}<br>　　}<br>　　}<br>　　<br>　　这部分代码的实现相当简洁，但已经足够完成所需了。 </p>
<img src ="http://www.blogjava.net/wangyong/aggbug/133821.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangyong/" target="_blank">CoolYongZi</a> 2007-08-01 16:11 <a href="http://www.blogjava.net/wangyong/archive/2007/08/01/133821.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java连接到不同数据库</title><link>http://www.blogjava.net/wangyong/archive/2007/08/01/133819.html</link><dc:creator>CoolYongZi</dc:creator><author>CoolYongZi</author><pubDate>Wed, 01 Aug 2007 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/wangyong/archive/2007/08/01/133819.html</guid><wfw:comment>http://www.blogjava.net/wangyong/comments/133819.html</wfw:comment><comments>http://www.blogjava.net/wangyong/archive/2007/08/01/133819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangyong/comments/commentRss/133819.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangyong/services/trackbacks/133819.html</trackback:ping><description><![CDATA[<p>1、Oracle8/8i/9i数据库（thin模式） <br>Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <br>String url="jdbc:oracle:thin:@localhost:1521:orcl"; <br>//orcl为数据库的SID <br>String user="test"; <br>String password="test"; <br>Connection conn= DriverManager.getConnection(url,user,password); </p>
<p>2、DB2数据库 <br>Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); <br>String url="jdbc:db2://localhost:5000/sample"; <br>//sample为你的数据库名 <br>String user="admin"; <br>String password=""; <br>Connection conn= DriverManager.getConnection(url,user,password); </p>
<p>3、Sql Server7.0/2000数据库 <br>Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); <br>String url="jdbc:microsoft:sqlserver://localhost:1433;databasename=pubs"; <br>//mydb为数据库 <br>String user="sa"; <br>String password=""; <br>Connection conn= DriverManager.getConnection(url,user,password); </p>
<p>4、Sybase数据库 <br>Class.forName("com.sybase.jdbc.SybDriver").newInstance(); <br>String url =" jdbc:sybase:Tds:localhost:5007/myDB"; <br>//myDB为你的数据库名 <br>Properties sysProps = System.getProperties(); <br>SysProps.put("user","userid"); <br>SysProps.put("password","user_password"); <br>Connection conn= DriverManager.getConnection(url, SysProps); </p>
<p>5、Informix数据库 <br>Class.forName("com.informix.jdbc.IfxDriver").newInstance(); <br>String url = <br>"jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver; <br>user=testuser;password=testpassword"; <br>//myDB为数据库名 <br>Connection conn= DriverManager.getConnection(url); </p>
<p>6、MySQL数据库 <br>Class.forName("org.gjt.mm.mysql.Driver").newInstance(); <br>String url ="jdbc:mysql://localhost/myDB?user=soft&amp;password=soft1234&amp;useUnicode=true&amp;characterEncoding=8859_1" <br>//myDB为数据库名 <br>Connection conn= DriverManager.getConnection(url); </p>
<p>7、PostgreSQL数据库 <br>Class.forName("org.postgresql.Driver").newInstance(); <br>String url ="jdbc:postgresql://localhost/myDB" <br>//myDB为数据库名 <br>String user="myuser"; <br>String password="mypassword"; <br>Connection conn= DriverManager.getConnection(url,user,password); <br>8、access数据库<br>con = DriverManager.getConnection("jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ=C:/data/Access/test1.mdb","dba","sql");</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/wangyong/aggbug/133819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangyong/" target="_blank">CoolYongZi</a> 2007-08-01 16:02 <a href="http://www.blogjava.net/wangyong/archive/2007/08/01/133819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>